在上一篇文章 《DDoS渗透与攻防实战(二):CC攻击工具实现与防御理论》中,笔者阐述了一个防御状态机,它可用来抵御来自应用层的DDoS攻击,但是该状态机依赖一个能应对大量条目快速增删的ip黑白名单防火墙,我们目前并没有发现很好的开源实现以供我们使用。
实现方案选择:
硬件实现或者软件实现?
在面对诸如大量畸形包这样的攻击时,硬件实现将会是非常好的选择,这是因为在进行此类型的封包过滤时,系统需要记忆的状态很少(对于FPGA、ASIC诸多硬件实现方案来讲,记忆元件的成本决不可忽视,寄存器与静态RAM都非常昂贵,所以当需要记忆的信息很少时,纯硬件方案的速度优势使得其完胜软件方案)。
但是,当状态机需要处理庞大的记忆信息时,我们就需要选择廉价的存储器——动态随机存储器(如SDRAM中的DDR3)来作为系统状态机的存储介质,以降低系统的成本和复杂度。这时,软件实现更胜一筹。尽管纯硬件实现的速度会比软件的方式高出很多,但我们也从第一篇文章《DDoS渗透与攻防实战 (一) : 初识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_destroy
fr_ip_hash_array_insert_ip :增加一条精确ip记录
fr_ip_hash_array_insert_blurip_ptr :增加一条模糊ip记录(以指针引用的方式&#x