从iptables 到 nf_conntrack(1)

Big Picture1

公司的监控服务器开启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 表,从而可能会导致上述情况。

Big Picture2

公司kubernetes 网络网络需要改为calico,在calico的单个AS范围是TOR还是IDC产生了分歧,公司一架构师担心路由增多会导致conntrack 表爆满,乍一听觉得很别扭,为啥路由表和conntrack 有关了,但又不能立刻反驳,毕竟可能我只站在第二层,这个架构师已站在第五层了,所以先复习一下conntrack的相关知识,避免被打脸。

Netfilter 和 iptables

Netfilter是一个内核架构,是集成到linux内核协议栈的一套防火墙系统,而iptables 是用户态的一个工具,通过cli 将配置下发给内核态的netfilter, 所以我们常说的iptables ,全程应该是netfilter/iptables 比较恰当,就当复习了,先从iptables的4表5链开始:

五链

内核在网络上定义的五个钩子(hook),进路由(PRE-ROUTING), 进系统(INPUT), 转发(FORWARD), 出系统(OUTPUT), 出路由(POST-ROUTING),每个hook上会有各自的hook 函数负责对数据包的处理,hook 函数有各自的优先级,基于优先级,顺序执行这些hook函数。

  • PRE-ROUTING: 在对数据包作路由选择之前,应用该链上的对应规则(表)。
  • INPUT: 处理入站数据包,应用该链上的对应规则(表)。
  • OUTPUT: 处理出站数据包,应用该链上的对应规则(表)。
  • FORWAR链: 处理转发数据包,应用该链上的对应规则(表)。
  • POST-ROUTING: 在对数据包作路由选择之后,应用该链上的对应规则(表)。

来张鸟哥的经典图
从iptables 到 nf_conntrack(1)

四表

即每个链中存储的规则,数据包到了每个链点的时候,就会去对应的表中查询对应的规则,来判断数据包的行为(是否转发, 丢弃,过滤等)

  • Raw表:决定数据包是否被状态跟踪机制处理。
  • Mangle表:修改数据包的服务类型、TTL、并且可以配置路由实现QOS
  • Nat表: 用于网络地址转换(IP、端口)
  • Filter表: 过滤数据包
  • 四表的优先级自上而下

表和链的对应关系:

从iptables 到 nf_conntrack(1)

nf_conntrack

上面只是复习了下iptables的基础,现在才是容易导致故障的重头,即nf_conntrack,nf_conntrack 并不是所有网络协议都会追踪,目前只有TCP、UDP、ICMP、DCCP、SCTP、GRE这6种。


对于conntrack 追踪的数据包,一共有五种状态:

  • NEW: NEW匹配连接的第一个包, 比如tcp 链接的SYN包就可以算做NEW状态。
  • ESTABLISHED: ESTABLISHED匹配连接的响应包及后续的包。比如TCP三次握手中的ACK包,就可以看做是ESTABLISHED状态。
  • RELATED: 这个有点复杂,RELATED 状态意思是需要和一个状态为ESTABLISHED的链接发生关系,我的理解是比如A与B 建立了链接,然后A收到请求后,反向链接B进行数据传输,这个独立出来用作传输的链接就可以算做RELATED,上面的描述比较抽象,但想一想GRE,VXLAN 这种overlay网络,会好理解一点。
  • INVALID: INVALID匹配那些无法识别或没有任何状态的数据包, 一般情况下我们应该DROP此类状态的包。
  • UNTRACKED: UNTRACKED状态比较简单,它匹配那些带有 NOTRACK 标签的数据包。

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

待续…

个人公众号, 分享一些日常开发,运维工作中的日常以及一些学习感悟,欢迎大家互相学习,交流

从iptables 到 nf_conntrack(1)

上一篇:网络连接导致的性能问题


下一篇:Netfilter 是如何工作的(一):HOOK点