公司的监控服务器开启ipatbles 以后,经常会报kernel: nf_conntrack: nf_conntrack: table full, dropping packet的内核报错,原因是conntrack 表满了,常规的做法是以下几种:
sysctl –w net.netfilter.nf_conntrack_max = 2097152 #状态跟踪表的最大行数的设定 sysctl -w net.netfilter.nf_conntrack_buckets = 1048576 #修改哈希表大小 # 还可以修改一些conntrack_tcp_timeout_fin_wait之类的建链/wait 等的超时时间等 # 卸载/禁用模块 rmmod nf_conntrack_ipv4 rmmod nf_conntrack_ipv6 rmmod xt_state rmmod xt_CT rmmod xt_conntrack rmmod iptable_nat rmmod ipt_REDIRECT rmmod nf_nat rmmod nf_conntrack ------ blacklist nf_conntrack blacklist nf_conntrack_ipv6 blacklist xt_conntrack blacklist nf_conntrack_ftp blacklist xt_state blacklist iptable_nat blacklist ipt_REDIRECT blacklist nf_nat blacklist nf_conntrack_ipv4 # 或者iptables策略直接禁止追踪 -A PREROUTING -p tcp -j NOTRACK -A PREROUTING -p udp -j NOTRACK -A OUTPUT -p tcp -j NOTRACK -A OUTPUT -p udp -j NOTRACK
- 在防火墙关闭状态下,不要通过iptables指令(比如 iptables -nL)来查看当前状态, 因为这样会导致防火墙被启动,而且规则为空。虽然不会有任何拦截效果,但所有的链接依然会进入conntrack 表,从而可能会导致上述情况。
公司kubernetes 网络网络需要改为calico,在calico的单个AS范围是TOR还是IDC产生了分歧,公司一架构师担心路由增多会导致conntrack 表爆满,乍一听觉得很别扭,为啥路由表和conntrack 有关了,但又不能立刻反驳,毕竟可能我只站在第二层,这个架构师已站在第五层了,所以先复习一下conntrack的相关知识,避免被打脸。
Netfilter是一个内核架构,是集成到linux内核协议栈的一套防火墙系统,而iptables 是用户态的一个工具,通过cli 将配置下发给内核态的netfilter, 所以我们常说的iptables ,全程应该是netfilter/iptables 比较恰当,就当复习了,先从iptables的4表5链开始:
内核在网络上定义的五个钩子(hook),进路由(PRE-ROUTING), 进系统(INPUT), 转发(FORWARD), 出系统(OUTPUT), 出路由(POST-ROUTING),每个hook上会有各自的hook 函数负责对数据包的处理,hook 函数有各自的优先级,基于优先级,顺序执行这些hook函数。
来张鸟哥的经典图
即每个链中存储的规则,数据包到了每个链点的时候,就会去对应的表中查询对应的规则,来判断数据包的行为(是否转发, 丢弃,过滤等)
- 四表的优先级自上而下
表和链的对应关系:
上面只是复习了下iptables的基础,现在才是容易导致故障的重头,即nf_conntrack,nf_conntrack 并不是所有网络协议都会追踪,目前只有TCP、UDP、ICMP、DCCP、SCTP、GRE这6种。
对于conntrack 追踪的数据包,一共有五种状态:
conntrack的数据结构有点复杂,后续再具体学习代码分析下,先看下一般情况下如何管理这些conntrack:
查看当前conntrack 追踪的链接
[root@dev001 ~]# cat /proc/net/nf_conntrack | wc -l 157 [root@dev001 ~]# cat /proc/net/nf_conntrack | head -n 1 ipv4 2 tcp 6 86390 ESTABLISHED src=127.0.0.1 dst=127.0.0.1 sport=45506 dport=2379 src=127.0.0.1 dst=127.0.0.1 sport=2379 dport=45506 [ASSURED] mark=0 zone=0 use=2 #网络层协议名、网络层协议编号、传输层协议名、传输层协议编号、记录失效前剩余秒数、连接状态(不是所有协议都有),[ASSURED] 请求和响应都有流量,[UNREPLIED] 没收到响应,哈希表满的时候这些连接先扔掉 [root@dev001 ~]#
查看当前conntrack hash表里的实时连接跟踪数
[root@dev001 ~]# sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_count = 166
比较下来发现count比cat /proc/net/nf_conntrack | wc -l 条目数大,这是因为nf_conntrack里面保存的都是正式追踪的链接,而count 里面记录了所有追踪的链接,包含了Unconfirm里面的链接。
conntrack hash表的大小
[root@dev001 ~]# sysctl net.netfilter.nf_conntrack_buckets net.netfilter.nf_conntrack_buckets = 16384
64位系统,8G内存默认 65536, 16G翻倍,如此类推,另外netfilter是内核态的,所以不能存在swap
能够追踪的最大条目
[root@dev001 ~]# sysctl net.netfilter.nf_conntrack_max net.netfilter.nf_conntrack_max = 131072 [root@dev001 ~]# sysctl net.nf_conntrack_max net.nf_conntrack_max = 131072 > 默认nf_conntrack_buckets * 4
待续…