当前位置导航:炫浪网>>网络学院>>操作系统>>Linux教程

系统安全:一次DOS事件的解决办法

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. 配置内核参数

代码:
======================================================================

#--以下为sysctl 内核参数设置

#net.ipv4.conf.default.rp_filter = 1

#net.ipv4.conf.all.rp_filter = 1

#net.ipv4.conf.eth1.rp_filter = 1

# 开启IP源地址验证,防止IP地址欺骗,在任何情况下都应开启,默认关闭

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do 

     echo 1 > $f 

done

sysctl -w net.ipv4.conf.default.accept_source_route=0   # 禁用icmp源路由选项

sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1         # 忽略icmp ping广播包,应开启

#sysctl -w net.ipv4.icmp_echo_ignore_all=1                      # 忽略所有icmp ping数据,覆盖上一项

sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1

# 以下一段为抵抗syn flood攻击,平时建议关闭

sysctl -w net.ipv4.tcp_syncookies=1              # tcp syncookie,默认关闭

sysctl -w net.ipv4.tcp_max_syn_backlog=1280   # syn队列,默认1024,> 1280可能工作不稳定,需要修改内核源码参数

sysctl -w net.ipv4.tcp_synack_retries=2             # syn-ack握手状态重试次数,默认5,遭受syn-flood攻击时改为1或2

sysctl -w net.ipv4.tcp_syn_retries=2                  # 外向syn握手重试次数,默认4

# 以下一段为应对tcp connect连接耗尽攻击,如果开启iptables connlimit模块可禁用

# 有严重连接性能影响和不稳定因素,慎用

sysctl -w tcp_tw_recycle=1                           # 默认0,tw快速回收

sysctl -w tcp_tw_reuse=1                             # 默认0,tw重用

sysctl -w tcp_keepalive_intvl=60                    # 默认75,tcp keeplive探测轮询时间

sysctl -w tcp_keepalive_probes=3                  # 默认9,tcp keeplive探测轮询次数

sysctl -w tcp_keepalive_time=1800                # 默认7200,tcp keeplive时间

sysctl -w tcp_fin_timeout=30                        # 默认60,tcp fin状态超时时间

#sysctl -w net.ipv4.tcp_retries1=2                     # tcp连接重传参数,慎用

#sysctl -w net.ipv4.tcp_retries2=8

sysctl -w net.ipv4.ip_conntrack_max=65535          # 增大iptables状态跟踪表

======================================================================


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之类的语句完全优先信任管理地址。

原文链接:http://bbs.et8.net/bbs/showthread.php?t=671756

上一页  [1] [2] 

相关内容
赞助商链接