强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

iptables 完全指南 / 第 10 章:连接跟踪机制

第 10 章:连接跟踪机制

本章目标:深入理解 Linux 连接跟踪(conntrack)的状态机,掌握 ESTABLISHED、RELATED、NEW、INVALID 四种状态的含义,学会使用 conntrack 工具调试连接问题。


10.1 连接跟踪概述

连接跟踪(Connection Tracking)是 Netfilter 框架的核心模块,它为每个经过防火墙的网络连接维护一条状态记录。通过连接跟踪,防火墙能够:

  • 有状态过滤:只检查新连接的第一个包,后续包自动放行
  • NAT 支持:NAT 依赖连接跟踪记录地址转换映射
  • 协议辅助:跟踪 FTP、SIP 等多连接协议的关联连接

10.1.1 连接跟踪在数据包处理中的位置

数据包进入
    │
    ▼
┌──────────────┐
│ raw 表        │ ← 可在此跳过连接跟踪(NOTRACK)
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ conntrack    │ ← 创建/查找/更新连接跟踪条目
│ (NEW/ESTABLISHED/
│  RELATED/INVALID)
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ mangle 表     │
│ nat 表        │ ← NAT 使用连接跟踪记录
│ filter 表     │ ← filter 表使用 conntrack 状态匹配
└──────────────┘

10.2 连接状态详解

10.2.1 四种连接状态

状态含义触发条件
NEW新连接的第一个包conntrack 表中没有该连接的记录
ESTABLISHED已建立连接的后续包conntrack 表中已有该连接的双向通信记录
RELATED与已有连接相关的新连接辅助模块识别的关联连接(如 FTP 数据通道)
INVALID无法识别状态的数据包无法解析或不属于任何已知连接

10.2.2 NEW 状态

# 匹配新连接
iptables -A INPUT -m conntrack --ctstate NEW -j ACCEPT

# TCP 的 NEW 状态:SYN 包
# UDP 的 NEW 状态:第一个数据包
# ICMP 的 NEW 状态:echo-request

注意:NEW 不代表连接一定会成功建立。一个 SYN 包是 NEW 状态,即使目标端口未开放。

10.2.3 ESTABLISHED 状态

# 匹配已建立连接的后续包
# TCP:看到双向通信(SYN + SYN-ACK 都出现)
# UDP:看到双向数据包
# ICMP:看到 echo-reply
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
# 匹配与已有连接相关的新连接
iptables -A INPUT -m conntrack --ctstate RELATED -j ACCEPT

RELATED 状态的典型场景:

场景主连接关联连接
FTP 主动模式控制通道 (21)数据通道 (20)
FTP 被动模式控制通道 (21)动态端口数据通道
ICMP 错误任何连接ICMP unreachable
SIP/RTPSIP 信令 (5060)RTP 媒体流
TFTPTFTP 请求 (69)动态端口数据传输
Amanda 备份Amanda 控制Amanda 数据
# 加载 FTP 辅助模块(使 FTP 数据通道被识别为 RELATED)
modprobe nf_conntrack_ftp

# 加载 TFTP 辅助模块
modprobe nf_conntrack_tftp

# 加载 SIP 辅助模块
modprobe nf_conntrack_sip

10.2.5 INVALID 状态

# 记录无效数据包
iptables -A INPUT -m conntrack --ctstate INVALID \
  -j LOG --log-prefix "IPT-INVALID: "

# 丢弃无效数据包
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

INVALID 状态的典型原因:

原因说明
乱序 TCP 包序列号不在窗口内
ICMP 错误消息不对应任何已知连接
内存不足conntrack 表满,无法创建新条目
协议异常无法解析的数据包

10.3 TCP 连接状态机

10.3.1 TCP 三次握手与 conntrack

客户端              conntrack               服务器
  │                    │                      │
  │──── SYN ─────────→│ 记录: NEW             │──── SYN ─────────→
  │                    │ 状态: SYN_SENT        │
  │                    │                      │
  │←─── SYN+ACK ─────│ 更新: SYN_RECV        │←─── SYN+ACK ──────
  │                    │                      │
  │──── ACK ─────────→│ 更新: ESTABLISHED     │──── ACK ─────────→
  │                    │                      │
  │←─── 数据 ─────────│ ESTABLISHED           │←─── 数据 ──────────
  │                    │                      │

10.3.2 TCP 状态超时

conntrack 状态对应 TCP 状态默认超时
SYN_SENTSYN_SENT120 秒
SYN_RECVSYN_RECV60 秒
ESTABLISHEDESTABLISHED432000 秒(5天)
FIN_WAITFIN_WAIT120 秒
CLOSE_WAITCLOSE_WAIT60 秒
LAST_ACKLAST_ACK30 秒
TIME_WAITTIME_WAIT120 秒
CLOSECLOSED10 秒
# 查看当前 TCP 超时设置
sysctl -a | grep net.netfilter.nf_conntrack_tcp_timeout

# 优化高并发场景的超时
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=1800
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=15
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_fin_wait=15
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=10
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_sent=15
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_recv=10

10.4 conntrack 工具

10.4.1 查看连接跟踪表

# 查看所有连接跟踪条目
conntrack -L

# 按协议过滤
conntrack -L -p tcp
conntrack -L -p udp
conntrack -L -p icmp

# 按状态过滤
conntrack -L --state ESTABLISHED
conntrack -L --state NEW

# 按源 IP 过滤
conntrack -L -s 192.168.1.100

# 按目的端口过滤
conntrack -L -p tcp --dport 80

# 精确匹配
conntrack -L -p tcp --src 192.168.1.100 --dst 10.0.0.10 --dport 80

10.4.2 监控连接变化

# 实时监控新建/更新/销毁的连接
conntrack -E

# 输出示例:
# [NEW]    tcp  6 120 SYN_SENT src=192.168.1.100 dst=10.0.0.10 sport=54321 dport=80
# [UPDATE] tcp  6 60 SYN_RECV src=192.168.1.100 dst=10.0.0.10 sport=54321 dport=80
# [UPDATE] tcp  6 432000 ESTABLISHED src=192.168.1.100 dst=10.0.0.10 sport=54321 dport=80

10.4.3 统计信息

# 查看当前连接跟踪条目数
conntrack -C

# 查看 conntrack 统计信息
conntrack -S

# 输出示例:
# packets    1234567
# bytes      987654321
# avg-pkt-size  800
# new        12345
# established 1220000
# invalid    123
# ignore     456
# delete     1100000
# delete_list 890
# insert     12345
# insert_failed 0
# drop       0
# early_drop 0
# error      0
# search_restart 0

10.4.4 删除连接跟踪条目

# 删除特定连接
conntrack -D -p tcp --dport 80 -s 192.168.1.100

# 删除所有 TCP 连接
conntrack -D -p tcp

# 清空所有连接跟踪(危险!会导致已建立连接丢失状态)
conntrack -F

# 删除特定状态的连接
conntrack -D --state TIME_WAIT

10.4.5 高级过滤

# 使用 Mark 过滤
conntrack -L -m 1

# 使用 Labels 过滤
conntrack -L --label web-traffic

# 查看 NAT 转换后的连接
conntrack -L -p tcp --src-nat
conntrack -L -p tcp --dst-nat

10.5 典型配置模式

10.5.1 基于状态的有状态防火墙

#!/bin/bash
# ═══════════════════════════════════════════════════
# 有状态防火墙(推荐配置)
# ═══════════════════════════════════════════════════

iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 核心规则:允许已建立和相关的连接
# 这条规则放在最前面,能匹配 90%+ 的数据包
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 丢弃无效包
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# 允许回环接口
iptables -A INPUT -i lo -j ACCEPT

# 允许新连接:SSH
iptables -A INPUT -p tcp --dport 22 --syn \
  -m conntrack --ctstate NEW -j ACCEPT

# 允许新连接:HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn \
  -m conntrack --ctstate NEW -j ACCEPT

# 允许新连接:ICMP
iptables -A INPUT -p icmp --icmp-type echo-request \
  -m conntrack --ctstate NEW -j ACCEPT

# 日志并丢弃其他
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: "
iptables -A INPUT -j DROP

10.5.2 FTP 被动模式支持

#!/bin/bash
# FTP 服务器防火墙配置(被动模式)

# 加载 FTP 连接跟踪辅助模块
modprobe nf_conntrack_ftp
modprobe nf_nat_ftp

# 持久化加载
echo "nf_conntrack_ftp" >> /etc/modules-load.d/ftp.conf
echo "nf_nat_ftp" >> /etc/modules-load.d/ftp.conf

# 允许已建立的连接和 RELATED(FTP 数据通道)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 允许 FTP 控制通道
iptables -A INPUT -p tcp --dport 21 -j ACCEPT

# 允许 FTP 被动模式数据端口范围
iptables -A INPUT -p tcp --dport 30000:31000 -j ACCEPT

# 允许 FTP 主动模式数据通道(由 conntrack_ftp 自动识别为 RELATED)
# 不需要额外规则

iptables -P INPUT DROP

10.5.3 SIP/VoIP 防火墙

#!/bin/bash
# VoIP 服务器防火墙配置

# 加载 SIP 辅助模块
modprobe nf_conntrack_sip
modprobe nf_nat_sip

# 允许 SIP 信令
iptables -A INPUT -p udp --dport 5060 -j ACCEPT
iptables -A INPUT -p tcp --dport 5060 -j ACCEPT

# 允许 RTP 媒体流(由 conntrack_sip 自动识别为 RELATED)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# RTP 端口范围(备用,如果辅助模块不生效)
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT

10.6 conntrack 内核参数参考

10.6.1 核心参数

参数默认值建议值说明
nf_conntrack_max65536262144最大连接跟踪条目数
nf_conntrack_buckets1638465536哈希桶数
nf_conntrack_tcp_timeout_established4320001800TCP 已建立连接超时(秒)
nf_conntrack_tcp_timeout_time_wait12015TIME_WAIT 超时
nf_conntrack_udp_timeout3010UDP 超时
nf_conntrack_icmp_timeout3010ICMP 超时
nf_conntrack_generic_timeout600120通用超时
# 一次性优化 conntrack 参数
cat >> /etc/sysctl.conf << 'EOF'
# conntrack 性能优化
net.netfilter.nf_conntrack_max = 262144
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 15
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_udp_timeout = 10
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmp_timeout = 10
net.netfilter.nf_conntrack_generic_timeout = 120
EOF

sysctl -p

10.7 故障排查

10.7.1 conntrack 表满

# 检查是否出现 conntrack 表满
dmesg | grep "nf_conntrack: table full"

# 检查使用率
COUNT=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
echo "使用率: $COUNT / $MAX ($(( COUNT * 100 / MAX ))%)"

# 查看哪些 IP 占用最多连接
conntrack -L | awk '{print $5}' | cut -d= -f2 | sort | uniq -c | sort -rn | head -20

# 查看哪些端口连接最多
conntrack -L | awk '{print $8}' | cut -d= -f2 | sort | uniq -c | sort -rn | head -20

10.7.2 DNAT 规则不生效

# 症状:修改 DNAT 规则后旧连接仍然走旧路径
# 原因:conntrack 缓存了旧的 NAT 映射

# 解决:清除相关连接跟踪条目
conntrack -D -p tcp --dport 80
# 症状:FTP 数据通道被误判为 NEW 状态并被拒绝
# 原因:未加载 FTP 辅助模块

# 检查辅助模块
lsmod | grep nf_conntrack_ftp

# 加载模块
modprobe nf_conntrack_ftp

10.8 注意事项

⚠️ ESTABLISHED 不等于 TCP ESTABLISHED:conntrack 的 ESTABLISHED 状态指的是"conntrack 看到了双向通信",与 TCP 的 ESTABLISHED 状态含义不同。

⚠️ conntrack 表满会导致 NAT 失败:当 conntrack 表满时,新连接无法创建跟踪条目,NAT 转换会失败,数据包可能被错误处理。

⚠️ conntrack -F 的风险:清空 conntrack 表会导致所有已建立连接的状态信息丢失。如果有 NAT,NAT 映射也会丢失,导致已有连接中断。

⚠️ NOTRACK 与 ESTABLISHED 不兼容:被 NOTRACK 标记的数据包不会进入 conntrack,因此不能使用 ESTABLISHED/RELATED 状态匹配。


10.9 扩展阅读

资源说明
man conntrackconntrack 工具手册
man conntrackd连接跟踪同步守护进程
/proc/net/nf_conntrack内核 conntrack 表文件
/proc/net/stat/nf_conntrackconntrack 统计信息

本章小结

状态含义典型用途
NEW新连接的第一个包限制新连接速率
ESTABLISHED已建立连接的后续包放行已建立的连接
RELATED关联的新连接FTP/SIP/ICMP 错误
INVALID无法识别的包丢弃异常数据包

下一章第 11 章:端口转发与代理,将学习端口转发、负载均衡和透明代理的实现方法。