Appearance
iptables防火墙
iptables 在 Linux 上用于主机侧的包过滤和 NAT。虽然新发行版逐渐向 nftables 迁移,但 iptables 仍然广泛应用在老系统、容器网络和各类技术文档中。
一、iptables 和 firewalld 的关系
RHEL/CentOS 上常见 firewalld,它的底层可以调用 iptables 或 nftables。如果 firewalld 正在管理规则,直接手动改 iptables 规则可能被 firewalld 覆盖。处理防火墙之前先确认谁在主控。
bash
iptables -V # 看 iptables 版本
systemctl status firewalld # 看 firewalld 是否在运行
iptables -L -n -v # 看当前 iptables filter 表规则iptables 是用户态管理工具,真正在内核里处理报文的是 netfilter 框架。命令只是把规则写入内核,数据包的匹配和动作在内核完成。
二、表、链和规则
iptables 的规则体系分三个层次理解:
| 概念 | 说明 |
|---|---|
| 表(Table) | 按功能分类的规则集合:过滤、NAT、修改报文 |
| 链(Chain) | 报文经过内核网络栈时的检查点 |
| 规则(Rule) | 匹配条件 + 动作,按顺序逐条比对 |
四张常用表:
| 表 | 功能 | 典型场景 |
|---|---|---|
| filter | 过滤,决定要不要让包通过 | 开放/阻止端口,最常用 |
| nat | 地址转换 | 源地址转换(SNAT/MASQUERADE)、目标地址转换(DNAT) |
| mangle | 修改报文头 | 修改 TOS、TTL,较少直接使用 |
| raw | 在连接跟踪之前处理 | 排除特定流量不做状态跟踪 |
五条链对应报文经过内核的不同位置:
| 链 | 触发时机 |
|---|---|
| PREROUTING | 报文刚到达网卡,尚未路由决策 |
| INPUT | 经过路由决策后,确定目标是本机 |
| FORWARD | 经过路由决策后,确定目标是另一台机器(本机作为网关) |
| OUTPUT | 本机进程发出的报文 |
| POSTROUTING | 报文即将离开网卡(路由决策之后) |
报文经过的路径取决于流量方向:
| 流量方向 | 经过的链 |
|---|---|
| 外部 → 本机服务 | PREROUTING → INPUT |
| 本机 → 外部 | OUTPUT → POSTROUTING |
| 外部 → 本机转发 → 外部 | PREROUTING → FORWARD → POSTROUTING |
开放端口的场景主要看 filter 表的 INPUT 链。排查端口不通时,先判流量的方向(进本机、出本机、还是转发),就知道该看 INPUT、OUTPUT 还是 FORWARD。
三、查看规则
bash
iptables -L -n -v # 默认 filter 表,-n 不解析名称,-v 显示计数器
iptables -S # 以接近命令的形式输出(方便复制和回滚)
iptables -t nat -L -n -v # 查看 nat 表
iptables -L INPUT -n --line-numbers # 带行号,方便后续按行号删除iptables -S 的输出格式可以直接当作命令重新执行,回滚和备份时更实用。-v 输出中的计数器(pkts、bytes 列)也很重要——某条规则的计数器一直不涨,说明包没有匹配到这里。
四、规则基本结构
一条规则由匹配条件和动作组成:
| 组成 | 示例 | 含义 |
|---|---|---|
| 操作 | -A INPUT | 追加(Append)到 INPUT 链末尾 |
| 协议 | -p tcp | 只匹配 TCP 协议 |
| 目标端口 | --dport 22 | 目标端口是 22 |
| 状态 | -m state --state ESTABLISHED,RELATED | 连接状态为已建立或相关 |
| 动作 | -j ACCEPT | 匹配后放行 |
规则的顺序至关重要:iptables 从链的第一条开始逐条向下匹配,命中即执行动作,不再继续往下看。
一个安全的最小规则集:
bash
# 放行已经建立和相关的连接——保证现有 SSH 不会断
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 放行本机回环(lo),很多本地服务依赖 127.0.0.1 通信
iptables -A INPUT -i lo -j ACCEPT
# 放行 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 放行业务端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 默认策略:INPUT 链未匹配的包一律丢弃
iptables -P INPUT DROP远程操作防火墙时,默认策略(-P INPUT DROP)必须在放行 SSH 和相关连接的规则之后才设置。先在旁边留一个已登录的 tmux 会话更稳。
三种动作的区别:
| 动作 | 行为 | 对方看到的效果 |
|---|---|---|
| ACCEPT | 放行 | 正常通信 |
| DROP | 直接丢弃,不回复任何内容 | 超时(等待后无响应) |
| REJECT | 丢弃并回复错误(ICMP port unreachable 或 TCP RST) | 立即收到拒绝 |
公网入口常用 DROP(不暴露服务存在信息)。内网排错时 REJECT 更友好——失败快,不至于一直等超时。
五、状态跟踪
iptables 可以通过连接跟踪(conntrack)识别包属于哪个连接。
连接状态:
| 状态 | 含义 |
|---|---|
| NEW | 新发起的连接的第一个包 |
| ESTABLISHED | 属于已有连接的包(双向) |
| RELATED | 与已有连接相关的包(如 FTP 的数据通道) |
| INVALID | 无法归类或异常的包 |
ESTABLISHED,RELATED 规则的核心价值:允许本机主动访问外部后,外部返回的响应包能够通过防火墙进来。如果没有这条规则,默认 DROP 的机器连自己主动发起的 HTTP 请求的回包都收不到。
部分新系统推荐 conntrack 模块写法:
bash
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTstate 和 conntrack 底层都是 netfilter 的连接跟踪系统。conntrack 是更现代的模块,功能上基本等价。维护老机器时不用强行修改风格,新规则优先用 conntrack。
六、规则的插入和删除
插入到指定位置:
bash
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT # 插入到 INPUT 链第 1 条按行号删除:
bash
iptables -L INPUT -n --line-numbers # 先看行号
iptables -D INPUT 3 # 删除第 3 条按规则内容匹配删除:
bash
iptables -D INPUT -p tcp --dport 80 -j ACCEPT按行号删之前再看一遍行号。链中增删规则后,后续规则的编号会跟着变。
七、NAT
NAT 修改报文中的 IP 地址或端口。常见两类用法:
| 类型 | 用途 | 常用链 |
|---|---|---|
| SNAT / MASQUERADE | 内网多台机器共享一个外网 IP 上网 | POSTROUTING |
| DNAT | 将外网的请求转发到内网某台机器 | PREROUTING |
内网机器共享上网(MASQUERADE 自动使用出口网卡的 IP):
bash
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE端口转发(外部访问本机 8080 转到内网 10.0.0.10:80):
bash
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.10:80做 NAT 转发时需要启用 IP 转发功能:
bash
sysctl -w net.ipv4.ip_forward=1持久化:
bash
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-ip-forward.conf
sysctl --system排查 NAT 规则时,同时看 nat 表和 filter 表。DNAT 之后,后续链(如 FORWARD)看到的包已经是被改写过的——源端口 :8080 已经变成了 :80。
八、保存和恢复规则
iptables 规则存在内存中,重启后丢失。不同发行版持久化方式不同:
RHEL/CentOS:
bash
service iptables save # 保存到 /etc/sysconfig/iptables
iptables-save > /etc/sysconfig/iptablesDebian/Ubuntu:
bash
apt install iptables-persistent -y
iptables-save > /etc/iptables/rules.v4临时加规则救火后,马上确认持久化,否则下次重启规则丢失。
九、和 firewalld 共存时的注意点
bash
firewall-cmd --state
firewall-cmd --list-all
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload如果团队统一用 firewalld 管理防火墙,不建议绕过它直接写 iptables。混着改的结果是规则互相覆盖,出问题时很难追溯规则的最终来源。
十、端口不通时的排查清单
bash
ss -lntp | grep ':80' # 服务是否在监听
iptables -L INPUT -n -v --line-numbers # filter 表 INPUT 链规则和计数器
iptables -t nat -L -n -v --line-numbers # NAT 表规则(有端口转发时)看计数器——如果某条规则的计数器始终为 0,说明包没有匹配到这儿。方向、表、链或上游网络都可能有问题。