■
SYN cookies
技术
我们知道,
TCP
协议开辟了一个比较大的内存空间
backlog
队列来存储半连接条目,当
SYN
请求不断增加,并这个空间,致使系统丢弃
SYN
连接。为使半连接队列被塞满的情况下,服务器仍能处理新到的
SYN
请求,
SYN cookies
技术被设计出来。
SYN cookies
应用于
linux
、
FreeBSD
等操作系统,当半连接队列满时,
SYN
cookies
并不丢弃
SYN
请求,而是通过加密技术来标识半连接状态。
在
TCP
实现中,当收到客户端的
SYN
请求时,服务器需要回复
SYN
+
ACK
包给客户端,客户端也要发送确认包给服务器。通常,服务器的初始序列号由服务器按照一定的规律计算得到或采用随机数,但在
SYN cookies
中,服务器的初始序列号是通过对客户端
IP
地址、客户端端囗、服务器
IP
地址和服务器端囗以及其他一些安全数值等要素进行
hash
运算,加密得到的,称之为
cookie
。当服务器遭受
SYN
攻击使得
backlog
队列满时,服务器并不拒绝新的
SYN
请求,而是回复
cookie
(回复包的
SYN
序列号)给客户端,
如果收到客户端的
ACK
包,服务器将客户端的
ACK
序列号减去
1
得到
cookie
比较值,并将上述要素进行一次
hash
运算,看看是否等于此
cookie
。如果相等,直接完成三次握手(注意:此时并不用查看此连接是否属于
backlog
队列)。
在
RedHat linux
中,启用
SYN cookies
是通过在启动环境中设置以下命令来完成:
# echo 1 > /proc/sys/net/ipv4/tcp_syncookies
■
增加最大半连接数
大量的
SYN
请求导致未连接队列被塞满,使正常的
TCP
连接无法顺利完成三次握手,通过增大未连接队列空间可以缓解这种压力。当然
backlog
队列需要占用大量的内存资源,不能被无限的扩大。
WIN2000
:除了上面介绍的
TcpMaxHalfOpen, TcpMaxHalfOpenRetried
参数外,
WIN2000
操作系统可以通过设置动态
backlog(dynamic backlog)
来增大系统所能容纳的最大半连接数,配置动态
backlog
由
AFD.SYS
驱动完成,
AFD.SYS
是一种内核级的驱动,用于支持基于
window socket
的应用程序,比如
ftp
、
telnet
等。
AFD.SYS
在注册表的位置:
HKLM\System\CurrentControlSet\Services\AFD\ParametersEnableDynamicBacklog
值为
1
时,表示启用动态
backlog
,可以修改最大半连接数。
MinimumDynamicBacklog
表示半连接队列为单个
TCP
端囗分配的最小空闲连接数,当该
TCP
端囗在
backlog
队列的空闲连接小于此临界值时,系统为此端囗自动启用扩展的空闲连接(
DynamicBacklogGrowthDelta
),
Microsoft
推荐该值为
20
。
MaximumDynamicBacklog
是当前活动的半连接和空闲连接的和,当此和超过某个临界值时,系统拒绝
SYN
包,
Microsoft
推荐
MaximumDynamicBacklog
值不得超过
2000
。
DynamicBacklogGrowthDelta
值是指扩展的空闲连接数,此连接数并不计算在
MaximumDynamicBacklog
内,当半连接队列为某个
TCP
端囗分配的空闲连接小于
MinimumDynamicBacklog
时,系统自动分配
DynamicBacklogGrowthDelta
所定义的空闲连接空间,以使该
TCP
端囗能处理更多的半连接。
Microsoft
推荐该值为
10
。
LINUX
:
Linux
用变量
tcp_max_syn_backlog
定义
backlog
队列容纳的最大半连接数。在
Redhat 7.3
中,该变量的值默认为
256
,这个值是远远不够的,一次强度不大的
SYN
攻击就能使半连接队列占满。我们可以通过以下命令修改此变量的值:
# sysctl -w net.ipv4.tcp_max_syn_backlog="2048"
Sun Solaris Sun Solaris
用变量
tcp_conn_req_max_q0
来定义最大半连接数,在
Sun Solaris 8
中,该值默认为
1024
,可以通过
add
命令改变这个值:
# ndd -set /dev/tcp tcp_conn_req_max_q0 2048
HP-UX
:
HP-UX
用变量
tcp_syn_rcvd_max
来定义最大半连接数,在
HP-UX
11.00
中,该值默认为
500
,可以通过
ndd
命令改变默认值:
#
ndd -set /dev/tcp tcp_syn_rcvd_max 2048
■
缩短超时时间
上文提到,通过增大
backlog
队列能防范
SYN
攻击;另外减少超时时间也使系统能处理更多的
SYN
请求。我们知道,
timeout
超时时间,也即半连接存活时间,是系统所有重传次数等待的超时时间总和,这个值越大,半连接数占用
backlog
队列的时间就越长,系统能处理的
SYN
请求就越少。为缩短超时时间,可以通过缩短重传超时时间(一般是第一次重传超时时间)和减少重传次数来实现。
Win2000
第一次重传之前等待时间默认为
3
秒,为改变此默认值,可以通过修改网络接囗在注册表里的
TcpInitialRtt
注册值来完成。重传次数由
TcpMaxConnectResponseRetransmissions
来定义,注册表的位置是:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters registry key
。
当然我们也可以把重传次数设置为
0
次,这样服务器如果在
3
秒内还未收到
ack
确认包就自动从
backlog
队列中删除该连接条目。
LINUX
:
Redhat
使用变量
tcp_synack_retries
定义重传次数,其默认值是
5
次,总超时时间需要
3
分钟。
Sun Solaris Solaris
默认的重传次数是
3
次,总超时时间为
3
分钟,可以通过
ndd
命令修改这些默认值。