nf_conntrack: table full, dropping packet

nf_conntrack:tablefull,droppingpacket连接跟踪表已满,开始丢包的解决办法

通过网上的一些解决方案和自己实践整理。原笔记地址

https://app.yinxiang.com/shard/s20/nl/2313278/34844067-6ff4-4091-adb0-36bc25fbfad8?title=nf_conntrack%3A%20table%20full%2C%20dropping%20packet

一、关闭防火墙。简单粗暴,直接有效

#/etc/init.d/iptablesstopcentos

#/etc/init.d/SuSEfirewall2_setupstopsuse

切记:在防火墙关闭状态下,不要通过iptables指令(比如iptables-nL)来查看当前状态!因为这样会导致防火墙被启动,而且规则为空。虽然不会有任何拦截效果,但所有连接状态都会被记录,浪费资源且影响性能并可能导致防火墙主动丢包!

二、加大防火墙跟踪表的大小,优化对应的系统参数

1、状态跟踪表的最大行数的设定,理论最大值

CONNTRACK_MAX=RAMSIZE(inbytes)/16384/(ARCH/32)

以64G的64位操作系统为例

CONNTRACK_MAX=64*1024*1024*1024/16384/2=2097152

即时生效请执行:

sysctl-wnet.netfilter.nf_conntrack_max=2100000

或者

vi/etc/sysctl.conf

net.netfilter.nf_conntrack_max=2100000

sysctl-p

2、其哈希表大小通常为总表的1/8,最大为1/2。

CONNTRACK_BUCKETS=CONNTRACK_MAX/8

同样64G的64位操作系统,哈希最佳范围是262144~1048576。

运行状态中查看

sysctlnet.netfilter.nf_conntrack_buckets

通过文件/sys/module/nf_conntrack/parameters/hashsize进行设置。

或者新建/etc/modprobe.d/iptables.conf,重新加载模块才生效:

optionsnf_conntrackhashsize=262144

3、还有些相关的系统参数`sysctl-a|grepnf_conntrack`可以调优(/etc/sysctl.conf):

net.netfilter.nf_conntrack_max=1048576

net.netfilter.ip_conntrack_tcp_timeout_established=3600

net.netfilter.nf_conntrack_tcp_timeout_close_wait=60

net.netfilter.nf_conntrack_tcp_timeout_fin_wait=120

net.netfilter.nf_conntrack_tcp_timeout_time_wait=120

三、使用raw表,添加“不跟踪”标识。如下示例更适合桌面系统或随意性强的服务器。因为它开启了连接的状态机制,方便和外部通信。修改/etc/sysconfig/iptables文件:

eden蓝色部份是在centos机器默认规则中添加的。

#Firewallconfigurationwrittenbysystem-config-firewall

#Manualcustomizationofthisfileisnotrecommended.

*raw

-APREROUTING-ptcp-mtcp--dport8080-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport8080-jNOTRACK

COMMIT

#filter表里存在但在raw里不存在的,默认会进行连接状态跟踪

*filter

:INPUTACCEPT[0:0]

:FORWARDACCEPT[0:0]

:OUTPUTACCEPT[0:0]

-AINPUT-mstate--stateESTABLISHED,RELATED,INVALID,UNTRACKED-jACCEPT

-AINPUT-picmp-jACCEPT

-AINPUT-ilo-jACCEPT

-AINPUT-mstate--stateNEW-mtcp-ptcp--dport22-jACCEPT

-AINPUT-mstate--stateNEW-mtcp-ptcp--dport3306-jACCEPT

-AINPUT-mstate--stateNEW-mtcp-ptcp--dport80:82-jACCEPT

-AINPUT-mstate--stateNEW-mtcp-ptcp--dport8080-jACCEPT

-AINPUT-jREJECT--reject-withicmp-host-prohibited

-AFORWARD-jREJECT--reject-withicmp-host-prohibited

COMMIT

*raw

#对TCP连接不启用追踪,解决ip_contrack满导致无法连接的问题

-APREROUTING-ptcp-mtcp--dport80-jNOTRACK

-APREROUTING-ptcp-mtcp--dport22-jNOTRACK

-APREROUTING-ptcp-mtcp--dport21-jNOTRACK

-APREROUTING-ptcp-mtcp--dport11211-jNOTRACK

-APREROUTING-ptcp-mtcp--dport60000:60100-jNOTRACK

-APREROUTING-ptcp-s192.168.10.1-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport80-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport22-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport21-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport11211-jNOTRACK

-AOUTPUT-ptcp-mtcp--sport60000:60100-jNOTRACK

-AOUTPUT-ptcp-s192.168.10.1-jNOTRACK

COMMIT

*filter

#允许ping

-AINPUT-picmp-jACCEPT

#对本地回路、第5张网卡放行

-AINPUT-ilo-jACCEPT

-AINPUT-ieth4-jACCEPT

#连接状态跟踪,已建立的连接允许传输数据

-AINPUT-mstate--stateESTABLISHED,RELATED,INVALID,UNTRACKED-jACCEPT

#filter表里存在但在raw里不存在的,默认会进行连接状态跟踪

-AINPUT-s192.168.10.31-ptcp--dport2669-jACCEPT

-AINPUT-jREJECT--reject-withicmp-host-prohibited

-AFORWARD-jREJECT--reject-withicmp-host-prohibited

COMMIT

或者干脆对所有连接都关闭跟踪,不跟踪任何连接状态。不过规则就限制比较严谨,进出都需要显式申明。示例如下:

*raw

#对TCP/UDP连接不启用追踪,解决nf_contrack满导致无法连接的问题

-APREROUTING-ptcp-jNOTRACK

-APREROUTING-pudp-jNOTRACK

-AOUTPUT-ptcp-jNOTRACK

-AOUTPUT-pudp-jNOTRACK

COMMIT

*filter

#允许ping

-AINPUT-picmp-jACCEPT

#对本地回路和eth1放行

-AINPUT-ilo-jACCEPT

-AINPUT-ieth1-jACCEPT

#只允许符合条件的连接进行传输数据

-AINPUT-ptcp--dport22-jACCEPT

-AINPUT-ptcp--sport80-jACCEPT

-AINPUT-pudp--sport53-jACCEPT

-AINPUT-pudp--sport123-jACCEPT

#出去的包都不限制

-AOUTPUT-ptcp-jACCEPT

-AOUTPUT-pudp-jACCEPT

#输入和转发的包不符合规则的全拦截

-AINPUT-jREJECT--reject-withicmp-host-prohibited

-AFORWARD-jREJECT--reject-withicmp-host-prohibited

COMMIT

效果如下图:

四、删除连接跟踪模块`lsmod|grepnf_conntrack`,不使用连接状态的跟踪功能。

1、删除nf_conntrack和相关的依赖模块,示例:

rmmodnf_conntrack_ipv4

rmmodnf_conntrack_ipv6

rmmodxt_state

rmmodxt_CT

rmmodxt_conntrack

rmmodiptable_nat

rmmodipt_REDIRECT

rmmodnf_nat

rmmodnf_conntrack

2、禁用跟踪模块,把它加到黑名单(/etc/modprobe.d/blacklist.conf):

#禁用nf_conntrack模块

blacklistnf_conntrack

blacklistnf_conntrack_ipv6

blacklistxt_conntrack

blacklistnf_conntrack_ftp

blacklistxt_state

blacklistiptable_nat

blacklistipt_REDIRECT

blacklistnf_nat

blacklistnf_conntrack_ipv4

3、去掉防火墙里所有和状态相关的配置(比如state状态,NAT功能),示例:

*filter

#允许ping

-AINPUT-picmp-jACCEPT

#对本地回路和第2张网卡放行

-AINPUT-ilo-jACCEPT

-AINPUT-ieth1-jACCEPT

#对端口放行

-AINPUT-ptcp--dport1331-jACCEPT

#对IP放行

-AINPUT-s192.168.10.31-jACCEPT

#允许本机进行DNS查询

-AINPUT-pudp--sport53-jACCEPT

-AOUTPUT-pudp-jACCEPT

-AINPUT-jREJECT--reject-withicmp-host-prohibited

-AFORWARD-jREJECT--reject-withicmp-host-prohibited

COMMIT

另外,防火墙的配置文件最好也改下,不要加载任何额外模块(/etc/sysconfig/iptables-config):

IPTABLES_MODULES=""#不需要任何附加模块

IPTABLES_MODULES_UNLOAD="no"#避免iptables重启后sysctl中对应的参数被重置为系统默认值

IPTABLES_SAVE_ON_STOP="no"

IPTABLES_SAVE_ON_RESTART="no"

IPTABLES_SAVE_COUNTER="no"

IPTABLES_STATUS_NUMERIC="yes"

IPTABLES_STATUS_VERBOSE="no"

IPTABLES_STATUS_LINENUMBERS="no"

往往我们对连接的跟踪都是基于操作系统的(netstat/ss),防火墙的连接状态完全是它自身实现产生的。