【Linux从入门到精通】第31篇:防火墙漫谈——iptables与firewalld防护指南
目录
一、引言:你的服务器正在被扫描
二、iptables核心概念:四表五链
2.1 理解“表”和“链”
2.2 四表:规则的功能分类
2.3 五链:规则执行的时机
2.4 一个具体的数据包流转示例
三、firewalld:iptables的现代化封装
3.1 为什么要引入firewalld?
3.2 核心概念:区域(Zone)
3.3 临时规则 vs 永久规则
四、firewall-cmd实战操作
4.1 基础服务管理
4.2 端口管理
4.3 富规则(Rich Rule):精确访问控制
4.4 查看与删除规则
4.5 完整配置示例
五、紧急情况下的“拔网线”
六、iptables vs firewalld:如何选择?
七、本篇小结
动手练习
八、下篇预告
一、引言:你的服务器正在被扫描
在第19篇配置SSH密钥登录时,我们提到过:刚买来的云服务器,几分钟内就会收到来自全球的暴力破解尝试。
这些攻击之所以能到达你的服务器,是因为默认情况下,你开放了SSH端口。如果防火墙没有正确配置,攻击者可以不断尝试登录。
防火墙的作用就是:在服务器和外部网络之间设置一道“围墙”,只放行你允许的流量,拒绝所有未经授权的访问。
Linux系统中最主流的防火墙工具有两个:
iptables:经典工具,直接操作内核规则,功能强大但稍显复杂
firewalld:iptables的现代封装,引入区域(zone)概念,动态管理更友好
它们的底层都基于Linux内核的netfilter框架,只是管理方式不同。
二、iptables核心概念:四表五链
2.1 理解“表”和“链”
iptables用表(table)和链(chain)两个维度来组织规则:
表:按功能的分类。决定了规则能做什么(过滤?地址转换?修改数据包?)
链:按时机分类。决定了规则在数据包经过的哪个环节生效
可以这样类比:
表就像不同的职能部门(财务部、安保部、运输部)
链就像进出大楼的检查点(大门口、走廊、电梯口)
数据包就是在大楼中穿行的人,在每个检查点都可能被某个部门拦截处理
2.2 四表:规则的功能分类
| 表名 | 功能 | 优先级 | 典型场景 |
|---|---|---|---|
| raw | 控制连接追踪,可跳过状态跟踪 | 最高 | 高并发服务器、DDoS防护 |
| mangle | 修改数据包标记(TTL、TOS等) | 第二 | 流量整形、QoS控制 |
| nat | 网络地址转换(SNAT/DNAT) | 第三 | 端口映射、内网上外网 |
| filter | 数据包过滤(放行/拒绝) | 最低 | 最常用,端口访问控制 |
记忆技巧:优先级从高到低——raw → mangle → nat → filter。filter优先级最低但使用频率最高。
其中filter表是默认表,如果不指定-t参数,iptables命令操作的就是filter表。日常的端口放行、IP黑名单都在这个表中配置。
2.3 五链:规则执行的时机
数据包进入服务器后,会按固定路径经过这些“检查点”:
text
外网数据包 ↓ PREROUTING ← 路由决策前的检查(DNAT在这里做) ↓ [路由决策:这个包是给我的,还是需要转发的?] ↓ ↓ 给我 转发给别人 ↓ ↓ INPUT FORWARD ↓ ↓ 本机应用 转发处理 ↓ ↓ OUTPUT [继续转发] ↓ ↓ POSTROUTING ← 离开本机前的最后检查(SNAT在这里做) ↓ 离开服务器
简单记忆:
PREROUTING:进门安检(所有入站包先经过这里)
INPUT:进自己房间(目标是本机)
FORWARD:穿堂而过(本机做路由器时)
OUTPUT:从房间出去(本机发出的包)
POSTROUTING:出门检票(所有出站包最后经过这里)
2.4 一个具体的数据包流转示例
假设外网用户访问你服务器的80端口(Nginx):
数据包到达网卡 → 进入PREROUTING链(可以做DNAT修改目标地址)
内核判断:目标是本机 → 进入INPUT链
filter表在INPUT链的规则被匹配:允许80端口 → 放行
数据包交给Nginx处理
Nginx返回响应 → 进入OUTPUT链
响应包经过POSTROUTING链 → 离开网卡
三、firewalld:iptables的现代化封装
3.1 为什么要引入firewalld?
iptables虽然强大,但有几个痛点:
规则修改是一次性整体替换,修改一条规则需要重新加载全部配置
没有持久化机制,重启后规则丢失(需要
iptables-save手动保存)语法较复杂,新手容易写出有安全漏洞的规则
firewalld就是为了解决这些问题而设计的:
动态管理:修改规则立即生效,不影响现有连接
区域(Zone)概念:为不同网络环境预设信任级别
服务(Service)抽象:可以直接放行
http而不需要记端口号
3.2 核心概念:区域(Zone)
firewalld用“区域”来表示网络的信任级别:
| 区域 | 信任级别 | 默认行为 | 适用场景 |
|---|---|---|---|
trusted | 最高 | 接受所有连接 | 完全可信任的内网 |
home | 较高 | 接受选定连接 | 家庭网络 |
work | 较高 | 接受选定连接 | 公司办公网络 |
internal | 中等 | 接受选定连接 | 内部网络 |
public | 默认 | 拒绝入站连接 | 公共网络(服务器默认用这个) |
dmz | 较低 | 拒绝入站连接 | 隔离区服务器 |
block | 极低 | 拒绝所有(回复ICMP) | 问题IP临时封锁 |
drop | 最低 | 丢弃所有(不回复) | 最高安全级别 |
查看当前使用的区域:
bash
firewall-cmd --get-default-zone # 通常输出 public
重要认知:云服务器默认使用
public区域,这个区域默认拒绝所有入站连接,只允许你明确放行的服务或端口。
3.3 临时规则 vs 永久规则
firewalld区分两种规则:
| 类型 | 特点 | 生效时机 | 重启后 |
|---|---|---|---|
临时规则(无--permanent) | 立即生效 | 立即可用 | 丢失 |
永久规则(有--permanent) | 写入配置文件 | --reload后生效 | 保留 |
最佳实践:先用临时规则测试,确认无误后再加--permanent保存。
四、firewall-cmd实战操作
4.1 基础服务管理
bash
# 查看当前区域的所有规则 firewall-cmd --list-all # 允许HTTP服务(自动放行80端口) sudo firewall-cmd --permanent --add-service=http # 允许HTTPS服务(自动放行443端口) sudo firewall-cmd --permanent --add-service=https # 查看已允许的服务 firewall-cmd --list-services # 移除服务 sudo firewall-cmd --permanent --remove-service=http # 重载配置(让永久规则生效) sudo firewall-cmd --reload
4.2 端口管理
bash
# 开放指定端口 sudo firewall-cmd --permanent --add-port=8080/tcp # 开放端口范围 sudo firewall-cmd --permanent --add-port=3000-3100/tcp # 查看已开放的端口 firewall-cmd --list-ports # 关闭端口 sudo firewall-cmd --permanent --remove-port=8080/tcp # 重载 sudo firewall-cmd --reload
4.3 富规则(Rich Rule):精确访问控制
普通的--add-port会让所有人都能访问该端口。如果需要限制访问来源(如只允许特定IP访问SSH),就需要富规则。
bash
# 只允许 192.168.1.100 访问SSH(22端口) sudo firewall-cmd --permanent --add-rich-rule=' rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept' # 拒绝某个IP访问所有服务 sudo firewall-cmd --permanent --add-rich-rule=' rule family="ipv4" source address="203.0.113.50" reject' # 允许某个网段访问特定端口 sudo firewall-cmd --permanent --add-rich-rule=' rule family="ipv4" source address="10.0.0.0/24" port protocol="tcp" port="3306" accept' sudo firewall-cmd --reload
富规则格式解读:
rule family="ipv4":规则作用于IPv4source address="IP":限制来源IPport protocol="tcp" port="端口":限制协议和端口accept / reject / drop:动作
4.4 查看与删除规则
bash
# 查看所有富规则 firewall-cmd --list-rich-rules # 删除富规则(需要完全匹配规则内容) sudo firewall-cmd --permanent --remove-rich-rule=' rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept' sudo firewall-cmd --reload
4.5 完整配置示例
以下是一个Web服务器的标准防火墙配置:
bash
# 1. 确认firewalld正在运行 sudo systemctl status firewalld # 2. 查看默认区域 firewall-cmd --get-default-zone # 通常为 public # 3. 开放HTTP和HTTPS(所有IP可访问) sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https # 4. SSH只允许公司IP访问(富规则) sudo firewall-cmd --permanent --add-rich-rule=' rule family="ipv4" source address="203.0.113.0/24" port protocol="tcp" port="22" accept' # 5. 移除SSH的通用开放(如果之前开放过) sudo firewall-cmd --permanent --remove-service=ssh # 6. 应用所有配置 sudo firewall-cmd --reload # 7. 验证配置 firewall-cmd --list-all
五、紧急情况下的“拔网线”
如果服务器正在遭受DDoS攻击或发现被入侵,你需要立即切断所有网络流量,给自己留出排查时间。这就是firewalld的panic模式。
bash
# 紧急断网(阻断所有入站和出站流量,仅保留已有连接) sudo firewall-cmd --panic-on # 检查是否处于panic模式 firewall-cmd --query-panic # 恢复正常(规则恢复为panic-on之前的状态) sudo firewall-cmd --panic-off
什么时候使用?
发现服务器被DDoS攻击,流量异常
检测到可疑的网络行为(如未知进程在往外传数据)
正在进行安全事件应急响应,需要隔离服务器
⚠️注意:panic模式会阻断所有网络流量。如果你是SSH远程连接的,执行
panic-on后你的SSH连接也会断开!所以这个操作通常需要在有带外管理(如VNC控制台)的情况下使用。
六、iptables vs firewalld:如何选择?
| 对比维度 | iptables | firewalld |
|---|---|---|
| 出现年代 | Linux 2.4(2001年) | RHEL/CentOS 7(2014年) |
| 规则修改 | 整体替换,可能中断连接 | 动态修改,不影响现有连接 |
| 持久化 | 需手动iptables-save | --permanent自动保存 |
| 易用性 | 语法复杂,需要理解表链 | Zone+Service抽象,更直观 |
| 底层 | 直接操作内核netfilter | 封装iptables或nftables |
选择建议:
| 场景 | 推荐 |
|---|---|
| 新系统、初学防火墙 | firewalld |
| 日常端口管理 | firewalld |
| 复杂NAT规则、特殊协议 | iptables |
| 老系统(CentOS 6) | iptables |
| Docker/K8s环境 | 直接用iptables(Docker自动管理) |
核心原则:不要同时运行iptables和firewalld,否则规则会互相冲突。如果你在用CentOS 7+、RHEL 7+或Fedora,直接使用firewalld即可。
七、本篇小结
iptables核心:
四表:raw(连接追踪)→ mangle(数据包修改)→ nat(地址转换)→ filter(过滤,最常用)
五链:PREROUTING → INPUT/FORWARD → OUTPUT → POSTROUTING
数据包按表优先级和链顺序依次匹配规则
firewalld核心命令:
| 操作 | 命令 |
|---|---|
| 开放服务 | firewall-cmd --permanent --add-service=http |
| 开放端口 | firewall-cmd --permanent --add-port=8080/tcp |
| IP限制访问 | firewall-cmd --permanent --add-rich-rule='...' |
| 查看规则 | firewall-cmd --list-all |
| 重载配置 | firewall-cmd --reload |
| 紧急断网 | firewall-cmd --panic-on |
| 恢复网络 | firewall-cmd --panic-off |
关键原则:
最小权限:只开放必要的端口,能用富规则限制来源IP就不全局开放
先测试后保存:临时规则确认无误后,再加
--permanent永远留后路:修改防火墙前确保有回滚方式(云服务器至少保留VNC控制台通道)
动手练习
bash
# 1. 检查防火墙状态 sudo systemctl status firewalld firewall-cmd --state # 2. 查看当前所有规则 firewall-cmd --list-all # 3. 临时开放一个测试端口 sudo firewall-cmd --add-port=8888/tcp firewall-cmd --list-ports # 4. 移除并确认(不加--permanent,重启消失) sudo firewall-cmd --remove-port=8888/tcp # 5. 练习富规则(仅允许本机IP访问22端口——测试用,确认前不要加--permanent) # firewall-cmd --add-rich-rule='rule family="ipv4" source address="你的IP" port port="22" protocol="tcp" accept' # firewall-cmd --list-rich-rules # firewall-cmd --remove-rich-rule='...' # 用同样的规则内容移除
八、下篇预告
防火墙保护了端口,但真正处理请求的是Web服务器。下一篇我们将进入Nginx入门——高性能Web服务器搭建,学习如何安装Nginx、配置虚拟主机、理解反向代理的概念,以及那个运维最常用的命令——nginx -s reload的平滑重启原理。
延伸思考:为什么firewalld的public区域默认拒绝入站连接?这是安全上的“默认拒绝”原则——凡是没明确允许的,一律禁止。就像一栋大楼,默认所有门都锁着,只有你需要用的房间才配钥匙。这个原则也是纵深防御体系的基础。
