深入理解iptables:Linux防火墙核心机制与实战配置指南

📅 2026/7/6 20:56:48 👁️ 阅读次数 📝 编程学习
深入理解iptables:Linux防火墙核心机制与实战配置指南

1. 项目概述:为什么iptables是Linux运维的“看门人”?

干了这么多年Linux运维和系统管理,我处理过无数服务器安全问题,从简单的端口暴露到复杂的DDoS攻击。在这些实战中,有一个工具几乎每次都会出场,它就是iptables。很多人一听到iptables就觉得头大,觉得它命令复杂、规则难懂,是Linux学习路上的“拦路虎”。但我想说,一旦你理解了它的设计哲学和核心机制,它就会成为你最可靠、最灵活的“看门人”。

简单来说,iptables是Linux内核中Netfilter防火墙框架的用户空间命令行工具。你可以把它想象成一个功能极其强大的数据包过滤器、修改器和路由器。所有进出你服务器的网络流量,都要经过iptables设定的层层关卡(我们称之为“链”),由你定义的规则来决定是放行、丢弃还是进行其他处理。无论是保护你的Web服务器只开放80和443端口,还是搭建一个NAT网关让内网机器共享上网,甚至是做端口映射、流量整形,都离不开它。

为什么在云原生和容器化大行其道的今天,我们还要深入理解这个“古老”的命令行工具?原因有三:第一,基础性。它是Linux网络安全的基石,很多高级防火墙方案(如firewalld)和容器网络(如Docker的bridge网络)底层都依赖或兼容iptables规则。第二,灵活性。它允许你进行极其精细的控制,从IP、端口到协议类型、连接状态,甚至数据包内容,你都能制定规则。第三,普适性。几乎所有的Linux发行版都预装了它,在紧急故障排查或最小化系统环境中,它往往是唯一可用的防火墙工具。

这篇文章,我将从一个老运维的角度,带你彻底吃透iptables。我不会只罗列命令,而是会拆解它的核心概念、工作机制,并结合大量生产环境中的真实场景,告诉你每条命令背后的“为什么”,以及那些手册里不会写的“避坑指南”。无论你是刚接触Linux的新手,还是想巩固基础的开发者,都能从这里获得可以直接上手的实战经验。

2. 核心概念拆解:四表五链与数据包的一生

在动手敲命令之前,我们必须先理解iptables的核心架构。很多人学不好iptables,就是因为一上来就死记硬背命令,结果规则一复杂就晕了。其实,它的设计非常清晰,核心就是“四表五链”。

2.1 五条链(Chains):数据包的必经之路

想象一下,数据包就像一辆辆要进入或离开你服务器这座“城堡”的汽车。iptables在城堡的关键位置设立了五个检查站,这就是五条链。每条链对应数据包生命周期中的一个特定阶段:

  1. PREROUTING链:数据包刚到达网络接口,在进行路由决策之前。这是数据包进入系统后的第一站。通常在这里做目标地址转换(DNAT),比如把访问公网IP:8080的请求,转发到内网服务器的80端口。
  2. INPUT链:数据包经过路由决策后,如果目标是本机(比如有人SSH连接你的服务器),就会进入这条链。这是我们做主机防火墙最常打交道的链,用来控制哪些外部流量可以访问本机的服务。
  3. FORWARD链:数据包经过路由决策后,如果目标不是本机(你的服务器充当了路由器或网关),就会进入这条链。在这里决定是否允许数据包被转发到另一个网络。
  4. OUTPUT链由本机进程产生的数据包,在发出之前,会经过这条链。可以用来控制本机程序能访问哪些外部资源。
  5. POSTROUTING链:数据包即将离开网络接口之前。这是数据包离开系统前的最后一站。通常在这里做源地址转换(SNAT),比如让内网机器通过网关服务器上网时,将内网IP替换为网关的公网IP。

一个数据包的旅程:假设一台外部电脑(IP: 1.2.3.4)要访问你服务器(IP: 5.6.7.8)上的网站。

  1. 数据包到达网卡 →PREROUTING链(检查,这里一般不做过滤)。
  2. 路由决策发现目标IP 5.6.7.8就是本机 →INPUT链(在这里,你的规则判断是否允许访问80端口)。
  3. Web服务器(如Nginx)处理请求,生成响应数据包。
  4. 响应数据包发出前 →OUTPUT链(检查本机发出的包)。
  5. 响应数据包离开网卡前 →POSTROUTING链(一般不做处理,直接发出)。

2.2 四张表(Tables):规则的功能分类

光有检查站(链)还不够,我们还需要规定检查员(规则)的职责。iptables用四张表来对规则进行功能分类,不同的表能做的事情不同,并且有固定的生效链。

  1. filter表:这是最常用的表,负责过滤数据包,决定是放行(ACCEPT)还是丢弃(DROP/REJECT)。它只能作用于INPUT、FORWARD、OUTPUT这三条链。我们常说的“设置防火墙规则”,大部分就是在配置filter表。
  2. nat表:负责网络地址转换。比如家庭路由器让多台设备共享一个公网IP,就是它的功劳。它只能作用于PREROUTING、OUTPUT、POSTROUTING这三条链(注意,某些旧资料可能说FORWARD链也可以,但在实际NAT场景中,FORWARD链通常不用于nat表规则)。
  3. mangle表:这个表功能特殊,用于修改数据包的元数据,比如修改TTL(生存时间)、设置QoS(服务质量)标记等。它比较底层,五条链都可以作用。
  4. raw表:主要用于连接跟踪的豁免。连接跟踪(conntrack)是iptables的一项高级功能,能识别一个连接(如一次TCP会话)。但有些流量(比如某些游戏或VPN流量)我们不希望被跟踪,就可以在raw表中设置规则。它作用于PREROUTING、OUTPUT链。

表和链的关系是关键:你可以把“链”想象成高速公路上的五个固定收费站,而“表”是四类不同的检查项目(如安检、海关、检疫、超载检查)。一辆车(数据包)经过某个收费站时,会依次接受这四类检查(如果该检查站在此收费站有设点的话)。执行的优先级是固定的:raw -> mangle -> nat -> filter

2.3 规则(Rules)、匹配(Matches)与目标(Targets)

理解了表和链的框架,我们再来看里面的具体内容。

  • 规则(Rule):就是一条具体的指令,它由两部分核心构成:匹配条件处理动作。规则按顺序排列在链中。
  • 匹配条件(Matches):用来判断当前数据包是否符合这条规则。可以是:
    • 通用匹配:如源/目标IP地址(-s, -d)、协议(-p tcp/udp/icmp)、流入/流出网卡(-i, -o)。
    • 扩展匹配:需要加载额外模块,功能更强大。如:
      • --dport,--sport:匹配目标/源端口(必须配合-p tcp-p udp使用)。
      • -m state --state NEW,ESTABLISHED,RELATED:匹配连接状态(这是实现“状态化防火墙”的关键,后面会细说)。
      • -m multiport --dports 80,443:匹配多个端口。
      • -m limit --limit 5/sec:限制匹配速率。
  • 处理动作(Targets):当数据包满足所有匹配条件时,要执行的操作。常见的有:
    • ACCEPT:接受数据包,允许其通过。
    • DROP:丢弃数据包,不给任何回应。就像对方和你说话,你直接走开不理他。这是更安全的拒绝方式。
    • REJECT:拒绝数据包,会返回一个错误响应(如tcp-reset)。就像对方和你说话,你回一句“不行”。虽然友好,但暴露了防火墙的存在。
    • SNAT/DNAT:在nat表中进行源/目标地址转换。
    • LOG:将匹配的数据包信息记录到系统日志(如/var/log/messages),然后继续匹配下一条规则。用于调试和审计。
    • 自定义链:跳转到另一个你自定义的链去执行规则,执行完再返回。

规则匹配的顺序至关重要!iptables从链的第一条规则开始,逐条向下检查。一旦某条规则匹配成功,就执行对应的动作(ACCEPT/DROP等),并且停止继续检查本链内后续的规则(除非动作是LOG或跳转到自定义链)。如果所有规则都不匹配,则执行该链的默认策略(Policy)

3. 命令详解与实战配置:从零构建你的防火墙

理论说了一堆,现在我们来点实际的。iptables的命令看起来参数很多,但其实有很强的规律性。一个完整的规则命令通常遵循这个结构:

iptables -t <表名> <命令> <链名> [规则号] <匹配条件> -j <动作>

其中-t <表名>可以省略,默认为filter表。

3.1 基础管理命令:查看、清空、设置策略

在开始添加具体规则前,我们先学会如何“看”和“清”。

查看规则:这是最常用的操作。

# 查看filter表(默认)的所有规则 iptables -L # 查看更详细的信息,包括数据包计数和字节计数,-v显示详情,-n不做域名反解(显示IP,更快) iptables -L -n -v # 查看nat表的所有规则 iptables -t nat -L -n -v # 查看规则并显示行号,这在删除特定规则时非常有用 iptables -L --line-numbers # 查看指定链的规则,例如只查看INPUT链 iptables -L INPUT -n -v

清空规则与计数器:在调试或重新配置时,往往需要从干净的状态开始。

# 清空filter表所有链的规则(不会改变默认策略) iptables -F # 清空nat表所有链的规则 iptables -t nat -F # 删除filter表中所有用户自定义的空链 iptables -X # 将filter表所有链的数据包和字节计数器归零 iptables -Z # 组合命令:清空所有规则、删除自定义链、计数器归零(常用初始化操作) iptables -F && iptables -X && iptables -Z

注意-F-X不会删除内置链(INPUT, OUTPUT等),也不会改变链的默认策略。如果你之前设置了iptables -P INPUT DROP,清空规则后INPUT链的默认策略依然是DROP,这可能导致你立刻被断开SSH连接!所以清空前最好先确认或设置一个宽松的默认策略。

设置默认策略:默认策略是当数据包不匹配任何规则时的最终处理方式。

# 设置INPUT链的默认策略为DROP(默认拒绝所有入站) iptables -P INPUT DROP # 设置FORWARD链的默认策略为DROP(默认禁止转发) iptables -P FORWARD DROP # 设置OUTPUT链的默认策略为ACCEPT(默认允许所有出站,通常这样设置方便) iptables -P OUTPUT ACCEPT

重要警告:在远程服务器上,千万不要直接执行iptables -P INPUT DROP!除非你已经通过规则允许了当前的SSH连接。否则你会立刻失去连接。正确的做法是,先添加允许SSH的规则,再设置默认DROP策略。

3.2 规则增删改查:精细控制之道

添加规则:使用-A(append) 在链的末尾追加,或-I(insert) 在指定位置插入。

# 在INPUT链末尾添加一条规则,允许来自192.168.1.0/24网段的TCP 22端口(SSH)连接 iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT # 在INPUT链的第1条位置插入规则(优先级最高),允许本地回环接口(lo)的所有流量 iptables -I INPUT 1 -i lo -j ACCEPT # 如果不指定位置,-I 默认插入到链的首位(等同于 -I INPUT 1) iptables -I INPUT -i lo -j ACCEPT

为什么允许lo接口很重要?很多本地服务(如数据库连接、Docker容器通信)会通过回环地址(127.0.0.1)进行内部通信。如果不允许,可能导致这些服务异常。

删除规则:使用-D(delete)。

# 方法1:通过完整的规则描述来删除(必须完全匹配) iptables -D INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT # 方法2:通过规则的行号来删除(更常用,先用 --line-numbers 查看) iptables -L INPUT --line-numbers # 假设看到要删除的规则行号是3 iptables -D INPUT 3

修改规则:iptables没有直接的修改命令。通常的做法是删除旧规则,再添加新规则。或者使用-R(replace) 替换指定行号的规则,但需要完整重写规则,容易出错,不如删了再加直观。

3.3 状态检测:让防火墙更智能的关键

这是iptables一个极其强大的特性,也是现代防火墙的标配。它使得防火墙不再是孤立地检查每个数据包,而是能理解“连接”的概念。

-m state --state <状态>模块可以匹配连接的几种状态:

  • NEW:连接的第一个包,意味着这是一个新的连接请求。
  • ESTABLISHED:一个已经建立的连接。只要连接成功建立(完成TCP三次握手),后续该连接的双向数据包状态都是ESTABLISHED。
  • RELATED:一个与已有连接相关的连接。例如FTP的数据连接(端口20)就是控制连接(端口21)的RELATED连接。或者ICMP的错误消息(如“目标不可达”)也与触发它的TCP/UDP连接相关。
  • INVALID:无法识别或状态异常的数据包,通常直接丢弃。

这个功能为什么重要?它极大地简化了规则配置,并提高了安全性。我们来看一个经典配置:

# 1. 允许所有已建立的及相关连接进入(这是关键!) iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 2. 开放新的入站连接(如SSH, HTTP) iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT # 3. 设置默认策略为DROP iptables -P INPUT DROP

解读:规则1允许所有回包相关连接。这意味着,一旦你从服务器内部发起一个对外部网站的请求(比如curl example.com),这个请求的出站包会被OUTPUT链默认允许(假设OUTPUT策略是ACCEPT)。当外部网站的回包到达时,它的状态是ESTABLISHED,规则1会放行它。这样,你就不需要为每一个可能的回包端口单独写规则了。规则2只控制的入站连接请求。这种“允许回包,控制新请求”的模式,是配置防火墙的最佳实践之一。

3.4 一个生产环境Web服务器防火墙配置示例

假设我们有一台公网Web服务器,需要提供HTTP(80)、HTTPS(443)服务,并且我们需要通过SSH(22)管理它。我们采用“默认拒绝,显式允许”的白名单策略。

#!/bin/bash # 保存为 firewall.sh, chmod +x firewall.sh 后执行 # 1. 清除所有现有规则和计数器,设定默认策略(危险!请确认当前连接已被允许) iptables -F iptables -X iptables -Z iptables -t nat -F iptables -t mangle -F # 设置默认策略:INPUT和FORWARD默认拒绝,OUTPUT默认允许 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # 2. 允许本地回环接口,这是必须的 iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # 3. 允许状态为ESTABLISHED和RELATED的数据包进入(核心规则!) # 这条规则保证了所有由本机主动发起的连接的回包都能进来。 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 4. 允许ICMP (ping),便于网络诊断,可根据安全要求选择是否开放 iptables -A INPUT -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT # 5. 开放管理端口SSH (22)。强烈建议将源IP限制为管理IP段,例如办公室IP。 # iptables -A INPUT -s 203.0.113.0/24 -p tcp --dport 22 -m state --state NEW -j ACCEPT # 如果无法固定IP,至少使用强密码或密钥认证。这里先开放给所有IP(仅作示例,生产环境请勿这样!) iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT # 6. 开放Web服务端口 iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT # 7. (可选)记录被拒绝的数据包到日志,用于监控和调试 iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4 # 注意:LOG目标不会终止数据包匹配,匹配后还会继续向下匹配。通常放在链的最后,默认策略之前。 # 最后,INPUT链的默认策略已经是DROP,所以不匹配以上任何规则的数据包将被丢弃。 # 保存规则,使其在重启后依然生效(不同发行版保存方式不同) # CentOS/RHEL 6: service iptables save # CentOS/RHEL 7+/Ubuntu: 需要安装iptables-persistent或使用其他方法,见下文。

重要提醒:在远程服务器上执行此脚本前,务必确保第5步的SSH规则已经生效,并且你的当前连接IP在允许的源IP范围内。一个安全的做法是,先通过服务器的本地控制台(如云平台的VNC)执行,或者分步执行命令,并在执行iptables -P INPUT DROP前,先添加好允许自己IP的SSH规则并测试。

4. 高级应用场景:NAT、端口转发与流量控制

iptables不仅仅是个包过滤器,它的nat表功能让它能扮演路由器的角色。

4.1 SNAT:共享上网(源地址转换)

这是家庭路由器或公司网关的典型应用。内网机器(192.168.1.0/24)没有公网IP,需要通过一台有公网IP(假设为203.0.113.10)的Linux服务器上网。

# 首先,确保Linux服务器开启了IP转发功能(临时生效) echo 1 > /proc/sys/net/ipv4/ip_forward # 永久生效:编辑 /etc/sysctl.conf,设置 net.ipv4.ip_forward = 1,然后执行 sysctl -p # 在nat表的POSTROUTING链添加SNAT规则 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.10

原理:内网机器发出的数据包,经过网关服务器时,在POSTROUTING链(即将发出时)将其源IP从内网IP(如192.168.1.100)替换为网关的公网IP(203.0.113.10)。外部服务器回包时,目标地址是203.0.113.10,网关收到回包后,再根据连接跟踪表将目标IP转换回内网IP,送回内网机器。

对于动态公网IP(如ADSL拨号),可以使用MASQUERADE(伪装)动作,它会自动获取出口网卡的IP地址。

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ppp0 -j MASQUERADE

4.2 DNAT:端口映射(目标地址转换)

将公网IP的某个端口流量,转发到内网某台服务器的指定端口。比如将网关的公网IP203.0.113.102222端口,映射到内网服务器192.168.1.10022(SSH)端口。

iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 2222 -j DNAT --to-destination 192.168.1.100:22

原理:外部访问203.0.113.10:2222的数据包到达网关后,在PREROUTING链(路由前)将其目标IP和端口修改为192.168.1.100:22。然后系统根据新的目标IP进行路由,将其转发到内网服务器。内网服务器处理后的回包,会经过网关的SNAT(或MASQUERADE)处理,将源IP改回公网IP,返回给外部客户端。

4.3 连接限制与防攻击

iptables的扩展模块可以帮助我们抵御一些简单的攻击。

限制同一IP的并发连接数,可用于缓解CC攻击。

# 限制单个IP对80端口的并发连接数不超过50个 iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 50 --connlimit-mask 32 -j REJECT
  • --syn:只匹配TCP SYN包(新的连接请求)。
  • -m connlimit:使用连接数限制模块。
  • --connlimit-above 50:连接数超过50则触发动作。
  • --connlimit-mask 32:以32位掩码(即单个IP)为单位进行统计。如果是24,则按一个C段统计。

限制访问速率,可用于防止暴力破解或洪水攻击。

# 对SSH端口,限制每秒最多接受3个新连接,突发值设为10(允许前10个连接快速建立) iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m limit --limit 3/minute --limit-burst 10 -j ACCEPT # 超过限制的新连接将被丢弃(因为默认策略是DROP,或者可以在后面加一条REJECT规则)
  • -m limit:使用限速模块。
  • --limit 3/minute:平均速率限制为每分钟3个。
  • --limit-burst 10:令牌桶容量为10。初始时有10个令牌,每匹配一个连接消耗一个令牌,令牌会按限制速率(3个/分钟)补充。这允许短时间内有突发连接。

5. 规则管理与持久化:避免重启后功亏一篑

通过命令行配置的iptables规则是保存在内存中的,系统重启后会丢失。因此,将配置持久化是必须的。

5.1 规则保存与恢复

CentOS 6 / RHEL 6

# 保存当前规则到默认配置文件 /etc/sysconfig/iptables service iptables save # 或者使用命令 iptables-save > /etc/sysconfig/iptables # 重启iptables服务,会从配置文件加载规则 service iptables restart

CentOS 7+ / RHEL 7+ / Fedora: 这些系统默认使用firewalld。如果你想继续使用纯iptables,需要先停止并禁用firewalld,安装iptables-services

systemctl stop firewalld systemctl disable firewalld yum install iptables-services -y systemctl enable iptables systemctl start iptables # 配置好规则后,保存 service iptables save # 或 iptables-save > /etc/sysconfig/iptables

Debian / Ubuntu: Debian系没有内置的保存服务。常用的方法是安装iptables-persistent包。

sudo apt-get update sudo apt-get install iptables-persistent -y # 安装过程中会询问是否保存当前规则。安装后,可以使用以下命令手动保存IPv4规则: sudo netfilter-persistent save # 规则会被保存到 /etc/iptables/rules.v4 (IPv4) 和 /etc/iptables/rules.v6 (IPv6) # 系统启动时会自动加载这些规则。

也可以手动操作:

# 保存规则 iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6 # 恢复规则 iptables-restore < /etc/iptables/rules.v4

5.2 使用自定义脚本管理

对于复杂的规则集,或者需要动态调整的场景,维护一个Shell脚本是更清晰的方式。将前面所有的iptables命令写在一个脚本里(如/usr/local/bin/firewall.sh),并赋予执行权限。在脚本开头清空所有规则,然后从头构建。这样:

  • 版本可控:脚本可以放入Git等版本控制系统。
  • 清晰明了:所有规则一目了然,方便注释和修改。
  • 灵活执行:可以随时执行脚本以应用新的规则集。

然后,你可以通过系统的启动脚本(如/etc/rc.local,但注意该方法在某些新系统中已不推荐)或创建一个systemd服务,在开机时运行这个脚本,以实现持久化。

6. 常见问题排查与实战心得

即使理解了原理和命令,在实际操作中依然会踩坑。下面分享几个我遇到过的典型问题和处理技巧。

6.1 问题:配置完防火墙后,服务器无法访问外网了。

排查思路

  1. 检查OUTPUT链策略iptables -L OUTPUT -n。如果默认策略是DROP,而你没有任何允许出站的规则,那么本机进程发出的所有数据包都会被丢弃。通常OUTPUT策略设为ACCEPT比较安全方便。
  2. 检查INPUT链的ESTABLISHED规则:这是最常见的原因。如果你设置了iptables -P INPUT DROP,但忘记了添加-m state --state ESTABLISHED,RELATED -j ACCEPT这条规则,那么服务器对外发起请求后,外部的回包(状态为ESTABLISHED)也会被INPUT链丢弃,导致连接无法建立。症状是:能ping通外部(ICMP是独立的),但curl、wget等TCP/UDP连接超时。
  3. 检查DNS:如果域名无法解析但IP可以访问,可能是OUTPUT链屏蔽了UDP 53端口(DNS)。确保有规则iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

6.2 问题:配置了端口转发(DNAT),但内网服务无法访问。

排查思路

  1. 确认IP转发已开启cat /proc/sys/net/ipv4/ip_forward必须为1。
  2. 检查FORWARD链策略和规则:数据包在网关服务器上被转发时,不仅要经过nat表的PREROUTING链做DNAT,还要经过filter表的FORWARD链。如果FORWARD链默认是DROP,你需要添加规则允许转发的流量。
    # 允许从内网网卡(如eth1)到外网网卡(如eth0)的已建立连接及相关连接 iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许从外网网卡到内网网卡的新连接(针对DNAT后的流量) iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.100 -p tcp --dport 22 -m state --state NEW -j ACCEPT
  3. 检查内网服务器的网关和路由:内网服务器(192.168.1.100)的默认网关必须指向这台做转发的Linux服务器(192.168.1.1)。否则,内网服务器收到目标为自己的数据包后,回包可能不会发给网关。

6.3 问题:如何临时开放一个端口进行测试,测试完再关闭?

不要直接修改正在运行的规则集,容易出错。建议在测试前备份当前规则。

# 备份当前规则 iptables-save > /tmp/iptables.backup # 临时添加规则(例如开放8080端口) iptables -A INPUT -p tcp --dport 8080 -j ACCEPT # ... 进行测试 ... # 测试完毕后,恢复备份的规则 iptables-restore < /tmp/iptables.backup

或者,如果你记得添加的规则,可以直接用行号删除它。

6.4 实操心得与注意事项

  1. 顺序就是生命:iptables规则是从上到下匹配的。把最具体、最严格的规则放在前面,把最通用、最宽松的规则(如ESTABLISHED规则)放在它们后面、默认策略之前。例如,拒绝某个IP的规则应该放在允许某个端口的规则前面,如果顺序反了,允许规则先匹配,拒绝就失效了。
  2. 默认策略用DROP,但小心“把自己锁在外面”:设置-P INPUT DROP是安全的最佳实践,但务必在之前添加允许现有SSH连接和本地流量的规则。一个安全的方法是写一个脚本,在脚本开头先设置允许自己IP和SSH端口的规则,再设置默认DROP,然后一次性执行整个脚本。
  3. 善用日志(LOG Target)调试:在不确定规则是否生效时,可以在规则前插入一条LOG规则。例如,你想知道哪些到80端口的包被拒绝了,可以加一条:iptables -I INPUT -p tcp --dport 80 -j LOG --log-prefix "[IPTABLES HTTP-DENY] "。然后去/var/log/messages/var/log/syslog查看日志。注意:生产环境谨慎使用,避免日志洪水。
  4. 理解“连接跟踪”(Conntrack):状态检测(-m state)依赖于内核的conntrack模块。在高并发连接场景下(如繁忙的Web服务器、NAT网关),conntrack表可能会被填满,导致新连接无法建立。可以通过sysctl net.netfilter.nf_conntrack_max查看和调整最大值。
  5. IPv6别忘了:iptables只处理IPv4。如果你的服务器启用了IPv6,还需要用ip6tables命令配置相应的防火墙规则,否则安全防护会有缺口。

iptables的深度和广度远不止于此,它还支持更复杂的字符串匹配、时间控制、标记(MARK)等高级功能。但对于绝大多数系统管理员和开发者来说,掌握本文所述的核心概念、命令语法、状态检测、NAT转换以及规则管理,已经足以应对90%以上的日常防火墙配置需求。记住,防火墙规则是安全策略的体现,在追求安全的同时,务必保证可用性。每次修改前做好备份,修改后充分测试,这才是用好iptables这个强大工具的不二法门。