ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

iptables五链详解:从数据包路径到防火墙故障排查

iptables五链详解:从数据包路径到防火墙故障排查 先从一个真实故障说起运维同事在服务器上敲了一条 iptables 命令本意是“只允许某个 IP 访问 22 端口”结果刚执行完自己的 SSH 会话立刻断开再也没连上。后来通过带外管理登录才发现他把默认链策略直接设成了 DROP并且允许规则写在了拒绝规则后面一条规则就干掉了整台服务器的入站流量。这类问题在 Linux 服务器上非常常见。iptables 看似简单但它的匹配顺序、链的路径、表的作用范围任何一个环节理解偏差都可能造成服务不可达、服务器无法出网、局域网无法转发等故障。本文将围绕 iptables 的 5 条内置链展开拆解一条规则为什么会“锁死”服务器并通过完整实战让大家掌握查看、添加、删除、保存规则的方法最后总结高频故障的排查思路。内容偏运维实操建议打开自己的测试环境跟着执行。1. 先搞懂 iptables 和 Netfilter1.1 iptables 是什么iptables 是 Linux 内核中 Netfilter 框架的用户态管理工具。Netfilter 是内核里的一组数据包处理钩子iptables 则负责向这些钩子上注册规则。两者配合实现数据包过滤、网络地址转换NAT、数据包修改等能力。通俗地说iptables 是一个“关卡列表”。每个经过 Linux 网络协议栈的数据包都会在特定位置停下来接受规则审查。审查结果可能是ACCEPT放行。DROP丢弃就像数据包从未出现过。REJECT拒绝并且主动返回一个不可达信息。LOG记录日志然后继续匹配。服务器被“一条规则挡住”本质上是某个关卡上的 DROP 或 REJECT 规则命中把本应放行的流量拦掉了。1.2 表与链的关系iptables 中经常提到“四表五链”。四张表filter过滤规则最常用。nat网络地址转换用于源地址转换SNAT、目的地址转换DNAT等。mangle修改数据包服务类型、TTL、Mark 等。raw优先级最高用于跳过连接跟踪。五条内置链PREROUTING数据包进入路由决策之前。INPUT发给本机的数据包。FORWARD由本机转发的数据包。OUTPUT本机发出的数据包。POSTROUTING数据包离开本机之前即路由决策之后。每张表会在某几条链上工作。例如 filter 表只在 INPUT、FORWARD、OUTPUT 链上工作nat 表涉及 PREROUTING、INPUT、OUTPUT、POSTROUTINGmangle 表覆盖全部五条链。这个结构和路由决策有关也是认清数据包路径的关键。1.3 表/链的处理顺序同一个数据包会先经过哪张表在每条链上表的优先级是固定的PREROUTINGraw - mangle - natINPUTmangle - filterFORWARDmangle - filterOUTPUTraw - mangle - nat - filterPOSTROUTINGmangle - nat简单记住raw 优先级最高mangle 其次nat 再次filter 最后。filter 表是数据包“是否放行”的最终裁决点之一这也是为什么大多数人只接触 filter 表。2. 5 条链的完整数据包路径2.1 三种典型包流向要理解 5 条链先看一个数据包到达 Linux 服务器后会有几种命运访问本机数据包进入网卡 - PREROUTING - 路由判断目的为本地 - INPUT - 交给本地进程。转发数据包进入网卡 - PREROUTING - 路由判断目的不是本地 - FORWARD - POSTROUTING - 从另一块网卡离开。本机发出本地进程产生数据包 - 路由判断出口 - OUTPUT - POSTROUTING - 从网卡离开。如果你把服务器当作路由器FORWARD 链就是管控转发流量的大门。很多“防火墙开了却没效果”或“无法转发”的问题都出在 FORWARD 链上。下面用一个 ASCII 简图表达数据包入网卡 | v PREROUTING (raw - mangle - nat) | v 路由判断 |-- 目的为本机 -- INPUT (mangle - filter) -- 本地进程 | |-- 需要转发 -- FORWARD (mangle - filter) -- POSTROUTING (mangle - nat) -- 出网卡 | v 本地进程产生数据包 -- 路由判断 -- OUTPUT (raw - mangle - nat - filter) -- POSTROUTING -- 出网卡2.2 一条规则最多影响哪个环节当你执行iptables -A INPUT -j DROP这条规则挂在 INPUT 链上它只会拦截“本机接收的包”。如果服务器原本要转发流量这条规则不会影响转发。但如果要挡掉所有访问本机的流量只需要这一条就能让 SSH、HTTP、ping 全部失效。同样iptables -A OUTPUT -j DROP会拦住本机发出的所有流量包括向外访问 API、DNS 解析、ping 外部地址。此时如果你在远程服务器上执行等于把自己锁死在“能进不能出”的状态SSH 会话还在但新命令可能无法等待远程响应。2.3 FORWARD 链引发的“看不到但过不去”如果设备配置了两个网卡并且已经开启了 IP 转发net.ipv4.ip_forward1流量从 eth0 进要从 eth1 出必须经过 FORWARD 链。很多人只加了一条iptables -A FORWARD -j DROP然后发现内网机器无法访问外网但防火墙本机访问外网却正常。原因就是本机流量走 OUTPUT 链转发流量走 FORWARD 链。这就是“五元组一致但无法转发”类问题的常见根源。所谓五元组通常指源 IP、源端口、目的 IP、目的端口、协议。检查转发问题时需要同时确认这五个字段是否在 FORWARD 链的放行规则里。3. 为什么一条规则就能挡住服务器3.1 匹配即停止iptables 的规则是按顺序匹配的。一个数据包进入链后从第一条规则开始逐条判断。一旦匹配某条规则就执行对应动作ACCEPT、DROP、REJECT、LOG 等不再继续往后匹配。这是最关键的特性规则顺序决定最终结果。如果你把DROP放在前面后面的ACCEPT永远不会执行。来看一段最容易踩坑的规则iptables -A INPUT -j DROP iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT这两条规则都追加到 INPUT 链末尾顺序是先 DROP 全部后允许特定 IP 访问 22。实际效果是所有入站数据包在第一条就被 DROP后面的 ACCEPT 成了摆设。即使之前查看规则时发现 ACCEPT 存在服务器依然无法访问。正确写法iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT iptables -A INPUT -j DROP放行规则必须先于拒绝规则。3.2 默认策略直接把门锁死每条内置链都有默认策略Policy。默认策略针对的是“链里所有规则都没匹配”的数据包。如果默认策略是 ACCEPT那规则只拦截明确要拦截的如果默认策略是 DROP那规则只放行明确要放行的。很多故障是设置默认策略时造成的iptables -P INPUT DROP执行后所有入站数据包默认丢弃。此时如果没有同时放行 SSH、HTTP 等端口服务器外部访问将立即全部断开。并且这类默认策略不会因为重启服务恢复除非手动修改。查看默认策略iptables -L INPUT输出中链首的Policy: DROP或Policy: ACCEPT就是当前默认策略。3.3 只放行半边流量还有一种隐蔽的“一条规则挡住服务器”的情况只放行了入方向或只放行了出方向。例如只放行入站 SSHiptables -A INPUT -p tcp --dport 22 -j ACCEPT但没有放行 OUTPUT 的回包或者 OUTPUT 默认策略是 DROP。TCP 连接不仅需要客户端的 SYN 到达服务器还需要服务器的 SYNACK 回给客户端。回包属于 OUTPUT 链如果 OUTPUT 被挡连接一样建立不起来。所以写规则时必须考虑“请求能进来”和“响应能出去”两个方向尤其是在默认策略为 DROP 时不能只关注单向端口。3.4 端口映射只加 PREROUTING 不加 FORWARD常见的端口映射需求公网访问防火墙的 8080 端口转发给内网服务器 192.168.1.10 的 80 端口。许多人只添加了iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.10:80发现无法访问。原因可能是这台 Linux 设备既是目标主机又是路由器公网包到达后路由判断目的为本地会走 INPUT 链而不是 FORWARD 链如果目的被 DNAT 到内网 IP则后续需要走 FORWARD 链。如果网络拓扑是 防火墙 - 内网服务器那么 PREROUTING 的 DNAT 只负责改写目标地址数据包能不能从防火墙转发到内网服务器还要看 FORWARD 链是否放行。下面是一个较完整的端口映射示例# 开启 IP 转发 sysctl -w net.ipv4.ip_forward1 # 外部访问防火墙 8080目的地址改为内网主机 iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.10:80 # 内网主机回包时源地址改为防火墙公网地址 iptables -t nat -A POSTROUTING -d 192.168.1.10 -p tcp --dport 80 -j SNAT --to-source 防火墙内网IP # FORWARD 链放行相关流量 iptables -A FORWARD -d 192.168.1.10 -p tcp --dport 80 -j ACCEPT iptables -A FORWARD -s 192.168.1.10 -p tcp --sport 80 -j ACCEPT具体 SNAT 地址需要根据你的网络结构调整这里重点是理解链路走向。4. 完整实战从清空规则到安全放行下面用一个 CentOS 7 环境演示 iptables 防火墙的配置过程。无论你用的是 Ubuntu、Rocky Linux 还是国产化 Linux 系统命令行思路基本一致只是保存方式稍有差异。4.1 环境准备本文示例环境操作系统CentOS Linux release 7.9内核版本3.10.0-1160网卡eth0公网 IPeth1内网 IP需要开放服务SSH 22、HTTP 80、HTTPS 443、DNS UDP 53、ping版本需要根据你的实际环境调整本节重点演示配置思路和命令执行逻辑。先查看当前系统是否安装了 iptablesiptables --versionCentOS 7 默认可能使用 firewalld需要先安装 iptables-services 并停止 firewalldsystemctl stop firewalld systemctl disable firewalld yum install -y iptables-services systemctl enable iptables在 Ubuntu/Debian 系统上可以安装iptables-persistent保存规则。不同发行版保存命令不同下面会单独说明。4.2 查看当前防火墙规则建议任何改动前先执行iptables -L -n -v --line-numbers参数说明-L列出规则。-n不解析主机名和服务名直接显示 IP 和端口。-v显示更多信息包括匹配的包数量、字节数。--line-numbers显示规则编号方便后续删除。输出示例Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED注意看每一条规则的in、out、source、destination和目标动作。调试时非常有用。如果想看 nat 表的规则iptables -t nat -L -n -v --line-numbers4.3 清空规则前的风险提醒执行清空命令前必须确认你在一个有带外管理权限的环境中否则一旦默认策略是 DROP清空规则不会自动恢复 ACCEPT 策略服务器可能直接失联。iptables -F iptables -t nat -F iptables -X iptables -Z-F清空链中的规则。-X删除用户自定义空链。-Z计数器清零。清空规则不等于重置默认策略。很多新手在这里踩坑规则清空了但默认策略还是 DROP服务器依旧无法访问。4.4 设置安全的基础规则下面是一套常用于服务器的基础规则。我们先把默认策略设为 ACCEPT这样即使后面规则写错也不会直接断网。# 设置默认策略 iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # 清空旧规则 iptables -F iptables -t nat -F然后再逐条添加控制规则# 允许本地回环 iptables -A INPUT -i lo -j ACCEPT # 允许已建立连接和相关连接 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许 SSH iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许 HTTP/HTTPS iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT # 允许 DNS 查询UDP iptables -A INPUT -p udp --dport 53 -j ACCEPT # 允许 ping iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # 其他入站流量默认丢弃 iptables -A INPUT -j DROP这里把-P INPUT ACCEPT作为临时策略再用最后一条-A INPUT -j DROP实现默认拒绝。这样比直接修改默认策略更稳妥因为规则列表比 Policy 更容易查看和调整。如果确定要设置默认策略为 DROP建议先把所有允许规则确认无误后最后再执行iptables -P INPUT DROP4.5 添加到 FORWARD 链的转发规则如果这台设备需要转发内网流量假设内网网段是 192.168.1.0/24外网网卡是 eth0需要添加# 开启 IP 转发 echo net.ipv4.ip_forward 1 /etc/sysctl.conf sysctl -p # 转发链只放行内网网段 iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -j DROP注意规则顺序先放行内网来源包再放行外网返回的关联包最后丢弃其他转发包。如果还需要做源地址转换让内网机器通过这台服务器上网iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADEMASQUERADE适合出口 IP 动态变化的场景它会自动把内网包的源地址改成 eth0 的 IP。如果外网 IP 固定也可以使用 SNATiptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 你的公网IP4.6 保存规则CentOS 7 使用 iptables-services 时service iptables save该命令会把当前的 IPv4 规则保存到/etc/sysconfig/iptables。之后开机自动加载。Ubuntu / Debian 使用 netfilter-persistent 保存apt install -y iptables-persistent netfilter-persistent save netfilter-persistent reload如果你使用的是临时性的 iptables 命令一旦重启规则会丢失。所以在生产环境保存规则这一步绝不能省略。4.7 验证效果在服务器本机和远程客户端分别验证。查看规则统计iptables -L INPUT -n -v --line-numbers输出中会显示每个规则匹配的包数量和字节数。如果数据包被丢弃最后那条 DROP 的计数会不断增加。测试 HTTP 连接curl -I http://服务器IP测试 pingping -c 3 服务器IP测试 SSHssh 用户服务器IP如果某个测试不通先看对应链的计数器能快速定位是哪条规则拦截。5. 常见故障与排查思路下面把之前运维中遇到的高频问题整理为一张表问题现象常见原因解决思路SSH 连不上服务器INPUT 默认策略为 DROP或 DROP 规则在 ACCEPT 之前通过带外/控制台登录调整规则顺序或设置 Policy ACCEPT服务端口被外部访问不到但本地正常防火墙未放行对应端口添加-A INPUT -p tcp --dport 端口 -j ACCEPT服务器无法访问外网OUTPUT 链规则过严或缺少放行规则检查 OUTPUT 默认策略放行 ESTABLISHED,RELATED 回包内网机器无法上网FORWARD 链未放行或 IP 转发未开启检查sysctl net.ipv4.ip_forward放行 FORWARD端口映射不生效PREROUTING 写了 DNAT但 FORWARD 未放行检查 FORWARD 链确保转发流量被允许清空规则后仍然被挡默认策略仍是 DROP执行iptables -P INPUT ACCEPT等规则明明存在但是被忽略规则顺序靠后前面已有 DROP/REJECT查看--line-numbers调整顺序或插入到前面重启后规则丢失没有保存规则使用service iptables save或 netfilter-persistent 保存5.1 无法 SSH 的紧急恢复当你已经无法通过 SSH 连接但有控制台或带外管理权限时按以下步骤处理# 先把默认策略恢复为 ACCEPT iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT # 清空规则 iptables -F iptables -t nat -F执行后所有流量暂时恢复放行。再重新编写安全的规则。如果没有控制台权限只能通过重启服务器并让防火墙恢复默认规则来应急。所以生产环境上设置默认策略 DROP 前必须确认有可靠的应急通道。5.2 规则不生效的检查思路规则不生效通常是匹配条件没写对或者流量没有走到对应链。可以用tcpdump抓包确认数据包是否到达网卡tcpdump -i eth0 -n port 80如果抓到了请求包但客户端连接失败说明包在 iptables 层被拦截。此时看iptables -L -v的计数器变化哪个链的 DROP 计数在增长就是问题点。特殊场景比如两个网卡入站接口和出站接口要写清楚-i和-o-i指进入接口-o指出接口。写反了规则就不会命中。5.3 IPv6 规则别忽略iptables 只管理 IPv4。IPv6 使用 ip6tables 管理。如果服务器启用了 IPv6SSH 或 HTTP 监听在 IPv6 地址你需要同时检查 ip6tables 规则。查看 IPv6 防火墙ip6tables -L -n -v --line-numbers很多“服务器某些 IP 能连某些 IP 不能连”的问题可能就是 IPv6 规则未配置而 DNS 解析返回了 IPv6 地址。5.4 “五元组一致但无法转发”的定位当你明确看到流量五元组符合某条 ACCEPT 规则但转发就是不成功时按下面顺序排查确认net.ipv4.ip_forward1已开启。确认数据包确实走了 FORWARD 链而不是 INPUT 链。这取决于路由判断目的 IP 必须是远程主机的 IP而非本机 IP。确认 FORWARD 链第一个匹配的规则是 ACCEPT而不是更早的 DROP。确认 POSTROUTING 的 SNAT/MASQUERADE 是否配置内网机器回包需要正确的源地址转换。抓包确认数据包在哪个接口消失tcpdump -i eth1 -n host 内网主机IP通过抓包结果判断包是没进入内核还是被 iptables 丢弃还是路由不回来。6. iptables 配置最佳实践6.1 遵循最小权限原则iptables 规则应遵循“默认拒绝按需放行”的思路。但这句话在落地时要谨慎对外提供服务明确放行对应端口和来源。对内管理限制 SSH 来源 IP或使用堡垒机。出站流量如果业务不需要主动访问外网可以限制 OUTPUT如果需要访问至少要放行 ESTABLISHED,RELATED。始终注意最小权限不是先把所有流量拒了再说而是先梳理业务依赖再配置规则。6.2 规则顺序要清晰尽量把“精确放行”放在前面把“兜底拒绝”放在后面。例如iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP含义是内网网段可以 SSH其他来源一律拒绝。注意不要反过来写否则内网也会被 DROP 拦截。为方便维护可以在规则中加注释iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 22 -j ACCEPT -m comment --comment allow intranet ssh查看时用iptables -L -n --line-numbers配合注释能快速识别规则用途。6.3 使用脚本管理规则在生产环境建议把规则整理成 Shell 脚本纳入版本管理。例如/etc/iptables-rules.sh#!/bin/bash # 定义变量 PUB_IFeth0 LAN_NET192.168.1.0/24 # 设置默认策略 iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # 清空规则 iptables -F iptables -t nat -F # 本地回环 iptables -A INPUT -i lo -j ACCEPT # 允许已有连接 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 放行 SSH、HTTP、HTTPS iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT # 如果配置了 DNAT需要放行转发流量 iptables -A FORWARD -i $PUB_IF -p tcp --dport 80 -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 内网上网 iptables -t nat -A POSTROUTING -s $LAN_NET -o $PUB_IF -j MASQUERADE # 保存 service iptables save脚本化之后规则变更可以走代码评审也能快速重放。6.4 变更前备份规则iptables 规则一键导出iptables-save /backup/iptables-$(date %Y%m%d%H%M%S).rules恢复规则iptables-restore /backup/iptables-xxxx.rules在修改生产防火墙之前执行备份是成本最低的风险防范手段。6.5 关注 nftables 趋势很多现代 Linux 发行版如 RHEL 8/9、Ubuntu 22.04默认采用 nftables 框架iptables 命令只是兼容接口。nftables 语法更统一性能也更优。但本文讨论的 iptables 规则在大部分系统上仍可以继续使用。如果系统默认提示 nftables且没有 iptables 相关模块可以安装兼容层yum install -y iptables但长期来看新项目建议直接学习 nftables。iptables 的链、表、匹配思想在 nftables 中依然有延续性不会白学。6.6 安全边界和远程变更注意事项不要在生产环境用一条命令同时“清空 设置默认 DROP”尤其在没有后台管理通道时。远程修改防火墙建议先写一个定时任务在 5 分钟后自动清空规则防止把通道锁死。对规则变更做验证先在测试机模拟同样的网络拓扑和流量再发布到生产。脚本中可加入“保险定时回滚”# 3 分钟后自动恢复默认规则用于防止远程配置失误 (sh -c sleep 180; iptables -F; iptables -P INPUT ACCEPT; iptables -P OUTPUT ACCEPT; iptables -P FORWARD ACCEPT )这种方式不能直接作为长期方案但能在紧急变更时争取恢复时间。7. 从 iptables 到防火墙思维的提升iptables 虽然是一条条命令但它的核心是网络数据包路径的管控思想。学 5 条链不只是背名字而是要清楚每个数据包在任意时刻处于哪个阶段、会被哪些表处理。本次实战里我们完成了从清空规则、配置 INPUT/FORWARD 链、配置 NAT 到保存规则的全流程也说明了“一条规则挡住服务器”的常见原因DROP 放在 ACCEPT 之前。默认策略直接改为 DROP 却没放行必要端口。只放行入站忽略出站回包。FORWARD 链拦掉了转发流量。检查规则时优先关注--line-numbers、计数器、默认策略变更强制备份任何远程防火墙操作都要给自己留一条“回滚后路”。下一步可以继续学习iptables扩展匹配-m state、-m multiport、-m limit、-m time。NAT 的 SNAT、DNAT、MASQUERADE、REDIRECT 场景。nftables 语法以及如何把现有 iptables 规则迁移到 nftables。防火墙配置从来不是“凭感觉”的事。每次改规则前问自己三个问题这个包从哪来要到哪去应该在哪条链放行想清楚这三个问题很多故障都能避开。如果本文对你有帮助可以收藏备用下次排查 iptables 问题时直接对照操作。
返回列表