Linux防火墙iptables实战指南:四表五链、NAT与运维排错全解析
2026/9/15 2:48:52 网站建设 项目流程

这两年一直在做云上系统的网络运维,iptables这个老伙计始终绕不开。虽然现在firewalld、ufw这些前端工具用起来挺方便,但真到了排查生产故障、写初始化脚本、调Docker网络策略的时候,最终还是要直面iptables本身。这篇是系列笔记的第四篇,我打算把最近一年在项目里反复用到的知识点重新梳理一遍——不聊那些平时用不上的冷门参数,只讲真正会帮你解决问题的东西。

1. 先想清楚:为什么2026年了还在用iptables

很多人觉得iptables是"过时技术",毕竟nftables都出来好些年了,firewalld也成了各大发行版的默认前端。但现实是,你打开一台CentOS 7.3的老机器,或者接手一套多年前部署的生产环境,里面跑的仍然是iptables。即便是新装的Ubuntu 22.04/24.04,底层虽然换成了nftables,但为了兼容性,系统里仍然装着一个iptables-nft的兼容层,你敲iptables命令照样能用。

这里有个特别容易混淆的点,必须说清楚:

工具实际作用前端还是后端
iptables直接操作内核netfilter框架的规则命令工具(前端)
firewalld管理防火墙规则的服务firewalld是前端,底层调用iptables/nftables
ufwUbuntu下的简化防火墙同样是前端,底层调iptables
nftables新一代内核包过滤框架后端框架,和netfilter并存

我遇到过不少同行,在firewalld里加了规则发现不生效,然后直接用iptables -F把规则全清了——这种做法相当危险。因为firewalld维护的规则链和手动加的iptables规则链是两套东西。firewalld的规则放在filter表的IN_ZONES_*等自定义链里,你直接用iptables -F INPUT,只会清空INPUT链,kernel会接着走firewalld创建的链。看起来好像"没影响",但实际上如果你在INPUT链里加过自定义规则,就全没了。

所以我的建议很直接:如果你在用firewalld,就优先用firewall-cmd管理;如果你习惯iptables,就直接禁用firewalld,统一用iptables-service管理。两套并存是生产环境里最折磨人的问题源头。写这篇博文,就是想把iptables这一套原生用法彻底讲透,适合那些需要在裸机、云服务器、Docker宿主机上直接操作防火墙规则的人参考。

2. 四表五链不是背出来的:把内核数据走向画一遍就懂了

网上关于"四表五链"的文章非常多,但大部分人看完只记住了名词,遇到实际问题还是不知道怎么用。我也经历过这个阶段,后来发现关键在于把数据包的走向想清楚,而不是死记表链对应关系。

2.1 五条链到底在哪几个检查点

所谓"五链",其实是内核netfilter框架在数据包路径上预设的五个检查点(hook):

  • PREROUTING:数据包刚进入协议栈,还没做路由决策
  • INPUT:数据包目标地址是本机时,进入本机协议栈前
  • FORWARD:数据包目标地址不是本机,需要转发时
  • OUTPUT:本机进程发出的数据包,离开协议栈前
  • POSTROUTING:数据包即将离开网卡前

这五个点的顺序决定了规则执行的先后逻辑,比如你写了一条DNAT规则,必须放在PREROUTING链,因为要在路由决策之前改写目标地址,否则内核根本不知道该把包转发给谁。同理,SNAT必须放在POSTROUTING链,因为源地址的改写要等包真正要出网时才算数。

2.2 数据包经过哪些表,顺序是什么

现在把表和链套起来理解。每个检查点上会按优先级依次执行raw → mangle → nat → filter。优先级最高的是raw,它主要用来给数据包打NOTRACK标记,跳过连接跟踪;mangle用于修改数据包头部字段(比如TOS、TTL);nat做地址转换;filter做允许/拒绝的过滤。

画个简单的文字流程:

  • 外部数据包进网卡 → PREROUTING(raw → mangle → nat) → 路由决策 → 如果是本机 → INPUT(mangle → filter) → 本机进程
  • 外部数据包进网卡 → PREROUTING(raw → mangle → nat) → 路由决策 → 如果是转发 → FORWARD(mangle → filter) → POSTROUTING(mangle → nat) → 出网卡
  • 本机进程发包 → OUTPUT(raw → mangle → nat → filter) → 路由决策 → POSTROUTING(mangle → nat) → 出网卡

注意OUTPUT链的顺序比较特殊,filter排在nat后面。这个设计的原因是:OUTPUT链上要先处理NAT规则(比如本机访问某个地址的流量要映射到另一个地址),再做过滤,否则你基于策略路由或地址转换后的内容做限制就会失效。

2.3 理解四个表的职责边界

filter表只做一件事:放行或拒绝,term为ACCEPT、DROP、REJECT。平时写防火墙策略,99%的操作都在filter表,而且默认就在这个表上操作。

nat表做地址转换,包含SNAT、DNAT、MASQUERADE、REDIRECT这几种target。强调一下,nat表规则一般不写DROP或ACCEPT,因为它的职责是改地址而不是做判断。

mangle表专门改报文,常见的用途是修改TOS字段做QoS标记,或者改TTL,普通场景基本用不到。raw表更冷门,只有在做连接跟踪性能优化或者特殊转发需求时才会碰。

这样拆开想清楚,你在写规则的时候脑子里就会有个判断:这条规则要放在哪条链上?应该走哪个表?比如有人想让外网访问内网机器,第一反应是加ACCEPT规则,结果发现加了还是不通,其实应该用DNAT。这就是没分清filter和nat的边界。

3. 日常运维用得最多的iptables命令,逐条拆参数

命令这东西不常用就是会忘,我每次隔几个月再看,也要重新man一下。所以我把第一线运维里真正高频的命令整理了一份,每一行都标注了参数的含义和适用场景。

3.1 查看规则:iptables -L -n -v --line-numbers

iptables -L -n -v --line-numbers

-L表示列出规则,-n表示不做DNS反解,直接显示IP地址。这个极其重要,如果不加它,一条规则可能要卡好几秒做地址解析,而且解析出来的主机名会让你完全看不懂。 -v显示更详细的信息,包括每个规则匹配了多少包、多少字节,这是排查规则有没有命中的关键依据。--line-numbers给每条规则加上序号,后面做精确插入或删除时会用。

我建议排查问题时每次都看两遍:

第一遍用iptables -L -n -t filter看filter表,这是最常用的。第二遍用iptables -t nat -L -n -v检查NAT规则。很多人写完端口映射后,默认看filter表,发现没有规则,就开始怀疑服务有问题,其实问题是DNAT规则没写对或者没加载。

3.2 追加、插入、替换、删除规则

# 追加:把规则加到链末尾 iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT # 插入:把规则插到链顶(第1条) iptables -I INPUT -s 203.0.113.5 -j DROP # 替换:把第3条规则换成新的 iptables -R INPUT 3 -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT # 删除:按规则内容删 iptables -D INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT # 删除:按行号删 iptables -D INPUT 3

这些操作里最容易出问题的是先后顺序。iptables规则是按顺序匹配的,第一条匹配了就执行,后面的规则不会再看了。如果你把-I INPUT 1 -j DROP这种拒绝性规则插在最前面,那后面所有ACCEPT规则全部失效。我之前就见过有人把默认策略改成DROP后,想在最后加一条允许SSH的规则,但因为DROP已经在最前面了,SSH始终连不上。记住:白名单放行规则一定要放在拒绝规则前面。

3.3 设置默认策略和清空规则

# 设置INPUT链默认策略为DROP iptables -P INPUT DROP # 清空某条链的所有规则(注意不是恢复默认策略) iptables -F INPUT # 清空所有自定义链 iptables -X # 计数器清零 iptables -Z

关于-F这个操作我多啰嗦几句。它只会把链上的规则清掉,但默认策略(默认策略是链的属性,不是规则)不会变。如果你想恢复防火墙到"出厂状态",需要两条命令配合:

iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT iptables -t nat -F iptables -t filter -F iptables -t mangle -F

这些都是重量级操作,建议在测试环境先演练一遍。生产环境清空防火墙规则的瞬间,所有连接全部中断,你通过SSH远程操作的话,会直接把自己锁在外面。我个人的习惯是:修改防火墙前,先开一个后台定时任务,比如at now + 5 minutes执行恢复脚本,万一自己把网络搞断了,至少还能救回来。

3.4 保存规则:不同发行版的差异

  • CentOS 6 / 老系统:service iptables save,规则写在/etc/sysconfig/iptables
  • CentOS 7+ 且安装了iptables-services:service iptables save
  • Ubuntu:需要先安装iptables-persistent,然后netfilter-persistent save,规则在/etc/iptables/rules.v4

有一个比较迷惑的情况是:Ubuntu新版本里service iptables save这条命令可能不存在,因为服务名不是iptables,而是netfilter-persistent。我建议一律用restore的方式加载规则,最稳。

4. 匹配条件进阶:IP段、端口范围、状态和字符串

当你掌握了增删改查,下一步就是学会组合匹配条件。iptables的匹配条件决定了规则能管住什么样的流量,条件越精确,规则越安全。

4.1 按IP和网段匹配

# 单IP iptables -A INPUT -s 192.168.1.100 -j DROP # 网段 iptables -A INPUT -s 10.10.0.0/16 -j ACCEPT # 目标地址 iptables -A OUTPUT -d 203.0.113.0/24 -j DROP # 取反匹配 iptables -A INPUT ! -s 192.168.1.100 -j DROP

重点说一下取反匹配。! -s 192.168.1.100表示除了这个IP以外的所有来源都执行该规则。这种写在生产环境中风险极大,因为"除了A之外都拒绝"的规则,意味着所有新IP段都被一刀切挡在外面。我建议用取反之前先把下一跳、回程路由都确认一遍,否则很容易误伤。

4.2 按端口范围和服务匹配

# 单个端口 iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 端口范围 iptables -A INPUT -p tcp --dport 8000:8100 -j ACCEPT # 多个不连续端口,用multiport模块 iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT # 指定源端口(一般用于特殊协议,正常场景用不到) iptables -A INPUT -p tcp --sport 1024:65535 -j ACCEPT

-sport和--dport的区别一定要分清楚。--dport是目标端口,也就是客户端要访问的端口;--sport是源端口,通常由客户端随机分配。新手最常犯的错是写-p tcp --sport 443 -j ACCEPT想放行HTTPS,结果这个规则根本不管用,因为客户端发起HTTPS请求时的源端口是随机的高位端口,不是443。

4.3 基于连接状态(state)的匹配

iptables最强大的能力之一就是连接跟踪。用-m conntrack --ctstate可以匹配连接所处的状态。四个最常用的状态:

  • NEW:新建连接的第一个包
  • ESTABLISHED:已建立的连接后续包
  • RELATED:与现有连接相关的子连接,典型的是FTP数据连接、ICMP错误回包
  • INVALID:无法识别或异常的包,建议直接DROP

实践中最经典的一组规则是:

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate INVALID -j DROP iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT

这组规则的意思是:已建立的连接及其关联连接直接放行,异常包直接丢弃,只对SSH这个服务的NEW连接额外放行。这是真正的白名单思路,它能保证外网只能主动访问22端口,但内网主动访问外网的响应包都能正常回来。

4.4 字符串匹配做内容过滤

-m string模块可以基于应用层内容做匹配,比如屏蔽包含特定关键字的请求:

iptables -A FORWARD -m string --string "blocked-keyword" --algo bm -j DROP

注意--algo参数必须写,可选的算法有bm(Boyer-Moore)和kmp。性能上bm更快,用实际测试来看,绝大多数场景bm足够。但这种匹配有开销,而且容易误伤正常流量,生产环境我很少用,顶多用于临时应急,不建议做常态化防守手段。

5. 黑白名单的真正用法:默认策略决定了安全水位

做防火墙策略,最核心的设计决策就是默认策略到底是ACCEPT还是DROP,这也决定了你的系统是"白名单优先"还是"黑名单优先"。

5.1 黑名单策略:默认ACCEPT,只挡已知坏人

iptables -P INPUT ACCEPT iptables -A INPUT -s 1.2.3.4 -j DROP iptables -A INPUT -s 5.6.7.0/24 -j DROP

这种模式适合内网环境、对外服务较少、或者团队对网络行为不了解的场景。它的优点是不容易影响正常业务,缺点也很明显:所有未知攻击流量都是先到达服务端,由业务程序承受攻击压力,防火墙没有起到前置防护的作用。

5.2 白名单策略:默认DROP,只放行明确允许的

iptables -P INPUT DROP iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT

白名单模式才算是真正发挥了防火墙的价值。把默认策略设为DROP后,所有没显式放行的入站流量全部丢弃,攻击面大幅缩小。这里有几个容易被忽略的细节:

第一,一定要先放行-i lo回环接口。很多人在本机调试服务时发现不通,先怀疑防火墙,其实就是回环流量被DROP了。第二,ESTABLISHED,RELATED要放在最前面,保证所有已建立的连接不受影响,否则你SSH登上去敲了默认DROP的命令,下一秒就断连了。

5.3 DROP和REJECT的选择

这个二选一的问题每个做运维的都纠结过。我直接给一个结论表格:

策略返回给对端的信息适用场景
DROP无任何回包,表现为超时对外隐藏服务端口、防止端口扫描探测
REJECT返回拒绝消息(如tcp-reset或icmp-port-unreachable)本机拒绝访问时希望快速失败,避免客户端长时间等待

我个人在实际项目里的习惯是:公网入站一律DROP,内网互访需要快速反馈的场景用REJECT。举个例子,内网有台应用服务器要访问数据库的3306端口,如果数据库防火墙DROP了这条连接,应用服务器要等TCP超时(大约几十秒甚至更久)才会报错,对线上业务来说这个等待太痛苦了;如果用REJECT,应用服务器几乎立刻拿到连接被拒的反馈,重试机制很快就能触发。

6. 地址转换与端口映射:NAT的落地姿势

NAT是防火墙最常用的功能之一,在云上、物理机、虚拟机环境都是刚需。很多人配端口映射配不通,其实就是没搞清楚SNAT和DNAT的差异以及它们分别应该在哪个链上操作。

6.1 SNAT和MASQUERADE,到底用哪个

SNAT(源地址转换)的作用是把内网出去的包源地址改成公网或指定IP。典型命令:

iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j SNAT --to-source 203.0.113.10

MASQUERADE是SNAT的变体,自动获取出口网卡的当前IP作为转换地址:

iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE

两者的区别在于:SNAT的源地址是固定的,如果出口IP变了(比如拨号上网重连),规则就失效了;MASQUERADE动态获取出口IP,每次连接都实时读取网卡地址,适合出口IP会变的场景。

代价是MASQUERADE比SNAT稍慢一点,因为它每次都要去查询网卡当前IP,而在固定的云服务器上SNAT可以提前算好。所以我一般在云主机上写死SNAT,在家庭宽带、临时服务器上才用MASQUERADE。

6.2 DNAT端口映射,从外网访问内网服务

把公网IP的8080端口映射到内网一台服务器的80端口:

iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.20:80

这里必须写在PREROUTING链上,因为必须在路由决策前把目的地址改掉,内核才会把包转发到192.168.1.20。同时还需要开启IP转发:

echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf sysctl -p

写了DNAT后,还要考虑后续的转发放行问题:

iptables -A FORWARD -d 192.168.1.20 -p tcp --dport 80 -j ACCEPT

这个FORWARD规则特别容易被漏掉。默认策略是DROP的时候,如果你只写了DNAT,没写FORWARD放行,那包到了转发链路会被丢掉,端口映射始终不生效。

6.3 本机端口重定向:REDIRECT

有时需要把本机收到的某个端口流量转到另一个本地端口,比如让访问8080的流量直接交给本机80端口的服务处理:

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80

注意REDIRECT只在PREROUTING或OUTPUT链上生效,它的目标是本机,不能做跨主机转发。这种用法常见于透明代理场景,或者临时把一个服务端口隐藏起来。

7. 端口不通时,我按这个链路逐层排查

写防火墙规则只是第一步,真正麻烦的是排错。每当有同事跑来说"我端口访问不了",我基本都是按下面这个检查顺序来定位问题,效率最高,也最不容易漏项。

7.1 第一步:确认服务在监听

ss -lntp | grep 8080

看输出里有没有LISTEN状态,监听地址是0.0.0.0还是127.0.0.1。如果服务只监听在127.0.0.1,那外部本来就访问不了,跟防火墙没关系。这一步能排除掉一半的"假防火墙故障"。

7.2 第二步:检查iptables规则是否命中

iptables -L -n -v --line-numbers

重点看INPUT链里有没有一条ACCEPT规则匹配你想要的端口。另外看计数器,如果规则确实生效,Packets那列数字会一直增长。如果数字是0,说明流量根本就没到这条规则,问题在更前面的链路。

一个比较隐蔽的问题:很多人写规则用-p tcp --dport 8080,但流量进来时如果是通过NAT转发的,那么FORWARD链上还要有相应的放行规则。所以遇到转发场景,filter表的INPUT和FORWARD链都要检查。

7.3 第三步:确认firewalld是不是躲在后面

systemctl status firewalld

如果firewalld是active状态,而你在iptables里改了规则,firewalld会在某个时间点把你手动改的内容覆盖掉(特别是它重启时)。处理办法是统一管理:要么用firewalld,要么彻底禁用firewalld、启用iptables。

7.4 第四步:检查云平台安全组

云服务器上还有一个"远端防火墙"——安全组。这是很多人最容易忽略的一环。你在Linux内部把防火墙放得再开,安全组没放行对应端口,流量也一样进不来。我当时排查一台阿里云ECS的8080端口,在机器上curl本机明明通,但外部访问就是不行,最后发现就是安全组没加规则。

安全组和iptables的区别在于:iptables是服务器操作系统层面的过滤,安全组是云平台虚拟化网络层面的过滤,两者的规则叠加生效。

7.5 第五步:看Docker有没有干扰FORWARD链

如果宿主机上装了Docker,Docker daemon自己在filter表里维护了一批规则,放在DOCKER链、DOCKER-USER链等自定义链里。这些链的优先级高于你的自定义规则,可能导致你写在FORWARD链上的规则被跳过。

Docker官方建议:需要自定义防火墙规则时,写进DOCKER-USER链,不要在默认的FORWARD链里乱动,否则Docker的重启可能直接覆盖你写的规则。

8. 别把规则写死在命令行:持久化、脚本化、防误伤

在生产环境直接敲iptables命令,等于把规则放在一个随时会消失的沙地里。系统重启后规则全没,或者哪次误操作把链清了,后果不堪设想。我一直强调:防火墙规则要么写进持久化文件,要么做成一个自解释的脚本,纳入代码管理。

8.1 把当前规则保存到文件

最常见的做法是用iptables-save导出规则:

iptables-save > /etc/iptables/rules.v4 iptables-restore < /etc/iptables/rules.v4

iptables-save的输出格式是iptables-restore认识的格式,一条条对应。在Ubuntu系统上可以配合iptables-persistent实现重启自动加载:

apt install iptables-persistent netfilter-persistent save netfilter-persistent reload

CentOS 7+如果直接装了iptables-services,那就更简单:

systemctl enable iptables systemctl start iptables

它的规则文件在/etc/sysconfig/iptables,systemctl restart iptables会自动加载。

8.2 把规则写成一个bash脚本

我习惯把规则组织成初始化脚本,方便批量部署到多台机器。脚本结构大概是:

#!/bin/bash # 清理所有规则,恢复默认状态 iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT iptables -t nat -F iptables -t filter -F iptables -t mangle -F iptables -X # 开启IP转发(如果这台机器有转发需求) echo 1 > /proc/sys/net/ipv4/ip_forward # 放行回环与已建立连接 iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # 放行ssh / web iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT # 默认策略放最后设置 iptables -P INPUT DROP iptables -P FORWARD DROP

注意脚本里默认策略放在最后设置,而不是最前面,这样能减少"半成品状态"造成的窗口期。顺序就是:先放行,后拒绝,最后收紧默认策略。

8.3 防误伤的几条经验

修改防火墙规则时,我的习惯是分几步走,降低操作风险:

第一,先用at now + 5 minutes加一个定时恢复任务。内容是把当前规则的备份文件自动恢复回来。如果操作完5分钟内一切正常,再手动取消这个任务。万一操作失误导致SSH断了,过几分钟规则自动恢复,你还能重新连上去,不至于要从机房或者云控制台去救。

第二,不要在高峰期几分钟内连续修改多条重要规则。每次只改一条,观察业务日志和连接数,稳定后再改下一条。

第三,规则注释写上用途。iptables支持-m comment --comment

iptables -A INPUT -s 10.20.0.0/16 -p tcp --dport 3306 -j ACCEPT -m comment --comment "allow internal app to mysql"

半年后你再回来看规则,如果每条都带注释,排查速度能快好几倍。没注释的规则到时候真的就和天书一样。

9. 我在生产环境里踩过的几个坑,希望你绕开

最后分享几个真实踩过的坑。做运维就是这样,别人的教训比自己踩一遍划算得多。

9.1 坑一:清空规则把自己锁在服务器外

有一次我远程在一台海外云主机上调整防火墙,想都没想就执行了iptables -F INPUT,但当时默认策略已经被设成了DROP。结果就是所有入站连接包括SSH全被丢弃,我只能通过云厂商的VNC控制台去救。从那以后每次动防火墙,我都会先确认默认策略,并且先开好"逃生通道":比如先加一条-A INPUT -s 我的办公网IP -j ACCEPT,确认放行没问题了再继续操作。

9.2 坑二:规则顺序导致白名单失效

给一个内部运维平台配置白名单,把公司出口IP加进了ACCEPT规则,但发现访问依然被拒。排查了半天才看到,后面有一条-A INPUT -j DROP的兜底规则放在ACCEPT前面了,因为我自己加规则的时候顺手插到了顶部,且没注意顺序。iptables规则是线性匹配的,匹配到DROP后直接执行,后面的ACCEPT永远不会生效。

这个问题的教训是:明确的DROP规则和兜底DROP规则要区分开。如果你把兜底DROP放在最前面,那你加的所有ACCEPT永远都没用。

9.3 坑三:conntrack表满了导致新连接全部丢弃

一台流量很大的业务服务器,运行一段时间后突然出现大量连接超时。检查dmesg发现:

nf_conntrack: table full, dropping packet

这是连接跟踪表溢出的典型症状。默认的nf_conntrack_max可能只有几万条,对于高并发NAT转发场景根本不够用。解决方法是调大:

sysctl -w net.netfilter.nf_conntrack_max=1048576 sysctl -w net.netfilter.nf_conntrack_buckets=262144

同时可以缩短超时时间,尤其是TIME_WAIT状态的连接:

sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30

这个问题不在iptables规则本身,但对使用了大量DNAT/SNAT转发的环境来说,如果conntrack表满,再正确的规则也会丢包。

9.4 坑四:Docker重启后自定义规则被冲刷

Docker daemon虽然用的是iptables规则来实现容器网络,但它在启动时会对filter表、nat表做初始化。假如你在宿主机的FORWARD链上手工加了放行规则,Docker一重启,规则就可能被刷新掉,手工加的内容全没了。

应对办法是:如果你需要在Docker宿主机上做流量策略,就写到DOCKER-USER链里。这个链是Docker专门留给用户自定义规则的,Docker重启也不会动它。排查时如果发现规则总莫名消失,先看看是不是Docker自己刷的。

10. 一个小小的收尾建议

iptables这套东西,看十篇文章不如自己在测试环境搭两台虚拟机来回转发几次数据包。我在实际中摸索出来的习惯是:先在草稿纸上按"源地址/目标地址/协议/端口/动作"把规则列出来,再动手敲命令,最后用iptables-save保存。这样基本不会出大乱子。希望这篇小结对你有用,咱们下篇见。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询