SYN Flood是流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,塞满TCP等待连接队列,导致资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来,从而间接达到攻击的目的。
SYN Flood攻击利用的正是IPv4中TCP协议的三次握手过程进行的攻击。如果一端想向另一端发起TCP连接,它需要首先发送TCP SYN 包到对方,对方收到后发送一个TCP SYN+ACK包回来,发起方再发送TCP ACK包回去,这样三次握手就结束了。
我们把TCP连接的发起方叫作"TCP客户机(TCP Client)",TCP连接的接收方叫作"TCP服务器(TCP Server)"。值得注意的是在TCP服务器收到TCP SYN request包时,在发送TCP SYN+ACK包回TCP客户机前,TCP服务器要先分配好一个数据区专门服务于这个即将形成的TCP连接。一般把收到SYN包而还未收到ACK包时的连接状态成为半开连接(Half-open Connection)。
在最常见的SYN Flood攻击中,攻击者在短时间内发送大量的TCP SYN包给受害者,这时攻击者是TCP客户机,受害者是TCP服务器。根据上面的描述,受害者会为每个TCP SYN包分配一个特定的数据区,只要这些SYN包具有不同的源地址(这一点对于攻击者来说是很容易伪造的)。这将给TCP服务器系统造成很大的系统负担,最终导致系统不能正常工作。?
1、netstat -s来查看SYNs to LISTEN sockets dropped是否持续增长。message日志是否持续报flooding相关的报错。
2、打开tcp cookie的功能
这个cookie是指SYN Cookie。在目前以IPv4为支撑的网络协议上搭建的网络环境中,SYN Flood是一种非常危险而常见的DoS攻击方式。到目前为止,能够有效防范SYN Flood攻击的手段并不多,而SYN Cookie就是其中最著名的一种。SYN Cookie原理由D.J.Bernstain和Eric Schenk发明。在很多操作系统上都有各种各样的实现。
syn_cookies的官方介绍:
? 官方文档说明了当看到有SYN flood warning的时候并不一定真的是flooded,有可能是你的服务器没有正确的配置。同理,有时你的服务器有此报警的时候也并不一定是真的有attack,这时考虑需要你调整你的内核参数tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow。
3、用tcpdump抓包,如果有很多SYN,服务端回复了SYN+ACK,但客户端没有回复ACK,那么这可能就是恶意流量。如果恶意流量很大导致服务不可用,可对抓取到的可疑源端地址进行流量紧急封堵。
如果流量是正常流量的话,可以考虑优化调整内核参数可以调整内核的三个参数:tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow
tcp_max_syn_backlog变量告诉你在内存中可以缓存多少个SYN请求。该变量需要打开tcp_syncookies才有效。如果服务器负载很高,可以尝试提高该变量的值。
tcp_synack_retries变量用于TCP三次握手机制中第二次握手,当收到客户端发来的SYN连接请求后,服务端将回复SYN+ACK包,这时服务端处于SYN_RCVD状态,并等 待客户端发来的回复ACK包。如果服务端没有收到客户端的ACK包,会重新发送SYN+ACK包,直到收到客户端的ACK包。该变量设置发送 SYN+ACK包的次数,超过这个次数,服务端将放弃连接。默认值是5。
tcp_abort_on_overflow变量的值是个布尔值,默认值为0(FALSE关闭)。如果开启,当服务端接收新连接的速度变慢时,服务端会发送RST包(reset包)给客户端,令客户端 重新连接。这意味着如果突然发生溢出,将重获连接。仅当你真的确定不能通过调整监听进程使接收连接的速度变快,可以启用该选项。该选项也会影响到客户的连接。
net/ipv4/tcp_input.c
static bool tcp_syn_flood_action(const struct sock *sk,
?? ??? ??? ??? ?const struct sk_buff *skb,
?? ??? ??? ??? ?const char *proto)
{
?? ?struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
?? ?const char *msg = "Dropping request";
?? ?bool want_cookie = false;
?? ?struct net *net = sock_net(sk);
#ifdef CONFIG_SYN_COOKIES
?? ?if (net->ipv4.sysctl_tcp_syncookies) {
?? ??? ?msg = "Sending cookies";
?? ??? ?want_cookie = true;
?? ??? ?__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
?? ?} else
#endif
?? ??? ?__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
?? ?if (!queue->synflood_warned &&
?? ?net->ipv4.sysctl_tcp_syncookies != 2 &&
?? ?xchg(&queue->synflood_warned, 1) == 0)
?? ??? ?pr_info("%s: Possible SYN flooding on port %d. %s. ?Check SNMP counters.\n",
?? ??? ??? ?proto, ntohs(tcp_hdr(skb)->dest), msg);
?? ?return want_cookie;
}