/proc/net/nf_contrack 是连接跟踪文件,它里面的内容由 nf_conntrack.ko 模块写入。在 iptables 中使用 -m state 选项时,iptables 不但加载 xt_state.ko 模块,且 nf_conntrack.ko 模块也会被加载进来。一般而言,xt_state.ko 和 nf_conntrack.ko 这两个模块在许多 Linux 发行版里是默认编译进内核的。
下面通过几个试验来浅析一下 nf_conntrack 中的内容。
先打开一个已经连接不上了的网站,然后查看一下该文件内容:

[root@beyes   beyes]# cat /proc/net/nf_conntrack  

ipv4     2 udp      17 168 src=192.168.1.104 dst=192.168.1.1 sport=53221 dport=53 src=192.168.1.1 dst=192.168.1.104 sport=53 dport=53221 [ASSURED] mark=0 zone=0 use=2  
ipv4     2 tcp      6 115 SYN_SENT src=192.168.1.104 dst=66.85.191.46 sport=49535 dport=80 [UNREPLIED] src=66.85.191.46 dst=192.168.1.104 sport=80 dport=49535 mark=0 zone=0 use=2  
ipv4     2 tcp      6 116 SYN_SENT src=192.168.1.104 dst=66.85.191.46 sport=49536 dport=80 [UNREPLIED] src=66.85.191.46 dst=192.168.1.104 sport=80 dport=49536 mark=0 zone=0 use=2  
ipv4     2 udp      17 19 src=192.168.1.104 dst=192.168.1.1 sport=43652 dport=53 src=192.168.1.1 dst=192.168.1.104 sport=53 dport=43652 mark=0 zone=0 use=2  

将上面的每一行,根据每个空白所分隔作为一个字段,比如第 1 个字段是 ipv4,第 2 个字段是 2,第 3 个字段是 udp 等。
首先看第 1 条记录
该条记录主要是描述 DNS 解析的。首先客户端对服务器发出一个请求包,当这个数据报到达防火墙时,该连接在 state 模块里就认为是 NEW 状态,因此, nf_conntrack 模块随即将该连接信息添加到 /proc/net/nf_contrack 文件中来。下面是主要字段的说明:
第 3 个字段表示使用 udp 协议。
第 4 个字段中的 17 表示 udp 的协议编号,可以在 /etc/protocols 文件中查询到。
第 6 和 第 7 个字段 src=192.168.1.104 dst=192.168.1.1 分别指出了发出 udp 包的源地址 192.168.1.104 和发往的目的地址 192.168.1.1 。这里需要说明的是,我这里的上网环境是路由器拨号,个人计算机接在路由器上。因此,对于客户机来说,路由器192.168.1.1 是一个 DNS,而真正的 DNS 是在路由器里设置的,比如可以自动获取 ISP 所提供的 IP 或者自定义一个。
第 8 到第 13 个字段指出了客户机和路由器的 IP 地址,以及通讯时所用的端口,DNS 服务器使用 53 端口,客户机则随机使用。
第 14 个字段 [ASSURED] 表示客户端和路由器之间的连接已经确认。
第 5 个字段的值关系到两个文件,一个是 /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream ,另一个是 /proc/sys/net/netfilter/nf_conntrack_udp_timeout 。第 1 个文件中的值是 180,第 2 个文件中的值是 30 。像上面第 1 条 DNS 查询记录,当建立连接后,连接记录就会写到 /proc/net/nf_contrack 文件中,然后就开始从 180 秒(nf_conntrack_udp_timeout_stream)倒计时,如果时间到那么就将该条记录从文件中删除。如果 DNS 查询在发出后的 30 秒(nf_conntrack_udp_timeout)内还不能得到服务器的回应,那么也会删除掉该条记录,注意若是这种情况,那第 14 个字段的值为 [UNREPLIED],表示服务器不响应客户端。
再看第 2, 第 3 条记录
在了解了上面的第 1 条记录后,第 2, 第 3 条记录的解释也就大同小异了。注意看到,它的第 14 个字段的值是 [UNREPLIED] ,表示服务器无法响应客户端的请求。另外,第 6 个字段 SYN_SENT 表示连接状态。在 TCP 协议中,在客户端发送带有 SYN 标记的数据包后,这条 TCP 的连接状态就会设置为 SYN_SENT (顾名思义,已经发送了 SYN),当这个带有 SYN 标记的数据包送达防火墙时,防火墙上的 TCP 连接状态也会设置为 SYN_SENT,而对于 state 模块来说,则是 NEW 状态。接着,服务器的应答数据包里会带有 SYN 和 ACK 标记,如果能收到该应答包,那么 TCP 的连接就进入 SYN_RECV 状态。如果没有等到服务器的应答,那么防火墙就必须根据第 5 个字段的信息来处理这条连接。
第 5 个字段和上面的 UDP 的一样,也是一个时间值。它表示,如果客户端在超过 120 秒后还无法得到服务器端的应答,那么该连接状态在防火墙上就要被清除。这个 120 秒是由 /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_syn_sent 文件所给出。
当服务器对 SYN 请求发出应答数据包时,TCP 连接进入 SYN_RECV 状态,当应答数据包通过防火墙时,防火墙在 nf_conntrack 文件中也会将状态更新为 SYN_RECV。此时,对于 state 模块来说,它就是一个 ESTABLISHED 状态了。如果客户端不能接着响应服务器,那么防火墙在 60 秒后会清除该连接记录,这个 60 秒是由 /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_syn_recv 文件所给出的。
最后,当客户端和服务器端完成三次握手 后,nf_conntrack 模块也会将 /proc/net/nf_contrack 文件中的连接信息更新为 ESTABLISHED。注意,这里的 ESTABLISHED 状态是 TCP 连接状态,而不是 state 模块所描述的 ESTABLISHED 状态,state 的 “连接” 状态已经在TCP 的 SYN_RECV 时已经设立。当 TCP 的 ESTABLISHED 状态建立后,客户端和服务器就通过该条连接传输数据与通讯。如果在连接建立后,但一直没有传输任何数据包,那么防火墙会在 432000 秒之后清除该条记录,此时客户端和服务器端的连接将被迫中断。432000 这个时间值由 /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established 这个文件给出。如果在此时间内,如果又有数据传输,那么这个值又自动恢复为 432000 自动延续生命周期。

原文:https://ciaos.iteye.com/blog/2160416