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: 在对数据包作路由选择之后,应用该链上的对应规则(表)。
来张鸟哥的经典图
四表
即每个链中存储的规则,数据包到了每个链点的时候,就会去对应的表中查询对应的规则,来判断数据包的行为(是否转发, 丢弃,过滤等)
- Raw表:决定数据包是否被状态跟踪机制处理。
- Mangle表:修改数据包的服务类型、TTL、并且可以配置路由实现QOS
- Nat表: 用于网络地址转换(IP、端口)
- Filter表: 过滤数据包
- 四表的优先级自上而下
表和链的对应关系:
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
待续…