1. 项目概述为什么你需要掌握IPTables如果你在管理一台Linux服务器无论是云上的ECS、家里的树莓派还是公司内网的开发机那么“防火墙”这个词对你来说就绝不是一个可选项。它就像你家的大门决定了谁可以进来谁会被拒之门外。在Linux世界里这个“大门”最经典、最核心的守护者就是IPTables。很多人一听到IPTables就觉得头大觉得它命令复杂、概念抽象。确实它不像一些图形化防火墙工具那样点几下鼠标就能配置好。但它的强大之处也正在于此它直接运行在Linux内核中效率极高功能极其灵活。你可以用它做最基础的端口开关也能实现复杂的网络地址转换NAT、流量整形甚至是构建一个简易的网关路由器。可以说理解了IPTables你就掌握了Linux网络安全的底层逻辑。我见过不少运维新手一出问题就想着“先把防火墙关了试试”这其实是非常危险的习惯。关闭防火墙固然能暂时解决问题但也让服务器门户大开。正确的做法是学会如何精准地“配置”防火墙而不是简单地“关闭”它。这篇指南的目的就是带你从零开始理解IPTables的核心工作机制并学会用一系列清晰、安全的命令来构建你的第一道防线。我们会从“数据包如何流经系统”这个根本问题讲起一步步拆解表、链、规则最后落到具体的命令行操作和日常维护技巧上。2. 核心概念拆解数据包、表、链与规则在动手敲命令之前我们必须先理清几个核心概念。如果把IPTables看作一个物流分拣中心那么“表”就是不同的分拣车间“链”是车间里的流水线“规则”就是流水线上工人手里的分拣手册。而“数据包”就是等待被处理的快递。2.1 数据包的生命周期与五条关键链一个网络数据包进入或离开你的Linux主机时会经过几个预设的“检查点”这些检查点在IPTables中被称为“链”Chain。理解数据包的流向是理解所有规则配置的基础。主要有五条内置链它们分别位于网络栈处理流程的不同位置PREROUTING链数据包刚进入网络接口在进行路由决策之前。这是数据包遇到的第一关。通常在这里做目标地址转换DNAT比如把访问公网IP:80端口的请求转发到内网服务器的192.168.1.100:8080。INPUT链经过PREROUTING后如果路由决策判断这个数据包的目标地址是本机比如有人SSH连接你的服务器那么它就会进入INPUT链。这是我们最常打交道的链用于过滤进入本机进程的数据包。FORWARD链同样经过PREROUTING后如果路由决策判断这个数据包的目标地址是其他机器你的Linux主机充当了路由器或网关那么它就会进入FORWARD链。用于过滤需要转发的数据包。OUTPUT链由本机进程产生并准备发送出去的数据包比如你从服务器上curl一个外部网站在离开网卡之前会经过OUTPUT链。POSTROUTING链数据包即将离开网络接口在进行路由决策之后。这是数据包离开前的最后一关。通常在这里做源地址转换SNAT比如让内网机器通过网关上网时将内网IP替换为网关的公网IP。注意PREROUTING和POSTROUTING这两个链的名字非常形象。“PRE”和“POST”是相对于“路由决策”Routing这个动作而言的。记住这个就不会搞混它们的位置。2.2 四张功能各异的表链是挂载规则的钩子而规则根据功能的不同被分门别类地存放在不同的“表”Table中。IPTables默认有四张表每张表负责一类特定的功能并且只包含特定的链。filter表这是最常用的表负责过滤数据包决定是“放行”ACCEPT还是“丢弃”DROP。它内置了INPUT、FORWARD、OUTPUT三条链。我们常说的“配置防火墙规则”大部分时候就是在配置filter表。nat表负责网络地址转换Network Address Translation。当你的服务器需要做端口映射、共享上网SNAT或发布内网服务DNAT时就需要用到它。它包含PREROUTING、OUTPUT、POSTROUTING链注意没有INPUT和FORWARD。mangle表这是一个“修改”表用于对数据包进行一些特殊修改比如修改TTL值、设置QoS标记等。功能强大但日常使用较少。它包含了全部五条链PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。raw表主要用于配置“连接跟踪”的例外情况可以绕过Netfilter的连接跟踪机制提升性能。主要用于处理那些不需要状态跟踪的流量比如大量的DNS查询。它包含PREROUTING和OUTPUT链。表和链的关系总结 你可以把链想象成高速公路上的检查站而表就是检查站里不同职能的警察。一辆车数据包经过检查站时可能会被“交警”filter表查酒驾被“缉毒警”nat表查货物被“路政”mangle表查超载。但不是每个检查站都有所有类型的警察。表名主要功能包含的链filter包过滤防火墙核心功能INPUT, FORWARD, OUTPUTnat网络地址转换SNAT/DNATPREROUTING, OUTPUT, POSTROUTINGmangle修改数据包内容TTL, TOS等所有五条链raw连接跟踪豁免性能优化PREROUTING, OUTPUT2.3 规则匹配条件与处理动作规则是最终生效的指令它由两部分构成匹配条件和处理动作。匹配条件用来判断当前数据包是否适用这条规则。条件可以非常精细例如-s 192.168.1.100匹配源IP是192.168.1.100的数据包。-d 10.0.0.1匹配目标IP是10.0.0.1的数据包。-p tcp --dport 80匹配使用TCP协议且目标端口是80HTTP的数据包。-i eth0匹配从eth0网卡进入的数据包。-m state --state ESTABLISHED,RELATED匹配属于已建立连接或相关连接的数据包这是一个极其重要且常用的状态匹配。处理动作当数据包满足所有匹配条件时要对其执行的操作。常见动作有-j ACCEPT接受允许数据包通过。-j DROP丢弃直接扔掉数据包不给发送方任何回应。这是最常用的“拒绝”方式更安全。-j REJECT拒绝丢弃数据包但会向发送方返回一个“拒绝访问”的错误消息如ICMP port-unreachable。这会让对方明确知道被拒绝了。-j LOG记录日志将数据包信息记录到系统日志如/var/log/messages然后继续匹配下一条规则。-j SNAT/-j DNAT进行源/目标地址转换属于nat表。规则匹配的顺序至关重要数据包进入一条链后会从第一条规则开始按顺序逐条匹配。一旦匹配成功就执行对应的动作并且停止在本链中继续匹配后续规则。如果所有规则都不匹配则执行该链的默认策略Policy。3. 实战操作从安装到第一条安全规则理论讲得再多不如动手敲一遍。我们从一个干净的Linux环境开始一步步搭建一个基础但安全的防火墙配置。这里以CentOS/RHEL 7系列为例其他发行版命令可能略有不同如Ubuntu使用iptables-persistent包来保存规则。3.1 环境准备与基础命令首先我们需要确保IPTables工具可用并停用可能冲突的其他防火墙如firewalld。# 1. 检查iptables命令是否可用 which iptables # 如果未安装则安装CentOS/RHEL sudo yum install -y iptables-services # 2. 停止并禁用firewalld如果系统安装了它 sudo systemctl stop firewalld sudo systemctl disable firewalld # 3. 启动iptables服务并设置开机自启 sudo systemctl start iptables sudo systemctl enable iptables # 4. 查看当前filter表的规则默认可能是空的或有一些宽松规则 sudo iptables -L -n -v # -L: 列出规则 # -n: 以数字形式显示IP和端口不进行DNS反向解析速度更快 # -v: 显示详细信息如匹配的数据包计数和字节数执行iptables -L -n -v后你可能会看到一个近乎“全开放”的配置。我们的目标是将它收紧。3.2 制定一个“先允许后拒绝”的白名单策略一个安全的防火墙策略应该是“默认拒绝显式允许”。也就是说先把大门关上然后只给我们信任的流量开几扇小窗。但在配置过程中为了避免把自己锁在门外我们采用一个稳妥的步骤设置默认策略为ACCEPT确保当前连接不会中断。清空所有现有规则从一张白纸开始。配置我们需要的允许规则。最后将默认策略改为DROP。重要警告如果你是通过SSH远程连接服务器进行操作的千万不要在未添加允许SSH的规则前就将INPUT链的默认策略设为DROP否则你会立刻断开连接且无法重连。下面的步骤是安全的。# 步骤1 2设置默认策略为ACCEPT并清空所有规则 # 注意-F 是清空链内所有规则但不会改变链的默认策略Policy sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -F # 清空filter表所有链的规则 sudo iptables -t nat -F # 清空nat表 sudo iptables -t mangle -F # 清空mangle表 # 步骤3开始添加我们的允许规则 # 3.1 允许本地回环(lo)接口的通信许多本地服务依赖它 sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A OUTPUT -o lo -j ACCEPT # 3.2 允许所有已建立和相关联的连接这是保证已有连接不中断的关键 sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 这条规则允许所有由本机发起的请求的返回数据包进来。没有它你连ping一个外网地址都收不到回复。 # 3.3 允许ICMP协议即ping便于网络诊断 sudo iptables -A INPUT -p icmp -j ACCEPT # 3.4 允许SSH连接假设使用默认22端口。这是你的生命线必须确保正确 sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 如果你修改了SSH端口例如是2222则改为 --dport 2222 # 3.5 允许HTTP和HTTPS流量如果你运行Web服务器 sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 步骤4将INPUT和FORWARD链的默认策略改为DROP # 现在我们已经放行了必要的流量可以关上大门了。 sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP # OUTPUT链通常保持ACCEPT因为我们通常信任本机发出的流量。如需严格可也设为DROP但需额外配置允许的出口规则。现在你的防火墙规则应该类似这样使用sudo iptables -L -n -v --line-numbers查看Chain INPUT (policy DROP) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 2 100 8000 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 3 5 420 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 4 10 800 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 6 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 Chain FORWARD (policy DROP) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/03.3 规则的增、删、改、查插入规则-I参数将规则插入到链的指定位置默认是头部第1条。位置很重要# 在INPUT链的第1条位置插入一条规则优先匹配 sudo iptables -I INPUT 1 -s 192.168.1.0/24 -j ACCEPT # 在INPUT链的第3条位置插入一条规则 sudo iptables -I INPUT 3 -p udp --dport 53 -j ACCEPT追加规则-A参数将规则追加到链的末尾。# 在INPUT链末尾追加一条规则 sudo iptables -A INPUT -p tcp --dport 3306 -s 10.10.10.5 -j ACCEPT删除规则-D参数可以通过规则编号或完整规则描述来删除。# 查看带编号的规则 sudo iptables -L INPUT --line-numbers # 删除INPUT链的第2条规则 sudo iptables -D INPUT 2 # 或者通过完整匹配条件删除必须和列出时完全一致 sudo iptables -D INPUT -p tcp --dport 3306 -s 10.10.10.5 -j ACCEPT替换规则-R参数替换指定编号的规则。# 将INPUT链第1条规则替换为新的规则 sudo iptables -R INPUT 1 -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT3.4 保存与恢复规则通过命令行配置的规则是保存在内存中的重启服务器就会丢失。因此配置测试无误后必须将其保存到磁盘。# 在CentOS/RHEL 7上使用iptables-services服务保存 sudo service iptables save # 这条命令会将当前规则保存到 /etc/sysconfig/iptables 文件 # 重启iptables服务或系统后规则会自动从这个文件加载。 # 你也可以手动备份和恢复规则文件 sudo iptables-save ~/iptables-backup-$(date %Y%m%d).rules # 备份 sudo iptables-restore ~/iptables-backup-20231027.rules # 恢复实操心得在批量修改规则前先用iptables-save备份当前配置是一个好习惯。如果改乱了可以快速恢复。另外对于生产服务器建议在本地机器上也保存一份备份的规则文件。4. 高级功能与模块应用掌握了基础规则配置你已经可以应对80%的场景。接下来我们看看IPTables一些更强大的高级匹配模块它们能让你实现更精细的控制。4.1 连接状态跟踪state模块这是最重要、最常用的模块没有之一。它让IPTables具备了“状态检测”的能力能识别一个数据包是属于一个新的连接、一个已建立的连接还是一个相关的连接。NEW连接的第一个包意味着这是一个新的连接请求。ESTABLISHED一个连接已经建立后续的包都属于这个状态。RELATED一个连接是已存在连接的衍生连接。最典型的例子是FTP的数据传输连接它是由已建立的FTP控制连接触发的。INVALID无法识别或无效的数据包通常直接丢弃。为什么它如此重要因为它极大地简化了规则配置。回想一下我们之前的基础规则-m state --state ESTABLISHED,RELATED -j ACCEPT。这一条规则就允许了所有由本机主动发起的对外请求的返回流量。如果没有它你每在OUTPUT链放行一个端口比如允许本机访问外部的80端口就必须在INPUT链为对应的返回流量再写一条复杂的规则。有了状态跟踪你只需要关心“允许谁进来发起新连接”NEW状态返回通路会自动建立。4.2 多端口与IP范围匹配multiport和iprangemultiport一次性匹配多个离散的或不连续的端口最多支持15个。# 允许访问22, 80, 443端口 sudo iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT # 也可以指定一个端口范围 sudo iptables -A INPUT -p tcp -m multiport --dports 10000:20000 -j ACCEPTiprange匹配一个连续的IP地址范围。# 允许来自192.168.1.100到192.168.1.200这个IP段的SSH连接 sudo iptables -A INPUT -p tcp --dport 22 -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT4.3 连接数限制connlimit模块用于限制同一IP地址到特定服务的并发连接数可以有效防止简单的CC攻击或资源耗尽。# 限制每个IP地址到本机80端口的并发连接数不超过20个 sudo iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 -j REJECT # 限制每个IP地址到本机22端口SSH的并发连接数不超过3个防止暴力破解 sudo iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP4.4 限速limit模块基于令牌桶算法进行速率限制常用于限制ICMPping洪水或某些端口的访问频率。# 限制ICMP包ping的接收速率平均每秒1个突发峰值不超过5个 sudo iptables -A INPUT -p icmp -m limit --limit 1/sec --limit-burst 5 -j ACCEPT # 上一条规则匹配的包会被放行超过限制的包会继续匹配下一条规则因此需要一条拒绝规则 sudo iptables -A INPUT -p icmp -j DROP--limit 1/sec表示每秒生成1个令牌即平均每秒允许1个包。--limit-burst 5表示令牌桶容量为5初始时有5个令牌允许前5个包不受限制通过之后就要按每秒1个的速率消耗令牌。5. 网络地址转换NAT实战NAT是让内网设备访问公网或将内网服务发布到公网的核心技术。IPTables的nat表专门负责此事。5.1 源地址转换SNAT共享上网假设你的Linux服务器有两张网卡eth0内网卡IP192.168.1.1连接内网。eth1公网卡IP203.0.113.10连接互联网。你想让内网网段192.168.1.0/24的机器都能通过这台服务器上网。# 1. 首先必须开启Linux内核的IP转发功能 echo 1 /proc/sys/net/ipv4/ip_forward # 永久生效编辑 /etc/sysctl.conf设置 net.ipv4.ip_forward 1然后执行 sysctl -p # 2. 在nat表的POSTROUTING链上添加SNAT规则 sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to-source 203.0.113.10 # 含义将来自192.168.1.0/24网段、从eth1网卡出去的包的源IP改为203.0.113.10更常用的方式是使用MASQUERADE动态伪装它适用于公网IP不固定如PPPoE拨号的情况sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE5.2 目的地址转换DNAT端口映射/发布内网服务假设内网有一台Web服务器IP为192.168.1.100:80你想让公网用户通过访问网关的公网IP203.0.113.10的80端口来访问它。# 在nat表的PREROUTING链上添加DNAT规则 sudo iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 80 -i eth1 -j DNAT --to-destination 192.168.1.100:80 # 含义将目标地址为203.0.113.10:80、从eth1进来的TCP包转发到192.168.1.100:80 # 同时别忘了在filter表的FORWARD链上允许这条转发的路径 sudo iptables -A FORWARD -d 192.168.1.100 -p tcp --dport 80 -j ACCEPT sudo iptables -A FORWARD -s 192.168.1.100 -p tcp --sport 80 -j ACCEPT6. 日常维护、问题排查与安全加固6.1 规则管理与优化建议规则顺序是性能关键最频繁匹配的规则应该放在最前面。例如那条ESTABLISHED,RELATED的规则应该非常靠前。使用自定义链管理复杂规则当规则很多时可以创建自定义链来分类管理。sudo iptables -N WEB_SERVERS # 创建名为WEB_SERVERS的自定义链 sudo iptables -A WEB_SERVERS -s 10.1.1.0/24 -j ACCEPT sudo iptables -A WEB_SERVERS -s 10.2.2.0/24 -j ACCEPT sudo iptables -A WEB_SERVERS -j DROP # 自定义链的默认规则 # 在主链中跳转到自定义链 sudo iptables -A INPUT -p tcp --dport 80 -j WEB_SERVERS定期审查规则使用iptables-save或iptables -L -n -v --line-numbers定期查看规则清理无效或过时的条目。6.2 常见问题与排查技巧配置完规则后服务无法访问了检查顺序使用--line-numbers查看规则顺序是不是某条DROP或REJECT规则在允许规则之前匹配了。检查状态规则确保-m state --state ESTABLISHED,RELATED -j ACCEPT这条规则存在且位置靠前。检查协议和端口确认规则中的协议-p tcp/udp和端口--dport/--sport写对了。使用日志定位在怀疑被拒绝的规则前插入LOG规则。sudo iptables -I INPUT 5 -p tcp --dport 8080 -j LOG --log-prefix [IPTABLES 8080_DENIED]: 然后通过tail -f /var/log/messages或journalctl -f查看日志看数据包是否命中了这条规则。如何临时禁用所有防火墙规则# 将所有链的默认策略设回ACCEPT并清空所有规则 sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -F sudo iptables -t nat -F sudo iptables -t mangle -F注意这只是临时措施重启iptables服务或服务器后会恢复保存的规则。规则保存失败在CentOS 7上确保iptables-services包已安装且服务已启动。保存的命令是service iptables save它会写入/etc/sysconfig/iptables。也可以直接使用iptables-save /etc/sysconfig/iptables。6.3 基础安全加固示例结合以上知识一个针对Web服务器的基础加固配置思路如下#!/bin/bash # 一个简单的Web服务器防火墙初始化脚本示例 IPT/sbin/iptables # 1. 清空所有规则设置默认策略 $IPT -F $IPT -X # 删除所有自定义链 $IPT -Z # 计数器清零 $IPT -P INPUT DROP $IPT -P FORWARD DROP $IPT -P OUTPUT ACCEPT # 2. 允许本地回环 $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT # 3. 允许状态为ESTABLISHED和RELATED的包必须 $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 4. 允许ICMP按需生产环境可限制或关闭 $IPT -A INPUT -p icmp -m limit --limit 1/s --limit-burst 10 -j ACCEPT # 5. 开放必要的服务端口白名单 # SSH - 限制源IP段并防暴力破解 $IPT -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -m state --state NEW -m recent --set --name SSH $IPT -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP $IPT -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -m state --state NEW -j ACCEPT # HTTP/HTTPS $IPT -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT $IPT -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT # 6. 记录并拒绝其他所有INPUT尝试记录日志便于分析攻击 $IPT -A INPUT -j LOG --log-prefix [IPTABLES INPUT DROP]: --log-level 4 $IPT -A INPUT -j DROP # 保存规则CentOS/RHEL service iptables save echo Firewall rules applied and saved.这个脚本展示了几个关键点严格的默认拒绝策略、状态跟踪、速率限制、针对SSH的简单防暴力破解使用recent模块以及最后的日志记录。你可以根据自己服务器的实际服务端口进行增删。掌握IPTables是一个循序渐进的过程。开始时可能会被其复杂的语法和概念吓到但一旦理解了“表、链、规则”这个核心框架并亲手配置几次你就会发现它其实是一个逻辑清晰、功能强大的工具。从配置一台单机的安全策略开始慢慢尝试做网关、做NAT每一步的实践都会加深你对Linux网络栈的理解。记住在修改生产环境规则前务必在测试环境验证并且永远通过service iptables save或相应的方法保存你的劳动成果。防火墙是安全的基石值得你花时间去打磨。