/var/log/messages报错信息:kernel: nf_conntrack: table full, dropping packet

问题背景:公司线上活动(可以理解为秒杀)瞬时流量比平时高好几倍,目前最高瞬时流量为25W/秒(requests),最低时瞬时流量为6W/秒(requests)
/var/log/messages日志一直报上述错误,直到活动结束

当时,深刻了解到iptables的这个报错,会造成拒绝服务的问题。查资料后,需要关闭iptables,但服务器在阿里云VPC网络内,使用的是阿里云的安全组策略,故iptables没有打开。后排查,虽iptables和firewalld没开,但是Centos7 还是加载了这个nf_conntrack模块,而导致出现了上面这个问题。

网上说有三种方法,分别为:

  • 修改参数法
  • 使用RAW表,跳过记录法
  • 移除模块法

因服务器没有使用iptables和firewalld,故采用的是移除模块法

1
2
3
4
5
6
7
# /sbin/lsmod | egrep 'ip_tables|conntrack'
nf_conntrack_ipv4 19108 2
nf_defrag_ipv4 12729 1 nf_conntrack_ipv4
xt_conntrack 12760 1
nf_conntrack 111302 5 nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_ipv4
ip_tables 27115 2 iptable_filter,iptable_nat
#

state模块和nf_conntrack之间是有依赖关系,想要卸载nf_conntrack模块的话,必须也要把state模块移除,不然,其会自动启用nf_conntrack模块。

卸载模块前需要先关闭iptables和firewalld,如果发现firewalld或iptables没有启用,但是卸载模块时,还是提示模块正在使用,则把iptables或firewalld启动后再关闭,再尝试卸载模块。

操作方法如下:

  • 先将/etc/sysconfig/iptables 中包含state的语句移除,并restart iptables
  • 执行语句
    1
    2
    3
    4
    5
    6
    7
    #这里是参考文档作者的
    modprobe -r xt_NOTRACK nf_conntrack_netbios_ns nf_conntrack_ipv4 xt_state
    modprobe -r nf_conntrack
    #这里是我实际卸载的模块
    modprobe -r nf_conntrack_netbios_ns xt_state
    modprobe -r nf_conntrack

执行完查看/proc/net/ 下面如果没用了 nf_conntrack ,就证明模块移除成功了

总结(以下摘录原文作者):
以上三种方法种,如果像web这样的操作访问量并发不大的情况下,建议通过第一种方法实现。因为nf_conntrack模块的作用不仅仅只用于记录状态,iptables还可以通过对该模块的使有达到动态过滤的作用。如我在用ab动测试的一台服务器上进行并发模拟时,在/var/log/message里发现如下的日志

1
2
Apr 22 15:21:46 localhost kernel: possible SYN flooding on port 80. Sending cookies.
Apr 22 15:22:46 localhost kernel: possible SYN flooding on port 80. Sending cookies.

而此时iptables会智能的将发动SYN flood攻击的IP暂时拒绝掉

1
2
3
4
5
6
7
# ab -c 500 -n 5000 "http://192.168.10.177/"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.10.177 (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 68 requests completed

如上所以,我用ab操作时,其就会收到apr_socket_recv 的错误提示 。我在网上查询到其具体实现的原理如下:

  • 传统的防火墙只能进行静态过滤,而 iptables 除了这个基本的功能之外还可以进行动态过滤,即可以对连接状态进行跟踪,通常称为 conntrack 。 但这不意味着它只能对 TCP 这样的面向连接的协议有效,它还可以对 UDP, ICMP 这种无连接的协议进行跟踪。

  • iptables 中的连接跟踪是通过 state 模块来实现的,是在PREROUTING 链中完成的,除了本地主机产生的数据包,它们是在 OUTPUT 链中完成。 它把“连接”划分为四种状态:NEW, ESTABLISHED, RELATED 和 INVALID。连接跟踪当前的所有连接状态可以通过 /proc/net/nf_conntrack 来查看(注意,在一些稍微旧的 Linux 系统上是 /proc/net/ip_conntrack)

  • 当 conntrack 第一次看到相关的数据包时,就会把状态标记为 NEW ,比如 TCP 协议中收到第一个 SYN 数据包。当连接的双方都有数据包收发并且还将继续匹配到这些数据包时,连接状态就会变为 ESTABLISHED 。而 RELATED 状态是指一个新的连接,但这个连接和某个已知的连接有关系,比如 FTP 协议中的数据传输连接。INVALID 状态是说数据包和已知的任何连接都不匹配

当然,仅仅利用iptables conntrack自动实现syn flood 等DDOS攻击时很弱的。而现成的动态过滤和DDOS防护的方法是很多的。比如netstat脚本实现,iptalbes限制每秒进行连接数,nginx/apache的连接数限制模块及fail2ban日志分析法………… ,所以在具有以上防护的情况下,非常推荐将web 、squid/varnish等应用所在的服务器配置为RAW方式 。我在现网一台150M/S 的cache server上将80和3128两个端口全部NOTRACK之后,conntrack hash表由瞬满直线下降到只有几百条。
最后,最不推荐使用的第三种方法,因为第三种方法会将state模块也一块儿移除掉。

参考:
http://www.361way.com/ip_conntrack-tablefull/1717.html
http://www.361way.com/%E5%86%8D%E7%9C%8Bnf_conntrack-table-full%E9%97%AE%E9%A2%98/2404.html
http://jaseywang.me/2012/08/16/%E8%A7%A3%E5%86%B3-nf_conntrack-table-full-dropping-packet-%E7%9A%84%E5%87%A0%E7%A7%8D%E6%80%9D%E8%B7%AF/
https://wiki.khnet.info/index.php/Conntrack_tuning
http://blog.zol.com.cn/2608/article_2607945.html
http://blog.csdn.net/dog250/article/details/7262619


本文出自”Jack Wang Blog”:http://www.yfshare.vip/2017/12/05/关于kernel-nf-conntrack-table-full-dropping-packet问题/