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)"这个包裹不用登记"
securitySELinux 安全上下文特殊安检通道

优先级(从上往下,数字越小优先级越高):

raw → mangle → nat → filter → security
五条链(数据包经过的检查点)

数据包每经过一个位置,保安就要查一次规则:

                    ┌──────────────┐
    进来 ──→ PREROUTING ──→ INPUT ──→ [本机进程]
                    │                ↑
                    ↓                │
                 FORWARD ──→ POSTROUTING ──→ 出去
                                  ↑
                    [本机进程] ──→ OUTPUT

三个场景对应三条路径:

场景数据包路径
访问本机(如 SSH 登录)PREROUTING → INPUT → 本机进程
本机访问外部(如 curl)本机进程 → OUTPUT → POSTROUTING
路由转发(NAT 网关)PREROUTING → FORWARD → POSTROUTING
表和链的"授权关系"

不是每个链都能查每张表。就像不是每个工位都有权做所有事:

表 \ 链PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING
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动态 SNATIP 不固定时的 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 把这一切统一了:

对比iptablesnftables
语法多命令、多参数统一语法,像编程
协议IPv4/IPv6 分开管inet 一把抓
性能500条开始卡万级规则稳如狗
配置iptables-save/restorenft 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 协议簇

管什么
inetIPv4 + IPv6(推荐,95%场景用这个)
ip仅 IPv4
ip6仅 IPv6
arpARP 协议
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)

学习路径建议:

  1. 先学 iptables 的核心概念(五表五链、路径图)

  2. 理解 SNAT/DNAT 的原理(实战最常用)

  3. firewalld 日常管理(省心)

  4. 有余力再看 nftables(以后是趋势)

一句话收尾:iptables 教你原理,firewalld 给你便利,nftables 给你未来。 看懂这篇,防火墙这块就稳了。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐