开放一个端口、封禁一个 IP、只允许内网访问数据库——这些需求和防火墙打交道。Linux 防火墙工具层层叠叠:iptables、firewalld、nftables、ufw,新手容易懵:到底用哪个?它们谁管谁?这一篇把四代防火墙的关系理清,重点讲透 iptables 的表/链/规则模型,再给出 firewalld 和 ufw 的实战配置,最后深入 Netfilter 原理。

Linux 防火墙配置教程:iptables、firewalld、nfta����ώՙ�
图片素材来自免费商用图库(pixabay,摄影师 Mariakray),非本站项目实拍。

一、四代防火墙的关系

先画一张家谱,避免混乱:

内核层:Netfilter(包过滤框架,所有工具最终都调用它)
   ↑
   ├─ iptables(老牌命令行工具,直接操作 Netfilter 规则)
   ├─ nftables(新一代,取代 iptables,内核 3.13+)
   ├─ firewalld(CentOS/RHEL 的守护进程,底层用 nftables/iptables,用「区域」抽象)
   └─ ufw(Ubuntu 的简易前端,底层调 iptables)
工具 定位 系统
Netfilter 内核框架 所有
iptables 直接操作规则 通用
nftables iptables 的替代品 新内核
firewalld 动态管理 + 区域抽象 RHEL/CentOS/Rocky
ufw 简易前端 Ubuntu/Debian

选择建议:Ubuntu 用 ufw 最省事;RHEL/CentOS/Rocky 用 firewalld;需要精细控制用 iptables/nftables。它们不要同时用,否则规则互相打架。

二、iptables 基础:表、链、规则

iptables 的模型是「表 → 链 → 规则」,理解了这层结构,一切就顺了。

四张表(按用途分)

表 用途
filter 默认表,过滤包(放行/拒绝)
nat 网络地址转换(端口转发、SNAT/DNAT)
mangle 修改包内容(TOS、TTL 等)
raw 连接跟踪前处理

日常 90% 都在 filter 表操作,默认就是它。

五条链(按包处理的时机)

链 触发时机
INPUT 进入本机的包
OUTPUT 本机发出的包
FORWARD 经过本机转发的包
PREROUTING 路由决策前(nat 常用)
POSTROUTING 路由决策后(nat 常用)

filter 表里有 INPUT、OUTPUT、FORWARD 三条链,这是最常打交道的。

查看规则

sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT)
num  target  prot  opt  source       destination
1    ACCEPT  tcp   --   0.0.0.0/0    0.0.0.0/0    tcp dpt:22
2    DROP    all   --   10.0.0.99    0.0.0.0/0
  • -L 列出,-n 不解析(显示数字),-v 详细,--line-numbers 显示行号

规则的基本操作

# 追加规则(加到末尾)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# 插入到第 1 条(最前面)
sudo iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT

# 删除第 3 条规则
sudo iptables -D INPUT 3

# 清空所有规则
sudo iptables -F

# 设置默认策略(先放行,再改 DROP,别锁死自己)
sudo iptables -P INPUT DROP

参数速查

参数 含义
-A/-I/-D 追加/插入/删除
-p 协议(tcp/udp/icmp)
--dport / --sport 目标/源端口
-s / -d 源/目标 IP
-i / -o 入/出网卡
-j 动作(ACCEPT/DROP/REJECT)
-m state --state 连接状态匹配

-j 的动作区别

动作 行为
ACCEPT 放行
DROP 丢弃(不回应,对方超时)
REJECT 拒绝(回一个拒绝包,对方秒知)
LOG 记录日志后继续匹配

DROP vs REJECT:DROP 静默丢弃,对方要等到超时;REJECT 主动拒绝,对方立即收到错误。安全上倾向 DROP(不暴露信息),体验上 REJECT 更快。

三、iptables 常用规则

放行 SSH、HTTP、HTTPS

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

放行已建立的连接(关键)

sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

这条必须加,否则出站的响应包进不来,会导致「能发不能收」。

只允许内网访问数据库

sudo iptables -A INPUT -p tcp --dport 3306 -s 10.0.0.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP

只允许特定 IP 访问 SSH

sudo iptables -A INPUT -p tcp --dport 22 -s 203.0.113.5 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP

封禁某 IP

sudo iptables -A INPUT -s 10.0.0.99 -j DROP

允许本机回环和 ICMP

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -p icmp -j ACCEPT

完整的一套基础规则(放最后 DROP)

# 清空
sudo iptables -F

# 默认策略
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# 放行回环
sudo iptables -A INPUT -i lo -j ACCEPT
# 放行已建立连接
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 放行常用端口
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 放行 ICMP
sudo iptables -A INPUT -p icmp -j ACCEPT

⚠️ 改防火墙的保命姿势

远程改 iptables 最怕把自己锁死。 两个技巧:

# 1. 加一条定时任务,5 分钟后清空规则(救命稻草)
sudo sh -c 'echo "iptables -F" | at now + 5 minutes'

# 2. 确认规则无误后,再取消这个定时任务

或者用 iptables-apply(部分发行版提供),它会在超时后自动回滚。

四、firewalld:区域与服务的抽象

firewalld 是 RHEL/CentOS/Rocky 7+ 的默认防火墙,用「区域(zone)」和「服务(service)」的概念,比裸 iptables 友好。

核心概念

  • 区域(zone):一套信任级别的规则集。不同网卡可绑不同区域。
  • 服务(service):预定义的一组端口,如 http = 80/tcp。
  • 运行时 vs 永久:--permanent 的规则才持久,改完要 reload。

常用区域

区域 信任级别
trusted 全放行
public 默认,只放行明示的服务
internal 内网,较信任
drop 丢弃所有入站

常用命令

# 查看状态
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-all

# 放行服务(永久)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

# 放行端口
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# 删除规则
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload

# 限制源 IP 访问某服务
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload

⚠️ 运行时与永久的区别

# 这条立即生效,但重启后丢失
sudo firewall-cmd --add-port=8080/tcp

# 这条永久保存,但需要 reload 才生效
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

图省事就都加 --permanent + reload,避免「重启后规则没了」。

五、ufw:Ubuntu 的简易防火墙

ufw(Uncomplicated Firewall)是 Ubuntu/Debian 上的简易前端,命令极简,适合日常。

基本操作

# 查看状态
sudo ufw status verbose

# 启用(先放行 SSH,否则断连)
sudo ufw allow 22/tcp
sudo ufw enable

# 放行服务
sudo ufw allow http
sudo ufw allow https

# 放行端口
sudo ufw allow 8080/tcp

# 允许某 IP 访问某端口
sudo ufw allow from 10.0.0.5 to any port 3306

# 拒绝
sudo ufw deny 23/tcp

# 删除规则
sudo ufw delete allow 8080/tcp

# 关闭
sudo ufw disable

# 重置
sudo ufw reset

默认策略

sudo ufw default deny incoming    # 默认拒绝入站
sudo ufw default allow outgoing   # 默认允许出站

ufw enable 之前务必先 allow 22/tcp,否则 SSH 一断你就进不去了。

六、nftables:新一代

nftables 取代 iptables,语法更统一(一张表管所有),性能更好。新系统上 iptables 命令其实往往是 nftables 的兼容包装。

Linux 防火墙:iptables、nftables、firewalld、ufw

四者并非并列:iptables 是传统 netfilter 用户态工具(规则链 filter/nat/mangle);nftables 是新一代统一框架,语法更简洁、性能更好,正逐步替代 iptables;firewalld 是面向区域的动态管理前端(底层可走 nft 或 iptables);ufw 是 Debian/Ubuntu 上的简化前端。生产环境建议统一一种,避免规则互相打架。

实战要点

出站默认放、入站默认拒是基本原则;做 NAT 用 MASQUERADE 或 SNAT;改规则前先留回退,远程改防火墙务必保留现有 SSH 会话或用定时任务回滚,防止把自己锁在外。规则顺序即匹配顺序,具体拒绝要放在通用允许之前。

相关阅读