这是有关网络地址转换networkaddresstranslationNAT的系列文章中的第二篇之前的第一篇文章介绍了如何使用iptablesnftables的报文跟踪功能来定位NAT相关的连接问题作为第二部分本文介绍
conntrack
命令它允许你查看和修改被跟踪的连接
引言
通过iptables或nftables配置的NAT建立在netfilters连接跟踪子系统之上
conntrack
命令作为conntracktools软件包的一部分用于查看和更改连接状态表
连接跟踪状态表
连接跟踪子系统会跟踪它看到的所有报文流运行
sudoconntrackL
可查看其内容
tcpESTABLISHEDsrc19216825dst10253980sport5646dport443src10253980dst19216825sport443dport5646ASSUREDmark0use1tcp626SYNSENTsrc19216825dst192168210sportdport443UNREPLIEDsrc192168210dst19216825sport443dportmark0use1udp1729src19216881dst239255255250sportdport1900UNREPLIEDsrc239255255250dst19216881sport1900dportmark0use1
上述显示结果中每行表示一个连接跟踪项你可能会注意到每行相同的地址和端口号会出现两次而且第二次出现的源地址端口对和目标地址端口对会与第一次正好相反这是因为每个连接跟踪项会先后两次被插入连接状态表第一个四元组源地址目标地址源端口目标端口记录的是原始方向的连接信息即发送者发送报文的方向而第二个四元组则记录的是连接跟踪子系统期望收到的对端回复报文的连接信息这解决了两个问题
如果报文匹配到一个NAT规则例如IP地址伪装相应的映射信息会记录在链接跟踪项的回复方向部分并自动应用于同一条流的所有后续报文
即使一条流经过了地址或端口的转换也可以成功在连接状态表中查找到回复报文的四元组信息
原始方向的第一个显示的四元组信息永远不会改变它就是发送者发送的连接信息NAT操作只会修改回复方向第二个四元组因为这是接受者看到的连接信息修改第一个四元组没有意义netfilter无法控制发起者的连接状态它只能在收到转发报文时对其施加影响当一个报文未映射到现有连接表项时连接跟踪可以为其新建一个表项对于UDP报文该操作会自动进行对于TCP报文连接跟踪可以配置为只有TCP报文设置了SYN标志位才新建表项默认情况下连接跟踪会允许从流的中间报文开始创建这是为了避免对启用连接跟踪之前就存在的流处理出现问题
连接跟踪状态表和NAT
如上一节所述回复方向的四元组包含NAT信息你可以通过命令过滤输出经过源地址NAT或目标地址NAT的连接跟踪项通过这种方式可以看到一个指定的流经过了哪种类型的NAT转换例如运行
sudoconntrackLptcpsrcnat
可显示经过源NAT的连接跟踪项输出结果类似于以下内容
tcp6114TIMEWAITsrc100010dst108212sport5536dport80src108212dst19216812sport80dport5536ASSURED
这个连接跟踪项表示一条从1000105536到10821280的连接与前面示例不同的是回复方向的四元组不是原始方向四元组的简单翻转源地址已修改目标主机108212将回复数据包发送到19216812而不是100010每当100010发送新的报文时具有此连接跟踪项的路由器会将源地址替换为19216812当108212发送回复报文时该路由器将目的地址修改回100010上述源NAT行为源自一条NFT伪装规则
inetnatpostroutingmetaoifnameveth0masquerade
其他类型的NAT规则例如目标地址DNAT规则或重定向规则其连接跟踪项也会以类似的方式显示回复方向四元组的远端地址或端口与原始方向四元组的远端地址或端口不同
连接跟踪扩展
连接跟踪的记帐功能和时间戳功能是两个有用的扩展功能运行
sudosysctlnetnetfilternfconntrackacct1
可以在运行
sudoconntrackL
时显示每个流经过的字节数和报文数运行
sudosysctlnetnetfilternfconntracktimestamp1
为每个连接记录一个开始时间戳之后每次运行
sudoconntrackL
时都可以显示这个流从开始经过了多少秒在上述命令中增加
outputktimestamp
选项也可以看到流开始的绝对时间
插入和更改连接跟踪项
你可以手动为状态表添加连接跟踪项例如
sudoconntrackIs192168710d10111protonum17timeout120sportdport80
这项命令通常被conntrackd用于状态复制即将主防火墙的连接跟踪项复制到备用防火墙系统于是当切换发生的时候备用系统可以接管已经建立的连接且不会造成中断连接跟踪还可以存储报文的带外元数据例如连接跟踪标记和连接跟踪标签可以用更新选项
U
来修改它们
sudoconntrackUm42ptcp
这条命令将所有的TCP流的连接跟踪标记修改为42
删除连接跟踪项
在某些情况下你可能想从状态表中删除条目例如对NAT规则的修改不会影响表中已存在流的经过报文因此对UDP长连接例如像VXLAN这样的隧道协议删除表项可能很有意义这样新的NAT转换规则才能生效可以通过
sudoconntrackD
命令附带可选的地址和端口列表选项来删除相应的表项如下例所示
sudoconntrackDpudpsrc100124dst10001sport1234dport53
连接跟踪错误计数
conntrack
也可以输出统计数字
sudoconntrackScpu0found0invalid130insert0insertfailed0drop0earlydrop0error0searchrestart10cpu1found0invalid0insert0insertfailed0drop0earlydrop0error0searchrestart0cpu2found0invalid0insert0insertfailed0drop0earlydrop0error0searchrestart1cpu3found0invalid0insert0insertfailed0drop0earlydrop0error0searchrestart0
大多数计数器将为0
Found
和
insert
数将始终为0它们只是为了后向兼容其他错误计数包括
invalid
报文既不匹配已有连接跟踪项也未创建新连接
insertfailed
报文新建了一个连接但插入状态表时失败这在NAT引擎在伪装时恰好选择了重复的源地址和端口时可能出现
drop
报文新建了一个连接但是没有可用的内存为其分配新的状态条目
earlydrop
连接跟踪表已满为了接受新的连接已有的未看到双向报文的连接被丢弃
error
icmpv6收到与已知连接不匹配的icmp错误数据包
searchrestart
查找过程由于另一个CPU的插入或删除操作而中断
clashresolve
多个CPU试图插入相同的连接跟踪条目
除非经常发生这些错误条件通常无害一些错误可以通过针对预期工作负载调整连接跟踪子系统的参数来降低其发生概率典型的配置包括
netnetfilternfconntrackbuckets
和
netnetfilternfconntrackmax
参数可在nfconntracksysctl文档中查阅相应配置参数的完整列表
当报文状态是
invalid
时请使用
sudosysctlnetnetfilternfconntrackloginvalid255
来获取更多信息例如当连接跟踪遇到一个所有TCP标志位均为0的报文时将记录以下内容
nfctproto6invalidtcpflagcombinationSRC10021DST100967LEN1040TOS0x00PREC0x00TTL255ID0PROTOTCPSPT5723DPT443SEQ1ACK0
总结
本文介绍了如何检查连接跟踪表和存储在跟踪流中的NAT信息本系列的下一部分将延伸讨论连接跟踪工具和连接跟踪事件框架
via作者FlorianWestphal选题lujun9972译者cooljelly校对wxy
本文由LCTT原创编译Linux中国荣誉推出