一次DOS事件的解决办法

2015/01/0410:01:47 发表评论

0.分析过程
首先,分析了DOS的类型、特征、攻击方法。

使用netstat -na|grep SYN_RECV|wc,发现当前存在大量SYN_RECV状态连接,源地址都是伪造的,netstat -na|grep SYN_RECV|wc显示数量为1024个,这个是当然,Linux默认的Syn_Backlog对列就是1024,超过的SYN都丢弃了。

针对的攻击端口是80:WWW服务,当然,Web服务器也已经无法访问了。

在 打开SYN_Cookie防护之后,攻击得到了一些缓解,但随后攻击流量又增大了,情况也好不到哪儿去,而Linux的Iptables又不能做 syn_proxy的,那么只好从其他方面下手,用tcpdump -w抓下了当时的数据流量,计数分析流量大约在1.8w pps左右,其中99%以上都是伪造源地址的syn包。

既然是伪造地址,那就比较难处理,不过经过仔细的统计和分析,还是分析出了这次攻击中主要数据的特征,主要有以下几条:

代码:

1. tcp标志位为 syn
2. ip数据总长为40Byte
3. ip头中的Identifier字端固定为256(0x0100)
4. TTL值平均分布为 74 - 95之间
5. tcp窗口值固定为16384
6. 目标端口为tcp:80
7. tcp初始化序列号为 17314131xx,按+1累计依次递增

这样,注意看其中的3、4、5几条,这是对我们来说最重要的线索。
3. ip identifier字端固定为0x0100,而在TCP/IP规范中,这个字段是为了防止一个连接中的分片包重复而作的包内序列号。虽然大多数操作系统 没有严格准循着一条规范,但这个数值的来源却是确定的,即在正常的TCP/IP堆栈中,这个字段的值应该是发送此数据包是的TCB(TCP控制块,一个内 核空间的TCP数据结构)的序列号。而即使系统也没有严格准循这一条,那么在网络中传输的数据,identifier字段的内容也应该是随机分布的,正常 的操作系统网络堆栈不可能发送出大量0x0100这样固定的字段内容来。

4. TTL值平均分布在74 - 95之间。按照常识也知道,大多数操作系统默认的TTL应该为32、64、128这样的2的整数次方;而另一个方面,TTL在网络传输的过程中每过一个路 由器就会自动减一,而现在的Internet路由设计已经是比较良好的,从任何一点到达Intetnet的另一端,一般来说TTL条数不会超过 20-30,这个我也测试过,从国内网通和电信的网络看来,到达国内和国际的大多数网站,TTL跳数都在20以内,而从Windows的Tracert命 令也可以看出--它假设的最大TTL超时条数也只是30。超过30条的正常Internet路由是很罕见的。那么我们来做一个简单的减法:

代码:

128 - 30 = 98
64 - 30 = 34
32 - 30 = 2

所以一个数据包,在正常的传输过程中,当到达端点时,它的TTL数分布范围应该是:代码:

2 - 32 (罕见)、 34 - 64 、 98 - 128

而在本次数据采样中,大多数伪造地址的SYN数据,TTL都在74 - 95之间。

其他附加特征,例如IP长度、TCP窗口、TCP SYN_Flag等,也可以作为附加判断标志。这样我们提取出这次攻击的主要特征码为:

代码:

a. tcp syn flag only, dst port 80
b. ip identifier = 0x0100
c. 74 < ttl < 95
d. tcp window = 16384

这样四条特征。

之后就是想办法过滤了。因为这次没办法假设其他的防火墙,只能用系统自身的iptables挡一下,所以效果么......够麻烦的。

1. 下载最新版的iptables-1.3.1和patch-o-matic snapshot 。(需要Linux内核
2.6.10以上版本支持,这一点...Redhat系的所有版本都得重编了。)
ftp://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/
解压iptables和pom;
运行pom patch脚本,过程中需要输入iptables和内核源代码完全路径;

代码:

./runme connlimit u32 TARPIT pkttype length

编译和安装iptables及pom内核模块。

代码:

# make -C /lib/modules/`uname -r`/build SUBDIRS=net/ipv4/netfilter/ modules
# make -C /lib/modules/`uname -r`/build SUBDIRS=net/ipv4/netfilter/ modules_install

编译iptables。并手工安装;

代码:

# make KERNEL_DIR=内核源码目录
# cp iptables iptables-save iptables-restore /usr/sbin
# cp extensions/*.so /usr/lib/iptables/

2. 配置内核参数

代码:


3. 配置iptables规则

代码:

#--以下为iptables规则设置--

modprobe ipt_TARPIT
modprobe ipt_u32
modprobe ipt_connlimit
modprobe ipt_length
modprobe ipt_pkttype

iptables -N input_ext
iptables -F input_ext                                    # 新建iptables队列

iptables -A INPUT -i lo -j ACCEPT 
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT            # 激活状态检测

iptables -A INPUT -i eth0 -j input_ext              # 扩展input规则
iptables -A INPUT -j DROP                              # 默认input规则,丢弃全部

iptables -A input_ext -p tcp -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -m u32 --u32 "0x2&0xffff=0x100&&0x5&0xff=0x4a:0x5f" -j DROP          # 本次syn-flood攻击指纹特征,丢弃
iptables -A input_ext -p tcp -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -m connlimit --connlimit-above 5 --connlimit-mask 32 -j TARPIT             # 防止连接耗尽攻击,每IP并发连接限制为4
iptables -A input_ext -p tcp -j TARPIT                                                   # 防止端口扫描攻击

iptables -A input_ext -m pkttype --pkt-type broadcast -j DROP                  # 丢弃广播数据包
iptables -A input_ext -p icmp -m limit --limit 6/s -m icmp --icmp-type 4 -j ACCEPT          # 接受icmp traceroute/echo reply数据,限制流量 5个/秒
iptables -A input_ext -p icmp -m limit --limit 6/s -m icmp --icmp-type 8 -j ACCEPT 
iptables -A input_ext -p icmp -m length --length 48:256 -j ACCEPT             # 限制icmp包大小为 0 - 256Byte,防止大包flood
                                                                              # 实际网络中如果不用icmp/udp协议,可以直接全部drop

1. 带宽占满的情况下,任何防护都是没用的。

2. 任何ip数据都是可以伪造的,如果攻击数据完全采用随机数发送的话,那么很可能无迹可寻。
3. 在进行过滤和dos防御的时候,不可避免的会损失一些正常的连接,这个时候,想想80/20规则,
不要力求完美。
4. 任何安全防护措施和内核参数的调整,都可能对系统和网络的稳定性造成一定的负面影响,所以要根据实际情况而定,切勿忙从。
5. 这个防火墙规则中主要生效的是TCP段和ICMP段,在带宽未被占满时可以一定程度防止syn-flood、icmp-flood、tcp-connect-flood类型的DOS。
但是syn-flood的u32规则是针对这次攻击的特征所写的,在应对其他攻击时不可能完全有效,必须单独重新分析。
tcp-connect连接限制,我目前定的是同一ip地址并发5个web连接,防止连接耗尽,在局域网NAT访问时可能会有些问题,可以根据网络拓扑情况添加信任规则。
6. 常见的网络层dos主要有:
syn-flood (协议缺陷型)
ack-flood(stream) (协议缺陷型)
icmp-flood(smarf) (流量型)
udp-flood(froogle) (流量型)
tcp-connect-flood (资源型)
对于icmp和udp,可以在规则链开始就直接丢弃掉;
对 于tcp-flood,可以使用conn-limit限制,效果比较好,但是要注意调整内核参数ip_conntrack的数值,否则可能造成 iptables状态跟踪表溢出,反而形成拒绝服务;另外,当syn+ack类型的攻击发生时,本省也会消耗大量的conntrack资源,所以防火墙规 则的顺序很重要。
对于syn-flood,最好的方法还是使用bsd pf的syn-proxy,效果不错,不过这个下次再讲吧。
如果不行的话,可能就只能针对个案进行模式特征分析了。

再次提醒,防火墙规则配置有风险,一定要根据自己实际情况调整和测试完毕后再上线。可以在input链的-j input_ext规则之前加一条:
-i INPUT 1 -s 内网地址 -j ACCEPT return之类的语句完全优先信任管理地址。

  • 微信扫码赞助
  • weinxin
  • 支付宝赞助
  • weinxin

发表评论

您必须才能发表评论!