网络---socket耗尽问题

SYN Flood攻击又称DOS(Denial Of Service),一般是指伪造客户端ip发送大量的syn包,服务端收到syn包后响应syn+ack根本无法到达客户端,服务端重发syn+ack,这个过程中socket处于半链接状态SYN_RECV,并占用一个半链接队列单元。半链接状态的socket足够多时,会将半连接队列耗光,导致后续syn包直接丢弃。

即使没有攻击,网络状态很差情况,服务端处发送syn+ack后到收到ack间隔时间过长,同样会积累大量的SYN_RECV的链路,导致半链接状态耗尽,同样会导致丢弃syn请求。

解决这个问题的方法:

方法1:修改参数,扩大实际的半链接队列,修改后需要重启服务进程。

listen(backlog)

{

somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;

if ((unsigned)backlog > somaxconn)     

backlog = somaxconn;

inet_listen->inet_csk_listen_start(sk, backlog);

nr_table_entries = min( backlog, sysctl_max_syn_backlog);

nr_table_entries = max( nr_table_entries, 8);

nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); // nr_table_entries 是半连接队列的长度

sk->sk_max_ack_backlog = backlog; //这里确定了accept queue的长度。

}

backlog为listen()的第二个参数;

sysctl_max_syn_backlog为系统配置net.ipv4.tcp_max_syn_backlog;

sock_net(sock->sk)->core.sysctl_somaxconn为系统配置net.core.somaxconn;

方法2:

echo 1 > /proc/sys/net/ipv4/tcp_syncookies,开启syncookies功能,立即生效。tcp_syncookies开启后,协议栈开辟一个hash结构,记录每个半连接状态的socket,不再使用半连接队列保存socket,当ack到达后可以从hash结构中恢复链路。这样规避了半连接队列耗尽问题。

Aix、Sun系统默认开启syncache功能,linux只有syncookies功能,不推荐使用,默认也不会开启。

你可能感兴趣的:(网络---socket耗尽问题)