DDoS攻防战(三):ip黑白名单防火墙frdev的原理与实现
? 康誥曰 作新民
? 詩曰 周雖舊邦 其命維新
? 是故 君子無所不用其極?
——禮記·大學
?
?
? 在上一篇文章《DDoS攻防戰?(二)?:CC攻擊工具實現與防御理論》中,筆者闡述了一個防御狀態機,它可用來抵御來自應用層的DDoS攻擊,但是該狀態機依賴一個能應對大量條目快速增刪的ip黑白名單防火墻,我們目前并沒有發現很好的開源實現以供我們使用。
?
·實現方案選擇:
??硬件實現或者軟件實現?
??在面對諸如大量畸形包這樣的攻擊時,硬件實現將會是非常好的選擇,這是因為在進行此類型的封包過濾時,系統需要記憶的狀態很少(對于FPGA、ASIC諸多硬件實現方案來講,記憶元件的成本決不可忽視,寄存器與靜態RAM都非常昂貴,所以當需要記憶的信息很少時,純硬件方案的速度優勢使得其完勝軟件方案)。
??但是,當狀態機需要處理龐大的記憶信息時,我們就需要選擇廉價的存儲器——動態隨機存儲器(如SDRAM中的DDR3)來作為系統狀態機的存儲介質,以降低系統的成本和復雜度。這時,軟件實現更勝一籌。盡管純硬件實現的速度會比軟件的方式高出很多,但我們也從第一篇文章《DDoS攻防戰?(一)?:?概述》中lvs性能的測試結果中看到,軟件實現的、作為服務器前端均衡調度器的lvs,性能理想并且能勝任實際生產環境中的、龐大的用戶請求處理,可見,如果設計合理,軟件實現的性能無需過多擔憂。
??最終,我們決定采用軟件的方法來實現所需的ip黑白名單模塊。
?
·最終系統鳥瞰:
??筆者花費大約二十天的時間,使用C語言實現了這一模塊,其中,內核空間的核心代碼約2300行,用戶空間管理工具的代碼總行數約為700行。下為系統的鳥瞰:
??·用戶空間管理工具fripadm,通過ioctl與工作于內核態的frdev模塊進行通信
??·frdev維護兩個double_hash_table的實例,并提供了一個掛在NF_INET_PRE_ROUTING的鉤子函數,其通過操作這兩個double_hash_table的實例以分別實現ip黑名單、白名單的功能
??·frdev通過內核中設備驅動的ioctl機制,向用戶空間提供這兩個double_hash_table實例的操作函數,而我們的用戶空間管理工具fripadm正是基于此而實現的
??下面是內核態的主要數據結構與其對應的操作函數:
struct fr_ip_hash_array的功能:精確ip查詢;模糊ip查詢;自定義hash表的長度;自定義hash function,其輸入散列隨機數為rnd;維護精確ip的哈希表;維護模糊ip的鏈表;維護精確ip與模糊ip的諸統計信息;ip字符描述語法:/* ips_syntax : RE digit =: [0-9]num =: (digit){1,3}atom =: num | (num'-'num) | '*'ip =: atom '.' atom '.' atom '.' atom ips =: (ip ' ')+*/// ret 0 success,otherwise syntax error// "1-220.*.100.33 1-220.*.100.33 1-220.*.100.33"struct fr_ip_hash_array的方法:fr_ip_hash_array_malloc / fr_ip_hash_array_destroyfr_ip_hash_array_insert_ip :增加一條精確ip記錄fr_ip_hash_array_insert_blurip_ptr :增加一條模糊ip記錄(以指針引用的方式)fr_ip_hash_array_delete_ipfr_ip_hash_array_delete_blurip_ptrfr_ip_hash_array_delete_ip_randomly :隨機地刪除指定數量的精確ipfr_ip_hash_array_insert_ip_bystrings :通過字符串的表述方式,向fr_ip_hash_array增加精確ip或者模糊ipfr_ip_hash_array_delete_ip_bystringsfr_ip_hash_array_find_bool :查找給定的ip是否在已存儲的模糊ip范圍之內或者精確ip的哈希表之中fr_ip_hash_array_find_ip_bool :查找給定的ip是否在精確ip的哈希表之中fr_ip_hash_array_find_ip_bystrings_bool?
·為什么使用雙哈希表緩沖?
??請考慮如下場景:
??情況1:來自應用層的DDoS攻擊常常是瞬間涌入大量非法ip請求,例如數萬個非法ip,所以,對于防火墻黑白名單功能的要求至少有如下:能在很短的時間內更新大量數據項,且不能造成系統服務停頓。
??分析:如果只使用一個全局的哈希表,當在短時間內進行大量的數據項增刪時,例如,成千上萬個,此時,即使采用多把讀寫鎖分割哈希表的策略,對共享資源的競爭也依然將嚴重影響系統響應速度,嚴重時系統可能會停頓或者更糟,對于生產環境中的高負載服務器,這是無法容忍的。
??解決:以空間換時間
?
? 采用雙哈希表緩沖的策略,將系統共享資源的競爭熱點壓縮至兩個hash表指針主備切換的極短時間內,此方法能顯著降低系統在大量數據項更新時共享資源的競爭。
??系統查詢將會直接訪問master指向的fr_ip_hash_array,而用戶的更新操作將直接針對mirror所指向的另一個fr_ip_hash_array實例,直到switch_mirror_update操作的執行,master將被瞬間“更新”。這是其主要的工作特點。
??對于SMP與多隊列網卡的系統,可采用如下策略:多數cpu核心專門負責處理內核的softirq任務,剩下的少數cpu負責進行雙哈希表的更新、切換與重建等操作。這樣可提高系統對攻擊的快速防御響應。
??但此方案將使得系統需要維護兩個互為鏡像的哈希表,這將加重系統內存的讀寫負擔。
??具體實現細節如下:
struct fr_ip_double_hash的成員:struct fr_ip_hash_array * master_ptr;rwlock_t master_lock; struct fr_ip_hash_array * mirror_ptr;rwlock_t mirror_lock;struct fr_ip_double_hash的方法:fr_ip_double_hash_malloc / fr_ip_double_hash_destroyfr_ip_double_hash_mirror_insert_ip :只針對mirror的insert ip操作fr_ip_double_hash_mirror_insert_blurip_ptrfr_ip_double_hash_mirror_insert_bystringsfr_ip_double_hash_mirror_delete_ipfr_ip_double_hash_mirror_delete_blurip_ptrfr_ip_double_hash_mirror_delete_bystringsfr_ip_double_hash_mirror_delete_ip_randomlyfr_ip_double_hash_mirror_delete_all :刪除mirror中所有的ip記錄,即所有的精確ip和模糊ip記錄fr_ip_double_hash_switch_mirror_update :將mirror與master互換,并更新master至mirror(此時的mirror即為之前的master)fr_ip_double_hash_rebuild :將雙哈希表重建,可指定新的hash function、rnd以及hash表的長度,這將解決hash表查詢效率低下的問題,以防御外界針對hash表的攻擊。當然,在重建之后,原有的諸多ip條目不會丟失。fr_ip_double_hash_find_boolfr_ip_double_hash_find_bystrings_bool?
掛到協議棧上的鉤子函數:
??在模塊初始化函數fr_ip_dev_init的最后,即當兩個雙哈希表實例(分別用作黑名單與白名單)初始化成功、fedev設備注冊成功之后,其將會執行nf_register_hook,將指定的鉤子函數fr_nf_hook_sample掛到NF_INET_PRE_ROUTING之上。
??fr_nf_hook_sample的主要處理代碼如下:
if(fr_ip_double_hash_find_bool(double_hash_white_ptr,sip)) return NF_ACCEPT;else if(fr_ip_double_hash_find_bool(double_hash_ptr,sip)) return NF_DROP;else return NF_ACCEPT;其中,double_hash_white_ptr指向白名單fr_ip_double_hash實例,double_hash_ptr則指向黑名單fr_ip_double_hash實例,由于支持模糊ip匹配,故,上述代碼使得對源ip過濾的“通”、“堵”策略皆可使用。
?
內核空間frdev的ioctl處理函數:
??目前,ioctl支持來自用戶空間的如下操作:
//黑名單操作 /* in-black ip */ #define FR_IP_IOCTL_TYPE_FIND 1 #define FR_IP_IOCTL_TYPE_FIND_BYSTRINGS 2 // * 輸入ip字符查找 #define FR_IP_IOCTL_TYPE_MIRROR_INSERT_IP 3 #define FR_IP_IOCTL_TYPE_MIRROR_INSERT_BYSTRINGS 4 // * #define FR_IP_IOCTL_TYPE_MIRROR_DELETE_IP 5 // * #define FR_IP_IOCTL_TYPE_MIRROR_DELETE_IP_RANDOMLY 6 //* #define FR_IP_IOCTL_TYPE_MIRROR_DELETE_BYSTRINGS 7 // * #define FR_IP_IOCTL_TYPE_MIRROR_DELETE_ALL 8 //* #define FR_IP_IOCTL_TYPE_SWITCH_MIRROR_UPDATE 9 // * #define FR_IP_IOCTL_TYPE_REBUILD 10 // * #define FR_IP_IOCTL_TYPE_COPY_HASH_STRUCT 11 // * #define FR_IP_IOCTL_TYPE_DUMP 12 //* 輸出雙哈希表的分布情況與統計信息 #define FR_IP_IOCTL_TYPE_MIRROR_INSERT_IP_BINS 13 //* 一次增加大量精確ip,以二進制的方式輸入 #define FR_IP_IOCTL_TYPE_MIRROR_DELETE_IP_BINS 14 //* //白名單操作 /* in-white ip */ #define FR_IP_IOCTL_TYPE_WHITE_FIND 101 #define FR_IP_IOCTL_TYPE_WHITE_FIND_BYSTRINGS 102 // * #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_INSERT_IP 103 #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_INSERT_BYSTRINGS 104 // * #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_DELETE_IP 105 #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_DELETE_IP_RANDOMLY 106 // * #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_DELETE_BYSTRINGS 107 // * #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_DELETE_ALL 108 //* #define FR_IP_IOCTL_TYPE_WHITE_SWITCH_MIRROR_UPDATE 109 // * #define FR_IP_IOCTL_TYPE_WHITE_REBUILD 110 // * #define FR_IP_IOCTL_TYPE_WHITE_COPY_HASH_STRUCT 111 // * #define FR_IP_IOCTL_TYPE_WHITE_DUMP 112 //* #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_INSERT_IP_BINS 113 //* #define FR_IP_IOCTL_TYPE_WHITE_MIRROR_DELETE_IP_BINS 114 //*? 上述各功能的具體實現請閱讀frdev源碼中的fr_ip_dev_ioctl_routine函數。
?
用戶空間管理工具:fripadm
??第一步,實現fripadm_black_in_exe與fripadm_white_in_exe,是分別管理黑白名單的工具,不過,較為簡陋,第二步,使用shell腳本對其進行二次封裝得到fripadm_black_in.sh與fripadm_white_in.sh這兩個較用戶友好的工具。
??fripadm為用戶空間的C語言開發者們提供了如下API:
//針對ip黑名單的操作 double_hash_find_bystrings(int fd,char * str, unsigned int size) //其中fd為frdev的fd——文件描述符 double_hash_mirror_insert_bystrings(int fd,char * str, unsigned int size) double_hash_mirror_insert_bins(int fd,char * str, unsigned int size) double_hash_mirror_delete_bystrings(int fd,char * str, unsigned int size) double_hash_mirror_delete_bins(int fd,char * str, unsigned int size) double_hash_mirror_delete_ip_randomly(int fd,unsigned int size) double_hash_mirror_delete_all(int fd) double_hash_switch_mirror_update(int fd) double_hash_rebuild(int fd,unsigned int modular, unsigned int rnd) double_hash_dump(int fd) //針對ip白名單的操作 double_hash_white_find_bystrings(int fd,char * str, unsigned int size) //其中fd為frdev的fd——文件描述符 double_hash_white_mirror_insert_bystrings(int fd,char * str, unsigned int size) double_hash_white_mirror_insert_bins(int fd,char * str, unsigned int size) double_hash_white_mirror_delete_bystrings(int fd,char * str, unsigned int size) double_hash_white_mirror_delete_bins(int fd,char * str, unsigned int size) double_hash_white_mirror_delete_ip_randomly(int fd,unsigned int size) double_hash_white_mirror_delete_all(int fd) double_hash_white_switch_mirror_update(int fd) double_hash_white_rebuild(int fd,unsigned int modular, unsigned int rnd) double_hash_white_dump(int fd)? fripadm_black_in_exe、fripadm_white_in_exe、fripadm_black_in.sh與?fripadm_white_in.sh的具體實現請參看frdev源碼。
?
最終系統測試:
? 按照README所述的過程,編譯、安裝完畢frdev設備后,便可進行如下測試:
? 原本被black所DROP的數據包,在更新了white的ip條目后,被white所ACCEPT,上圖紅線標出了數據包被截斷的icmp_seq的區間。 ?
? 關于frdev的陳述到此為止。
?
??最近筆者在閱讀《白帽子講Web安全》這本書時,發現了雅虎公司用于防護應用層DDoS攻擊的系統Yahoo?Detecting?System?Abuse,yahoo為此系統申請了專利保護。下面是關于這個系統的描述:?
?(Patent?N0.:?US?7,533,414?B1?資料來源?http://patentimages.storage.googleapis.com/pdfs/US7533414.pdf)
?? A?system?continually?monitors?service?requests?and?detects?service?abuses.
??First,?a?screening?list?is?created?to?identify?potential?abuse?events.?A?screening?list?includes?event?IDs?and?associated?count?values.?A?pointer?cyclically?selects?entries?in?the?table,advancing?as?events?are?received.?
??An?incoming?event?ID?is?compared?with?the?event?IDs?in?the?table.?If?the?incoming?event?ID?matches?an?event?ID?in?the?Screening?list,the?associated?count?is?incremented.?Otherwise,?the?count?of?a?selected?table?entry?is?decremented.?If?the?count?value?of?the?selected?entry?falls?to?Zero,?it?is?replaced?With?the?incoming?event.?
??Event?IDs?can?be?based?on?properties?of?service?users,such?as?user?identifications,?or?of?service?request?contents,such?as?a?search?term?or?message?content.?The?screening?list?is?analyzed?to?determine?whether?actual?abuse?is?occurring.
??大概思路如下:
? 此系統通過維護一個篩選表來得到用戶的請求頻率,以判斷其是否存在service?abuse,然采取相關措施,例如BLOCK。
??這種防御思想,與我們之前所提出的防御狀態機有著異曲同工之妙。筆者認為這是必然的。
??前面的文章已經提過,DDoS攻擊存在的主要原因之一是網絡服務的開放性,我們不可能從下層來解決這樣的問題(因為服務的可用性是第一要求),只能從上層分析解決.
? 而應用層已經處于協議棧的最高層,所以,要防御應用層DDoS攻擊,只能從應用層以上來尋找解法,故,在這種情況下,除了借助數據統計分析,難道還會有更好的方法么?
?
? 在實現frdev的過程中,借助互聯網解決了很多問題,所以,如果您需要frdev的源碼,請在下方留下郵箱?:)
? 這是frdev在github上的地址,https://github.com/swordtao/frdev,如果有小伙伴想要一起來增強frdev的功能,熱烈歡迎?:)
? 通訊郵箱:yunthanatos@163.com
?
?
轉載于:https://www.cnblogs.com/lixigang/p/5371836.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的DDoS攻防战(三):ip黑白名单防火墙frdev的原理与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于android开源类库StickyL
- 下一篇: 【C语言笔记初级篇】第六章:指针入门