网站的SYN_RECV(SYN_RECEIVED)的防范措施
服务器突然连接增加,查看发现很多SYN_RECV的连接
tcp6 0 0 172.16.0.168:443 167.249.170.220:42793 SYN_RECV - on (3.38/2/0)
tcp6 0 0 172.16.0.168:443 167.249.169.207:14104 SYN_RECV - on (0.26/0/0)
tcp6 0 0 172.16.0.168:443 167.249.169.247:11048 SYN_RECV - on (1.17/2/0)
tcp6 0 0 172.16.0.168:443 167.249.169.244:49962 SYN_RECV - on (2.00/2/0)
tcp6 0 0 172.16.0.168:443 167.249.169.247:13106 SYN_RECV - on (1.28/1/0)
tcp6 0 0 172.16.0.168:443 167.249.169.130:44840 SYN_RECV - on (1.18/1/0)
tcp6 0 0 172.16.0.168:443 167.249.170.79:11042 SYN_RECV - on (2.48/2/0)
tcp6 0 0 172.16.0.168:443 167.249.168.108:17191 SYN_RECV - on (0.56/2/0)
tcp6 0 0 172.16.0.168:443 167.249.169.139:42796 SYN_RECV - on (0.00/2/0)
SYN 是最常见又最容易被利用的一种手法。相信很多人还记得2000年YAHOO网站遭受的事例,当时利用的就是简单而有效的SYN,有些 网络蠕虫病毒配合SYN造成更大的破坏。本文介绍SYN的基本原理、工具及检测方法,并全面探讨SYN防范技术。
原因分析
参考文档: https://www.cnblogs.com/Renyi-Fan/p/10064236.html
TCP握手协议
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
- 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念: 未连接队列: 在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出 确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。
SYN-ACK 重传次数: 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
SYN的基本原理
SYN属于DOS的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。SYN\除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上SYN\并不管目标是什么系统,只要这些系统打开TCP服务就可以实施。 从上图可看到,服务器接收到连接请求(syn= j),将此信息加入未连接队列,并发送请求包给客户(syn=k,ack=j+1),此时进入SYN_RECV状态。当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。配合IP欺骗,SYN能达到很好的效果,通常,客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
SYN工具
SYN实现起来非常的简单,互联网上有大量现成的SYN工具。
windows系统下的SYN工具 以 synkill.exe为例,运行工具,选择随机的源地址和源端囗,并填写目标机器地址和TCP端囗,激活运行,很快就会发现目标系统运行缓慢。如果效果不明显,可能是目标机器并未开启所填写的TCP端囗或者防火墙拒绝访问该端囗,此时可选择允许访问的TCP端囗,通常,windows系统开放 tcp139端囗,UNIX系统开放tcp7、21、23等端囗。
检测SYN
检测SYN非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN
处理方式
参考文档: https://cloud.tencent.com/developer/article/1115567
TCP洪水攻击(SYN Flood)的诊断和处理
SYN Flood介绍
前段时间网站被攻击多次,其中最猛烈的就是TCP洪水攻击,即SYN Flood。
SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包(SYN包),被攻击[服务器]回应第二个握手包(SYN+ACK包),因为对方是假冒IP,对方永远收不到包且不会回应第三个握手包。导致被攻击服务器保持大量SYN_RECV状态的“半连接”,并且会重试默认5次回应第二个握手包,塞满TCP等待连接队列,资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来。
详细的原理,网上有很多介绍,应对办法也很多,但大部分没什么效果,这里介绍我们是如何诊断和应对的。
诊断
我们看到业务曲线大跌时,检查机器和DNS,发现只是对外的web机响应慢、CPU负载高、ssh登陆慢甚至有些机器登陆不上,检查系统syslog:
# tail -f /var/log/messages
Apr 18 11:21:56 web5 kernel: possible SYN flooding on port 80. Sending cookies.
检查连接数增多,并且SYN_RECV 连接特别多:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 16855
CLOSE_WAIT 21
SYN_SENT 99
FIN_WAIT1 229
FIN_WAIT2 113
ESTABLISHED 8358
SYN_RECV 48965
CLOSING 3
LAST_ACK 313
根据经验,正常时检查连接数如下:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 42349
CLOSE_WAIT 1
SYN_SENT 4
FIN_WAIT1 298
FIN_WAIT2 33
ESTABLISHED 12775
SYN_RECV 259
CLOSING 6
LAST_ACK 432
以上就是TCP洪水攻击的两大特征。执行netstat -na>指定文件,保留罪证。
应急处理
根据netstat查看到的对方IP特征:
# netstat -na |grep SYN_RECV|more
利用iptables临时封掉最大嫌疑攻击的IP或IP号段,例如对方假冒173.*.*.*号段来攻击,短期禁用173.*.*.*这个大号段(要确认小心不要封掉自己的本地IP了!)
# iptables -A INPUT -s 173.0.0.0/8 -p tcp –dport 80 -j DROP
再分析刚才保留的罪证,分析业务,用iptables解封正常173.*.*.*号段内正常的ip和子网段。这样应急处理很容易误伤,甚至可能因为封错了导致ssh登陆不了服务器,并不是理想方式。
使用F5挡攻击
应急处理毕竟太被动,因为本机房的F5比较空闲,[运维]利用F5来挡攻击,采用方式:让客户端先和F5三次握手,连接建立之后F5才转发到后端业务服务器。后来被攻击时F5上看到的现象:
- 连接数比平时多了500万,攻击停止后恢复。
- 修改F5上我们业务的VS模式后,F5的CPU消耗比平时多7%,攻击停止后恢复。
- 用F5挡效果明显,后来因攻击无效后,用户很少来攻击了,毕竟攻击也是有成本的。
调整系统参数挡攻击
没有F5这种高级且昂贵的设备怎么办?我测试过以下参数组合能明显减小影响,准备以后不用F5抗攻击。
第一个参数tcp_synack_retries = 0是关键,表示回应第二个握手包(SYN+ACK包)给客户端IP后,如果收不到第三次握手包(ACK包)后,不进行重试,加快回收“半连接”,不要耗光资源。
不修改这个参数,模拟攻击,10秒后被攻击的80端口即无法服务,机器难以ssh登录; 用命令netstat -na |grep SYN_RECV检测“半连接”hold住180秒;
修改这个参数为0,再模拟攻击,持续10分钟后被攻击的80端口都可以服务,响应稍慢些而已,只是ssh有时也登录不上;检测“半连接”只hold住3秒即释放掉。
修改这个参数为0的副作用:网络状况很差时,如果对方没收到第二个握手包,可能连接服务器失败,但对于一般网站,用户刷新一次页面即可。这些可以在高峰期或网络状况不好时tcpdump抓包验证下。
根据以前的抓包经验,这种情况很少,但为了保险起见,可以只在被tcp洪水攻击时临时启用这个参数。
tcp_synack_retries默认为5,表示重发5次,每次等待30~40秒,即“半连接”默认hold住大约180秒。详细解释:
The tcp_synack_retries setting tells the kernel how many times to retransmit the SYN,ACK reply to an SYN request. In other words, this tells the system how many times to try to establish a passive TCP connection that was started by another host. This variable takes an integer value, but should under no circumstances be larger than 255 for the same reasons as for the tcp_syn_retries variable. Each retransmission will take aproximately 30-40 seconds. The default value of the tcp_synack_retries variable is 5, and hence the default timeout of passive TCP connections is aproximately 180 seconds.
之所以可以把tcp_synack_retries改为0,因为客户端还有tcp_syn_retries参数,默认是5,即使服务器端没有重发SYN+ACK包,客户端也会重发SYN握手包。详细解释:
The tcp_syn_retries variable tells the kernel how many times to try to retransmit the initial SYN packet for an active TCP connection attempt. This variable takes an integer value, but should not be set higher than 255 since each retransmission will consume huge amounts of time as well as some amounts of bandwidth. Each connection retransmission takes aproximately 30-40 seconds. The default setting is 5, which would lead to an aproximate of 180 seconds delay before the connection times out.
第二个参数net.ipv4.tcp_max_syn_backlog = 200000也重要,具体多少数值受限于内存。
以下配置,第一段参数是最重要的,第二段参数是辅助的,其余参数是其他作用的:
vi /etc/sysctl.conf
# 最关键信息,默认值为5,修改为0表示不要重发
net.ipv4.tcp_synack_retries = 0
# 半连接队列长度
net.ipv4.tcp_max_syn_backlog = 200000
# 系统允许的文件句柄的最大数目,因为连接需要占用文件句柄
fs.file-max = 819200
# 用来应对突发的大并发connect 请求
net.core.somaxconn = 65536
# 最大的TCP 数据接收缓冲(字节)
net.core.rmem_max = 1024123000
# 最大的TCP 数据发送缓冲(字节)
net.core.wmem_max = 167771216
# 网络设备接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目
net.core.netdev.max_backlog = 165536
# 本机主动连接其他机器时的端口分配范围
net.ipv4.ip_local_port_range = 10000 65535
# __省略其它___
使配置生效:
# sysctl -p
注意,以下参数面对外网时,不要打开。因为副作用很明显,具体原因请google,如果已打开请显式改为0,然后执行sysctl -p关闭。因为经过试验,大量TIME_WAIT状态的连接对系统没太大影响:
# 当出现、半连接、队列溢出时向对方发送syncookies,调大、半连接、队列后没必要
net.ipv4.tcp_syncookies = 0
#TIME_WAIT状态的变量重用功能
net.ipv4.tcp_tw_reuse = 0
# 时间戳选项,与前面net.ipv4.tcp_tw_reuse参数配合
net.ipv4.tcp_timestamps = 0
#TIME_WAIT状态的连接回收功能
net.ipv4.tcp_tw_recycle = 0
为了处理大量连接,还需改大另一个参数:
# vi /etc/security/limits.conf
在底下添加一行表示允许每个用户都最大可打开409600个文件句柄(包括连接):
* – nofile 409600
- 文件句柄不要超过系统限制
/usr/include/linux/fs.h,相关链接:http://blog.yufeng.info/archives/1380
#define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */
- 内核参数详细解释:http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html
结束语
TCP洪水攻击还没完美解决方案,希望本文对您有所帮助,让您快速了解。
原文链接:http://tech.uc.cn/?p=1790