Linux 防火墙全攻略
Linux 防火墙全攻略
从 iptables 到 firewalld 再到 nftables,Linux 防火墙到底经历了什么?这篇文章用讲故事的方式,帮你把 Linux 防火墙的"三生三世"理清楚。
前言:防火墙到底是干啥的?
想象你的服务器是一栋写字楼:
-
大门(网口)朝外开,谁都能走到门口
-
你需要一个保安(防火墙)坐在门口,检查每个人的通行证
-
保安手里有张规则表:哪些人让进、哪些人赶走、哪些人带去特定房间
Linux 防火墙就是那个保安。它决定了:
-
谁能进来(INPUT)
-
谁能经过(FORWARD)
-
谁能出去(OUTPUT)
一、时间同步(背景知识)
在讲防火墙之前,笔记开头有一段 chrony 时间同步。为啥要提这个?
因为防火墙策略依赖时间。比如你设置"凌晨1点到4点禁止访问",如果服务器时间不准,规则就会乱套。
chronyc sources -v # 看时间同没同步上 timedatectl # 看当前时区时间
放在这里是因为:搞安全之前,先把时间调准。 时间都不对,日志排查更是灾难。
二、iptables:Linux 防火墙的"老炮儿"
2.1 它是咋工作的?
iptables 只是用户空间的配置工具,真正干活的是内核里的 netfilter。
关系是这样的:
你在终端敲 iptables 命令 ↓ iptables(用户空间工具)把规则传给内核 ↓ netfilter(内核空间引擎)在数据包经过时检查规则 ↓ 匹配到规则 → 按规则处理(放行/丢弃/记录...)
类比:iptables 是保安队长手里的对讲机,netfilter 是保安本人。你对对讲机喊"拦住那个人",保安就动手。
2.2 五表五链 — 保安的"工位图"
五张表(不同职责)
| 表 | 职责 | 类比 |
|---|---|---|
| filter | 包过滤(放行/拒绝) | 保安的核心工作——放人还是拦人 |
| nat | 地址转换(SNAT/DNAT) | 前台改电话号码——打进来的转接,打出去的伪装 |
| mangle | 修改包头部(TOS/TTL) | 给快递包裹改标签 |
| raw | 连接跟踪(NOTRACK) | "这个包裹不用登记" |
| security | SELinux 安全上下文 | 特殊安检通道 |
优先级(从上往下,数字越小优先级越高):
raw → mangle → nat → filter → security
五条链(数据包经过的检查点)
数据包每经过一个位置,保安就要查一次规则:
┌──────────────┐ 进来 ──→ PREROUTING ──→ INPUT ──→ [本机进程] │ ↑ ↓ │ FORWARD ──→ POSTROUTING ──→ 出去 ↑ [本机进程] ──→ OUTPUT
三个场景对应三条路径:
| 场景 | 数据包路径 |
|---|---|
| 访问本机(如 SSH 登录) | PREROUTING → INPUT → 本机进程 |
| 本机访问外部(如 curl) | 本机进程 → OUTPUT → POSTROUTING |
| 路由转发(NAT 网关) | PREROUTING → FORWARD → POSTROUTING |
表和链的"授权关系"
不是每个链都能查每张表。就像不是每个工位都有权做所有事:
| 表 \ 链 | PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING |
|---|---|---|---|---|---|
| raw | ✅ | ✅ | |||
| mangle | ✅ | ✅ | ✅ | ✅ | ✅ |
| nat | ✅ | ✅ | ✅ | ||
| filter | ✅ | ✅ | ✅ | ||
| security | ✅ | ✅ | ✅ |
常用组合就记住两个:
filter 表 + INPUT/FORWARD/OUTPUT 链 → 放行/拒绝
nat 表 + PREROUTING/POSTROUTING 链 → 地址转换
2.3 iptables 命令:保安的"标准话术"
iptables -t 表名 -操作 链名 [匹配条件] -j 处理动作
常用操作:
| 操作 | 含义 | 类比 |
|---|---|---|
-A | 追加到链尾 | "名单最后加一条" |
-I 2 | 插入到第2行 | "插队到第二位" |
-D 3 | 删除第3条 | "把第三条撕掉" |
-F | 清空所有规则 | "把名单全部擦掉" |
-L -n -v --line-numbers | 列出规则(带行号) | "把名单念一遍,带编号" |
-P INPUT DROP | 修改默认策略 | "以后不认识的一律不让进" |
匹配条件(怎么说清楚"拦谁"):
# 通用匹配 — 基础信息 -s 10.0.0.1 # 从哪个IP来的 -d 192.168.1.100 # 要去哪个IP -p tcp # 用什么协议 -i eth0 # 从哪个网口进来的 -o eth1 # 从哪个网口出去的 ! -s 10.0.0.12 # 除了10.0.0.12以外的(取反) # 扩展匹配 — 需要 -m 模块 -m multiport --dports 22,80,443 # 多个端口一起写 -m state --state NEW,ESTABLISHED # 连接状态 -m connlimit --connlimit-above 10 # 连接数超过10 -m limit --limit 10/second # 速率限制 -m time --timestart 01:00 --timestop 04:00 # 时间段
处理动作(怎么处置):
| 动作 | 效果 | 类比 |
|---|---|---|
ACCEPT | 放行 | "证件齐全,请进" |
DROP | 丢弃,无回应 | 保安装瞎,看都不看你 |
REJECT | 拒绝,有回应 | 保安告诉你"这里不准进" |
LOG | 记录日志,继续匹配 | 保安看了一眼,本子上记一笔,然后放你走 |
SNAT | 改源地址 | 给你换张假身份证再放出去 |
DNAT | 改目标地址 | 前台帮你转接到另一个办公室 |
MASQUERADE | 动态 SNAT | IP 不固定时的 SNAT(像手机号经常换) |
REDIRECT | 端口重定向 | 你找 80 号房间,前台让你去 8080 |
2.4 常用规则实战(跟着敲一遍)
场景一:保护本机
# ① 先放行自己和自己人(顺序很重要!) iptables -A INPUT -i lo -j ACCEPT # 本机环回 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 已经连上的 # ② 放行特定服务 iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT # Web # ③ 内网全放行 iptables -A INPUT -s 10.0.0.0/24 -j ACCEPT # ④ 其他全部拒绝 iptables -P INPUT DROP
⚠️ 注意顺序:iptables 是从上到下逐条匹配的,先匹配到了就执行,不继续往下走。所以先放行再拒绝。
场景二:限流防攻击
# 防 SSH 暴力破解 — 每分钟最多3次新连接 iptables -A INPUT -p tcp --dport 22 -m state --state NEW \ -m limit --limit 3/minute -j ACCEPT # 防 ping flood — 每秒最多5次 iptables -A INPUT -p icmp --icmp-type 8 \ -m limit --limit 5/second -j ACCEPT # 防 CC 攻击 — 同一IP最多10个并发连接 iptables -A INPUT -p tcp --dport 80 \ -m connlimit --connlimit-above 10 -j REJECT
场景三:禁止特定IP
# 拒绝一个IP iptables -A INPUT -s 10.0.0.12 -j DROP # 拒绝一个网段但放行其中一台(注意顺序!) iptables -A INPUT -s 10.0.0.1 -j ACCEPT # 先放行 iptables -A INPUT -s 10.0.0.0/24 -j DROP # 后拒绝
DROP vs REJECT:DROP 是"装死"——对方等超时;REJECT 是"礼貌拒绝"——直接告诉对方端口不可达。SSH 暴力破解建议 DROP,让攻击者慢慢等。
2.5 规则保存(不保存 = 白干)
iptables 规则存在内存里,重启就没了。一定要保存!
# Rocky/CentOS yum install iptables-services systemctl enable --now iptables iptables-save > /etc/sysconfig/iptables # Ubuntu iptables-save > /etc/iptables/rules.v4
三、NAT:地址转换——"瞒天过海"的艺术
3.1 为啥需要 NAT?
你家路由器只有一个公网 IP,但你全家手机电脑都在上网。NAT 就是干这个的——让一堆私网 IP 共享一个公网 IP 上网。
你的电脑(10.0.0.2) → 路由器(192.168.8.13) → 互联网
↑ SNAT 把源地址从10.0.0.2改成192.168.8.13
3.2 SNAT — 出门换身份证
场景:内网机器访问外网。出去的时候,把源地址从内网 IP 改成公网 IP。
# 固定公网 IP iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 \ -j SNAT --to-source 192.168.8.13 # 动态 IP(ADSL/4G)— 用 MASQUERADE iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 \ -j MASQUERADE
SNAT vs MASQUERADE:
-
SNAT:公网 IP 固定时用,性能更好
-
MASQUERADE:公网 IP 不固定时用(每次拔号都会变),每次发包会自动获取当前出口 IP
3.3 DNAT — 前台转接电话
场景:外网用户访问你网关的 80 端口,你要把流量转到内网的一台 Web 服务器。
# 端口映射:访问网关80 → 转到内网服务器80 iptables -t nat -A PREROUTING -d 10.0.0.13 -p tcp --dport 80 \ -j DNAT --to-destination 192.168.8.14:80 # 端口转换:访问网关8080 → 转到内网服务器80 iptables -t nat -A PREROUTING -d 10.0.0.13 -p tcp --dport 8080 \ -j DNAT --to-destination 192.168.8.14:80 # SSH 映射:访问网关2222 → 转到内网服务器22 iptables -t nat -A PREROUTING -d 10.0.0.13 -p tcp --dport 2222 \ -j DNAT --to-destination 192.168.8.14:22
3.4 NAT 必需的"开关"
做 NAT 的机器必须开启 IP 转发,否则内核不会转发数据包:
# 临时 sysctl -w net.ipv4.ip_forward=1 # 永久 echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -p
为什么? 默认情况下,Linux 内核只处理"目标地址是本机"的包,其他包直接丢弃。IP 转发就是告诉内核:"你不是目的地也能接,帮忙传一下。"
四、FORWARD 链:网关的"过路安检"
如果你把一台 Linux 机器配成路由器/NAT 网关,那除了 SNAT/DNAT 之外,还得管好 FORWARD 链——经过这台机器的流量要怎么过滤。
# 允许已建立的连接回来 iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许内网访问外网 iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT # 默认拒绝转发 iptables -P FORWARD DROP
类比:你家小区门口有个保安。 INPUT 是管"进小区",FORWARD 是管"穿小区而过的人"——保安也得管他们。
五、firewalld:iptables 的"友好包装版"
RHEL/CentOS/Rocky 默认用 firewalld,它不是另一个防火墙,而是 iptables/nftables 的前端管理工具。
核心概念:区域(Zone)
区域就是把不同信任级别的网络分到不同"安全区",每个区有自己的规则。
trusted(自家人)→ internal(内网)→ public(公共)→ drop(扔了) (越来越严格)
# 基础操作 firewall-cmd --state # 防火墙开着吗? firewall-cmd --list-all # 当前区域规则有哪些? firewall-cmd --get-default-zone # 当前默认是哪个区? firewall-cmd --set-default-zone=public # 改默认区 # 开放服务/端口 firewall-cmd --add-service=http --permanent # 放行 HTTP 服务 firewall-cmd --add-port=8080/tcp --permanent # 放行 8080 端口 firewall-cmd --remove-port=80/tcp --permanent # 关闭 80 端口 # 别忘了重载 firewall-cmd --reload # 富规则(更细粒度的控制) firewall-cmd --add-rich-rule='rule family=ipv4 source address=10.0.0.13/32 reject'
--permanent这个参数很坑——不加它,规则立即生效但重启后消失;加了它,规则需要 reload 才生效。建议先不加测试,确认没问题再加--permanent然后 reload。
六、nftables:iptables 的"接班人"
6.1 为啥要有 nftables?
iptables 的问题:
-
慢:规则多了(500+)性能明显下降
-
乱:IPv4 和 IPv6 两套命令
-
复杂:五表五链记到头晕
nftables 把这一切统一了:
| 对比 | iptables | nftables |
|---|---|---|
| 语法 | 多命令、多参数 | 统一语法,像编程 |
| 协议 | IPv4/IPv6 分开管 | inet 一把抓 |
| 性能 | 500条开始卡 | 万级规则稳如狗 |
| 配置 | iptables-save/restore | nft list/flush ruleset |
6.2 nftables 实操
# 查看所有规则
nft list ruleset
# 清空规则(慎用,会断开连接)
nft flush ruleset
# 创建表(inet = IPv4 + IPv6 统一处理)
nft add table inet myfw
# 创建链(指定 hook 点和优先级)
nft add chain inet myfw input '{ type filter hook input priority 0 ; policy accept ; }'
# 添加规则(和 iptables 语法不一样,更像自然语言)
nft add rule inet myfw input ip saddr 10.0.0.12 drop
nft add rule inet myfw input tcp dport 22 accept
# 查看规则(加 -a 显示 handle ID,删除时要用)
nft -a list chain inet myfw input
# 删除规则(通过 handle ID)
nft delete rule inet myfw input handle 11
# 插入/替换规则
nft insert rule inet myfw input ip saddr 10.0.0.12 drop
nft replace rule inet myfw input handle 12 ip saddr 10.0.0.100 drop
# 备份恢复
nft list ruleset > backup.nft
nft -f backup.nft
nftables 语法特点:从左到右读,像在说一句话:
nft add rule inet myfw input tcp dport 22 accept → 在 inet 族、myfw 表、input 链上加一条规则: 如果 TCP 目标端口是 22,就接受
6.3 协议簇
| 簇 | 管什么 |
|---|---|
inet | IPv4 + IPv6(推荐,95%场景用这个) |
ip | 仅 IPv4 |
ip6 | 仅 IPv6 |
arp | ARP 协议 |
bridge | 桥接(Docker 网络场景) |
netdev | 网卡入口层(ingress) |
七、日常排查四件套
最后给你一个防火墙健康检查清单,每天早上巡检用:
# 1. 当前有什么规则? iptables -vnL --line-numbers # 2. 完整规则集长啥样? iptables-save # 3. 时间同步上了吗? chronyc sources -v # 4. 时区对了吗? timedatectl
最常用的安全基线配置:
# 防火墙规则三板斧 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 已连的放行 iptables -A INPUT -s 10.0.0.0/24 -j ACCEPT # 内网放行 iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH放行 iptables -P INPUT DROP # 其他拒绝
总结:三代防火墙怎么选?
| 你是谁 | 用啥 |
|---|---|
| CentOS/RHEL 7+ 用户 | 系统自带 firewalld(底层是 iptables 或 nftables) |
| 想学最广泛的 | iptables — 所有 Linux 发行版都支持,文档最多 |
| 拥抱未来的 | nftables — 性能更好,语法更现代 |
| Ubuntu 用户 | 默认 ufw(底层也是 iptables) |
学习路径建议:
-
先学 iptables 的核心概念(五表五链、路径图)
-
理解 SNAT/DNAT 的原理(实战最常用)
-
用 firewalld 日常管理(省心)
-
有余力再看 nftables(以后是趋势)
一句话收尾:iptables 教你原理,firewalld 给你便利,nftables 给你未来。 看懂这篇,防火墙这块就稳了。
更多推荐



所有评论(0)