Linux系统经验菜鸟

在Linux服务器中使用iptables规则 防御SYN洪水/AB压力测试/CC攻击以及其他类型扫描器

iptables 是一款控制系统进出流量的强大配置工具。

IPTABLES 是与最新的 3.5 版本 Linux 内核集成的 IP 信息包过滤系统。如果 Linux 系统连接到因特网或 LAN、服务器或连接 LAN 和因特网的代理服务器, 则该系统有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置。

iptables_banner_andyx.net_.png插图

更多iptables相关文章请参见《系统管理员必备的16个经典iptables使用技巧

 

常用iptables操作

查找所有规则

iptables -L -n --line-numbers

iptables_show_andyx.net_.png插图(1)

删除一条规则

iptables -D INPUT 8

#注意,这个8是行号,是之前iptables -L INPUT --line-numbers 所打印出来的行号#

清空所有规则

iptables -F

保存/另存iptables规则

iptables-save

#若要导出/另存为iptables规则,请参照:
iptables-save > /root/iptables_copy_andyx.net.txt

还原iptables规则

# 先清空iptables规则表
iptables -F


#然后再从另存的iptables规则中还原
iptables-restore 《 /root/iptables_copy_andyx.net.txt

关于iptables中tcp-flags的说明

F : FIN 结束标志; 结束会话
带有该标志置位的数据包用来结束一个TCP回话,但对应端口仍处于开放状态,准备接收后续数据。

S : SYN 同步标志; 表示开始会话请求
同步序列编号(Synchronize Sequence Numbers)栏有效。该标 志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,
该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。
通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

R : RST 复位标志;中断一个连接
复位标志有效。用于复位相应的TCP连接。

P : PSH 推标志; 数据包立即发送
该标志置位时,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的

A : ACK 应答标志
确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头 内的确认编号栏内包含的确认编号(w+1,Figure:1)为下一个预期的
序列编号,同时提示远端系统已经成功接收所有数据。

E : ECE 显式拥塞提醒回应

W : CWR 拥塞窗口减少

TCP三次握手的原理

一个虚拟连接的建立是通过三次握手来实现的

1. (B) → [SYN] → (A)
假如服务器A和客户机B通讯. 当A要和B通信时,B首先向A发一个SYN (Synchronize) 标记的包,告诉A请求建立连接.
注意: 一个SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources)。认识到这点很重要,只有当A受到B发来的SYN包,才可建立连接,除此之外别无他法。
因此,如果你的防火墙丢弃所有的发往外网接口的SYN包,那么你将不能让外部任何主机主动建立连接。

2. (B) ← [SYN/ACK] ←(A)
接着,A收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作.
注意: SYN/ACK包是仅SYN和ACK标记为1的包.

3. (B) → [ACK] → (A)
B收到SYN/ACK 包,B发一个确认包(ACK),通知A连接已建立。至此,三次握手完成,一个TCP连接完成
注意: ACK包就是仅ACK 标记设为1的TCP包. 需要注意的是当三此握手完成、连接建立以后,TCP连接的每个包都会设置ACK位

这就是为何连接跟踪很重要的原因了。如果没有连接跟踪,防火墙将无法判断收到的ACK包是否属于一个已经建立的连接。一般的包过滤(Ipchains)收到ACK包时,会让它默认通过(这绝对不是个好主意)。而当状态型防火墙收到此种包时,它会先在连接表中查找是否属于哪个已建连接,否则丢弃该包。iptables_tcp-head_andyx.net_.jpg插图(2)

 

TCP四次挥手的原理

四次挥手用来关闭已建立的TCP连接

1. (B) → ACK/FIN → (A)

2. (B) ← ACK  ← (A)

3. (B) ← ACK/FIN ← (A)

4. (B) → ACK → (A)

注意: 由于TCP连接是双向连接,因此关闭连接需要在两个方向上做。ACK/FIN 包(ACK 和FIN 标记设为1)通常被认为是FIN(终结)包。然而,由于连接还没有关闭,FIN包总是打上ACK标记。没有ACK标记而仅有FIN标记的包不是合法的包,并且通常被认为是恶意的。

iptables_tcp-way_andyx.net_.jpg插图(3)三次握手和四次挥手示意图

TCP连接复位的原理

四次挥手不是关闭TCP连接的唯一方法. 有时,如果主机需要尽快关闭连接(或连接超时,端口或主机不可达),RST (Reset)包将被发送。

注意在,由于RST包不是TCP连接中的必须部分, 可以只发送RST包(即不带ACK标记)。

但在正常的TCP连接中RST包可以带ACK确认标记

注意:RST包是可以不要收到方确认的

无效的TCP标记

到目前为止,你已经知晓了 SYN, ACK, FIN, 和RST 标记。另外,还有PSH (Push) 和URG (Urgent)标记。
最常见的非法组合是SYN/FIN 包。注意:由于 SYN包是用来初始化连接的, 它不可能和FIN和RST标记一起出现。

所以说这一定是一个恶意攻击。
由于现在大多数防火墙已知 SYN/FIN 包, 别的一些组合,例如SYN/FIN/PSH, SYN/FIN/RST, SYN/FIN/RST/PSH。很明显,当网络中出现这种包时,你的网络肯定受到攻击了。
别的已知的非法包有FIN (无ACK标记)和”NULL”包,如同早先讨论的,由于ACK/FIN包的出现是为了关闭一个TCP连接,那么正常的FIN包总是带有ACK标记。
“NULL”包就是没有任何TCP标记的包(URG,ACK,PSH,RST,SYN,FIN都为0)。
到目前为止,正常的网络活动下,TCP协议栈不可能产生带有上面提到的任何一种标记组合的TCP包。当你发现这些不正常的包时,肯定有人对你的网络不怀好意。

tcp-flags基本使用方法

基本使用如下:

iptables -p tcp --tcp-flags 参数列表1 参数列表2 参数列表N

匹配指定的TCP标记,有两个参数列表,列表内部用逗号为分隔符,两个列表之间用空格分开,
LIST1用作参数检查,LIST2用作参数匹配。可用标志有:
SYN( 同步; 表示开始会话请求 ), ACK(应答);
FIN(结束; 结束会话),RST(复位;中断一个连接);
PSH(推送; 数据包立即发送),URG(紧急 );
ALL(指选定所有的标记),NONE(指未选定任何标记);

举例如下,当23端口符合规则时则抛弃:

[root@andyx.net ~]# iptables -A INPUT -p tcp --dport 23 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j DROP
[root@andyx.net ~]# iptables -A INPUT -p tcp --dport 23 --tcp-flags ALL SYN -j DROP
[root@andyx.net ~]# iptables -A INPUT -p tcp --dport 23 --syn -j DROP

上面3条规则其实是一样的,ALL表示“SYN,ACK,FIN,RST,URG,PSH”,表示匹配三次握手中的第一次,此外tcp扩展模块还提供了一个选项 – -syn 也表示第一次握手。

 

iptables防御实战

使用iptables对防火墙端口进行操作

开启指定端口,例如开启80或22端口:

iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -j ACCEPT

关闭指定端口,例如关闭8080或9000:

iptables -I INPUT -p tcp --dport 8080 -j DROP
iptables -I INPUT -p tcp --dport 9000 -j DROP

 

使用iptables屏蔽指定IP/IP段

屏蔽单个IP:

iptables -I INPUT -s 201.192.138.51 -j DROP

屏蔽小范围IP段:

# 这是个来自山东的恶意SQL注入扫描器,屏蔽范围113.128.12.1 至 113.128.12.254
iptables -I INPUT -s 113.128.12.0/24 -j DROP

# 这是个来自北京的恶意SQL注入扫描器,屏蔽范围219.143.140.1 至 219.143.140.254
iptables -I INPUT -s 219.143.140.0/24 -j DROP

屏蔽中等范围IP段:

# 这是一个来自于景安机房的恶意扫描器,屏蔽范围122.114.0.1 至 122.114.254.254
iptables -I INPUT -s 122.114.0.0/16 -j DROP

# 这是一个假冒百度搜索引擎的扫描器,屏蔽范围104.251.0.1 至 104.251.254.254
iptables -I INPUT -s 104.251.0.0/16 -j DROP

屏蔽广域范围IP段(慎用!!!)

# 可能的DDOS僵尸网络,屏蔽范围106.0.0.1 至 106.254.254.254
iptables -I INPUT -s 106.0.0.0/8 -j DROP

 

使用iptables防御SYN洪水攻击

SYN Flood 主要是利用了TCP协议的三次握手的缺陷,在这个攻击中,Flood带有一系列的syn数据包,每个数据包都会导致服务端发送SYN-ACK响应,然后服务器等待SYN+ACK之后的第三次握手ACK,由于客户端是软件生成的虚拟IP,永远不会再发送ACK响应服务端,服务端会利用从传机制直到超时后删除,整个系统资源也会被队列积压消耗,导致服务器无法对正常的请求进行服务。

iptables_syn-attack_andyx.net_.jpg插图(4)

判断SYN攻击非常的简单,当你在服务器上使用netstat命令看到大量的SYN_RECV半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。

iptables对于SYN的一般防御方法:

#缩短SYN - Timeout时间:
iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -m limit --limit 1/sec --limit-burst 5 -j ACCEPT


#设置同IP每秒 最多5个syn封包 进入,且burst为15,超出拒绝 :
iptables -N syn-flood    #新建一条额外iptables链
iptables -A INPUT -p tcp --syn -j syn-flood
iptables -A syn-flood  -p tcp -m limit --limit 5/s --limit-burst 15 -j RETURN
iptables -A syn-flood -j REJECT

注意:这个方式需要调节一个合理的速度值,不然会影响正常用户的请求!

 

使用iptables防御AB压力测试/CC攻击

防御此类供给的最好办法就限制特定IP在指定时间内的访问次数,通常新版本Linux内核模块都支持kernel-smp-modules-connlimit,所以我们可以直接使用connlimit进行限制:

实例1:抵御拒绝服务攻击 ,允许外网最多24个初始连接,然后服务器每秒新增12个,访问太多超过的丢弃

第二条是允许服务器内部每秒1个初始连接进行转发

iptables -A INPUT  -p tcp --syn -m limit --limit 12/s --limit-burst 24 -j ACCEPT
iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT

实例2:允许单IP访问服务器的80端口的最大连接数为 20 

iptables -I INPUT -p tcp --dport 80 -m connlimit  --connlimit-above 20 -j REJECT

实例3:使用recent模块对访问本机的22端口进行限制,每个ip每小时只能连接5次,超过的拒接,1小时候重新计算次数

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set -j ACCEPT

# 提示:上面recent规则只适用于默认规则为DROP中,如果要适用默认ACCEPT的规则,需要--set放前面 并且无-j ACCEPT

实例4:防止过多拒绝服务连接,设置允许外网网卡(eth0)每个IP最多15个初始连接,超过则丢弃

iptables -A INPUT -i eth0 -p tcp --syn -m connlimit --connlimit-above 15 -j DROP
iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT

提示:攻击这东西只能防御不能完全根除!只能缓解,降低到最低的风险。

 

使用iptables屏蔽部分扫描器

屏蔽NMAP SCAN

iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

屏蔽XMAS TREE

iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

屏蔽Null Scan

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

屏蔽INVALID COMBINATIONS

iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP

这里只列出一些常见的组合,此外还有一些非法的包组合,具体参考:http://www.stearns.org/modwall/archives/tcpchk.v0.1.1

屏蔽全部畸形包列表

iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP

iptables -A INPUT -p tcp --tcp-flags RST,FIN RST,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,URG SYN,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,PSH  -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,ACK,PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN  -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH  -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG  -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL RST  -j RETURN
iptables -A INPUT -p tcp --tcp-flags SYN,ACK NONE  -j DROP

(END)

文章由AndyX 收集整理,转载请注明来源:https://andyx.net/using_iptables_to_prevent_syn_flood_ab_stress_cc_attack/

Tcp-flags部分说明引用自独孤柯灵的博客,DDOS防御部分引用自zhang-san的博客。