Linux 防火墙实战:iptables 与 firewalld 全面解析
引言
“我的服务器怎么访问不了了?!”
相信不少运维新手都经历过这样的时刻——应用服务正常运行,端口也监听着,但浏览器就是打不开。折腾半天,最后试探性地执行了一条命令:
网页瞬间恢复访问。你顿时明白:原来是防火墙在“搞鬼”。
在 Linux 系统中,防火墙是保障网络安全的第一道防线。而说到 Linux 防火墙,绕不开两个名字:iptables 和 firewalld。它们到底是什么关系?有什么区别?日常工作中该用哪个?今天这篇文章就带你彻底搞明白。
一、Netfilter:一切防火墙的“地基”
在讲 iptables 和 firewalld 之前,有必要先认识一下 Netfilter。
Netfilter 是 Linux 内核中的一个框架,它在网络协议栈的关键路径上设置了一系列“挂载点”(钩子函数)。当数据包经过这些挂载点时,内核会依次调用挂载点上所有的钩子函数,直到数据包的处理结果被明确为接受、拒绝或丢弃。
iptables 和 firewalld 都不是真正的防火墙本身,它们只是用来定义防火墙规则的管理工具。真正执行这些规则的是内核中的 Netfilter 框架。你可以这样理解:
- Netfilter
- iptables / firewalld
明确了这一点,后面的内容就更好理解了。
二、iptables:Linux 防火墙的“元老”
2.1 核心架构:表、链、规则
iptables 采用 “表(Table)-链(Chain)-规则(Rule)” 三级结构来管理网络流量。
四表(Table) :
| |
|---|
filter | 默认表,用于数据包过滤(ACCEPT / DROP / REJECT) |
nat | 网络地址转换(SNAT / DNAT / MASQUERADE),用于端口转发或共享上网 |
mangle | 修改数据包头部(如 TTL、TOS),用于 QoS 或流量标记 |
raw | |
五链(Chain):
| |
|---|
PREROUTING | |
INPUT | |
FORWARD | |
OUTPUT | |
POSTROUTING | |
💡 规则优先级:raw > mangle > nat > filter
Iptables的4表5链:
Iptables数据包转发流程:

数据包先经过PREOUTING,由该链确定数据包走向:
- 目的地址是本地,则发送到INPUT,让INPUT决定是否接收下来送到用户空间,流程为①—>②;
- 若满足PREROUTING的nat表上的转发规则,则发送给FORWARD,然后再经过POSTROUTING发送出去,流程为:①—>③—>④—>⑥;
- 其中PREROUTING和POSTROUTING指的是数据包的流向,如上图所示POSTROUTING指的是发往服务器发出的数据包,而PREROUTING指的是来自服务器外部的数据包。
2.2 iptable命令用法
iptables的用法可以参考下图:
table:
-t 使用的表,包括filter、nat、mangle、raw,默认不指明是filter.
command:
-A 顺序添加,添加一条新规则,添加到末尾-I 插入,插入一条新规则 -I 后面加一数字表示插入到哪行-R 修改, 删除一条新规则 -D 后面加一数字表示删除哪行-D 删除,删除一条新规则 -D 后面加一数字表示删除哪行-N 新建一个链-X 删除一个自定义链,删除之前要保证次链是空的,而且没有被引用-L 查看(1.iptables -L -n 以数字的方式显示 2. iptables -L -v显示详细信息 3. iptables -L -x 显示精确信息)-E 重命名链-F 清空链中的所有规则-Z 清除链中使用的规则-P 设置默认规则
match:
隐含匹配: -p tcp udp icmp --sport指定源端口 --dport指定目标端 -s 源地址 -d 目的地址 -i 数据包进入的网卡 -o 数据包出口的网卡
扩展匹配: -m state --state 匹配状态的 -m mutiport --source-port 端口匹配 ,指定一组端口 -m limit --limit 3/minute 每三分种一次 -m limit --limit-burst 5 只匹配5个数据包 -m string --string --algo bm|kmp --string"xxxx" 匹配字符串 -mtime--timestart 8:00 --timestop 12:00 表示从哪个时间到哪个时间段 -mtime--days 表示那天 -m mac --mac-source xx:xx:xx:xx:xx:xx 匹配源MAC地址 -m layer7 --l7proto qq 表示匹配腾讯qq的 当然也支持很多协议,这个默认是没有的,需要我们给内核打补丁并重新编译内核及iptables才可以使用 -m layer7 这个显示扩展匹配
动作:
DROP 直接丢掉 ACCEPT 允许通过 REJECT 丢掉,但是回复信息-j LOG --log-prefix"说明信息,自己随便定义" ,记录日志 SNAT 源地址转换 DNAT 目标地址转换 REDIRECT 重定向 MASQUERAED 地址伪装
2.3 iptables常用命令
iptables 的命令语法虽然有一定学习曲线,但掌握核心的几个命令就足够应对日常工作了。
查看规则:
# 查看所有链的规则(默认 filter 表)iptables -L# 查看特定链的规则,带行号iptables -L INPUT -n --line-numbers# 查看 nat 表的规则iptables -t nat -L
添加规则:
# 在 INPUT 链末尾追加规则:允许 SSH(端口22)iptables -A INPUT -p tcp --dport 22 -j ACCEPT# 在 INPUT 链首位插入规则:禁止 ICMP(ping)iptables -I INPUT 1 -p icmp -j DROP# 允许来自特定 IP 的访问iptables -A INPUT -s 192.168.1.100 -j ACCEPT
删除规则:
# 按行号删除(先查看行号)iptables -D INPUT 1# 按内容删除iptables -D INPUT -p tcp --dport 80 -j ACCEPT
设置默认策略(白名单模式):
# 默认拒绝所有入站流量iptables -P INPUT DROP# 再逐条开放必要服务iptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPT
保存与恢复规则:
# 保存当前规则iptables-save > /etc/sysconfig/iptables# 恢复规则iptables-restore < /etc/sysconfig/iptables
2.3 高级应用:NAT 与端口转发
SNAT(源地址转换) :让内网主机通过防火墙访问外网:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
DNAT(目的地址转换) :将外部请求转发到内网服务器:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
2.4 连接状态跟踪:提升性能的关键
利用 conntrack 模块,可以避免对已建立的连接重复匹配规则:
# 允许已建立的连接和相关连接通过iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT# 仅允许新的 SSH 连接iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ACCEPT
这样做的好处是:一旦 SSH 连接建立成功,后续的数据包直接放行,不再逐条匹配规则,大幅提升效率。
三、firewalld:更友好的“动态管家”
3.1 设计理念:区域 + 服务
firewalld 是建立在 iptables 之上的动态防火墙管理工具,提供了更高层次的抽象。它从 RHEL/CentOS 7 开始成为默认防火墙。
firewalld 的核心优势在于 支持运行时动态修改规则,无需重启防火墙服务,不会中断现有连接。
核心概念:
| |
|---|
| 区域(Zone) | 按信任级别划分的网络环境,如 public(默认)、trusted(完全信任)、block(拒绝所有)等 |
| 服务(Service) | 预定义的端口和协议组合,如 http、ssh、mysql |
| 源地址(Source) | |
| 富规则(Rich Rule) | 支持复杂条件(IP、端口、协议、时间等)的自定义规则 |
3.2 常用命令
firewalld 的核心管理工具是 firewall-cmd。
状态与区域管理:
# 查看防火墙状态firewall-cmd --state# 查看所有可用区域firewall-cmd --get-zones# 查看默认区域firewall-cmd --get-default-zone# 查看指定区域的详情firewall-cmd --zone=public --list-all
服务与端口管理:
# 添加服务到默认区域(永久生效需加 --permanent)firewall-cmd --add-service=http --permanentfirewall-cmd --add-service=https --permanent# 开放端口firewall-cmd --add-port=3306/tcp --permanent# 重新加载配置使永久规则生效firewall-cmd --reload# 查看已开放的服务和端口firewall-cmd --list-servicesfirewall-cmd --list-ports
💡 关键区别:不加 --permanent 的修改只对当前运行生效,重启后丢失;加了 --permanent 需要执行 --reload 才能生效。
源地址控制:
# 允许特定子网访问firewall-cmd --zone=public --add-source=192.168.1.0/24 --add-service=ssh --permanent# 拒绝特定 IPfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.5" reject' --permanent
3.3 自定义服务
如果应用使用非标准端口,可以创建自定义服务文件:
<!-- /etc/firewalld/services/custom_http.xml --><?xml version="1.0" encoding="utf-8"?><service> <short>Custom HTTP</short> <description>Custom HTTP service on port 8080</description> <portprotocol="tcp"port="8080"/></service>
firewall-cmd --reloadfirewall-cmd --add-service=custom_http --permanent
3.4 富规则与端口转发
富规则支持更复杂的条件控制:
# 允许特定 IP 访问特定端口,仅在工作时间firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="8080" protocol="tcp" accept' --permanent
端口转发:
# 开启伪装(端口转发的前提)firewall-cmd --add-masquerade --permanent# 将本机 8080 端口转发到 80 端口firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80 --permanent
四、iptables vs firewalld:一张表看懂区别
| | |
|---|
| 定位 | | |
| 配置模型 | | |
| 规则更新 | | |
| 学习曲线 | | |
| 配置文件 | /etc/sysconfig/iptables | /usr/lib/firewalld/ |
| 默认策略 | | |
| 图形界面 | | |
| 后端支持 | | 可使用 iptables 或 nftables 后端 |
| 适用场景 | | |
一句话总结:iptables 是“乐高”——什么都能搭,但需要自己动手;firewalld 是“精装房”——拎包入住,省心省力。
五、实战:两个工具解决同一个需求
假设我们要完成一个常见任务:开放 Web 服务(80 和 443 端口),并允许 SSH 管理(22 端口),其余入站流量全部拒绝。
用 iptables 实现
# 1. 设置默认策略:拒绝所有入站iptables -P INPUT DROPiptables -P FORWARD DROP# 2. 允许已建立的连接iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT# 3. 开放必要端口iptables -A INPUT -p tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPT# 4. 允许本地回环iptables -A INPUT -i lo -j ACCEPT# 5. 保存规则iptables-save > /etc/sysconfig/iptables
用 firewalld 实现
# 1. 确保默认区域是 public(默认拒绝入站)firewall-cmd --get-default-zone # 应该是 public# 2. 添加服务firewall-cmd --add-service=ssh --permanentfirewall-cmd --add-service=http --permanentfirewall-cmd --add-service=https --permanent# 3. 重新加载生效firewall-cmd --reload# 4. 验证firewall-cmd --list-services
对比一下,firewalld 只需要 4 条命令,而 iptables 需要 6 条命令加一个保存操作。对于日常运维场景,firewalld 的简洁性显而易见。
六、常见问题与排错指南
Q1:firewalld 和 iptables 能同时用吗?
不建议同时启用。两者都操作同一套 netfilter 规则,同时启用可能导致规则冲突。如果启用了 firewalld,建议禁用 iptables 服务:
systemctl stop iptablessystemctl disable iptablessystemctl enable --now firewalld
Q2:修改了 firewalld 规则为什么不生效?
检查两个地方:
- 是否加了
--permanent 但没有执行 --reload
Q3:iptables 规则重启后消失了?
iptables 规则默认是临时的,需要手动保存:
# CentOS/RHELservice iptables save# 通用方法iptables-save > /etc/sysconfig/iptables
Q4:服务启动失败,怎么排查?
服务启动失败可以参考如下步骤排查:
# 1. 查看防火墙状态systemctl status firewalldfirewall-cmd --state# 2. 查看当前规则firewall-cmd --list-alliptables -L -n -v# 3. 临时关闭防火墙测试(仅用于排查)systemctl stop firewalld# 如果关闭后服务正常,说明是防火墙规则问题# 4. 查看selinux状态getenforce
Q5:找不到iptables服务,报错Unit iptables.service could not be found.
Centos 7以后默认没有安装iptables服务,需要通过yum install -y iptables-services之后就可以通过systemctl管理iptables服务了
七、iptables和firewalld到底应该选哪一个?
什么时候用 firewalld?
- 大多数现代 Linux 系统(CentOS 7+、RHEL、Fedora)
什么时候用 iptables?
📌 一句话建议:对于绝大多数新建 Linux 服务器,优先使用 firewalld;只有在 firewalld 无法满足的复杂场景下,才考虑降级到 iptables。对于一些较老的服务器iptables用得较多,一些比较资深的运维人员也比较习惯使用iptables作为linux的防火墙。
总结
从 iptables 到 firewalld,Linux 防火墙管理走过了一条从“底层精细”到“高层易用”的演进之路。两者都基于 Netfilter 框架,但设计理念截然不同:
- iptables 是“工匠型”工具——强大、灵活,但需要你亲手搭建每一块砖。
- firewalld
记住三句话:
- Netfilter 是内核的执行引擎,iptables 和 firewalld 只是管理工具
- 默认策略决定安全基调:iptables 默认允许,firewalld 默认拒绝——理解这一点,很多问题迎刃而解。
- 生产环境优先用 firewalld
防火墙是服务器的“守门人”,配置得当能挡住绝大部分恶意流量,配置失误也可能把自己挡在门外。希望这篇文章能帮你建立起清晰的防火墙管理思路,下次再遇到“服务访问不了”的问题,能快速定位是防火墙在“搞鬼”,还是真的程序出了 bug。
如果你有任何问题或经验分享,欢迎在评论区留言讨论!