Linux 防火墙

Administrator 1

Linux 防火墙


目录

  1. 软件包安装
  2. 防火墙基本概念:firewalld 与 iptables
  3. 区域(zone)概念:理解放行/拒绝的前提
  4. firewall-cmd 常用操作:开放/关闭端口,临时 vs 永久
  5. Ubuntu 系统的防火墙:UFW
  6. 踩坑排查:开放端口却连不上
  7. 常见问题排查清单
  8. 总结与对比
  9. 参考资料

软件包安装

Rocky/RHEL 默认安装了 firewalld(Minimal 安装也可能自带);Ubuntu/Debian 默认安装的是 ufw。若未安装,按下面方法安装并启动。

Rocky / RHEL / CentOS:firewalld

# 安装 firewalld
sudo dnf install -y firewalld

# 启动并设置开机自启
sudo systemctl enable --now firewalld

# 查看状态
sudo systemctl status firewalld
firewall-cmd --state        # 输出 running / not running

firewalld 自带基于 nftables 的过滤,无需再单独启用 iptables 服务。

Ubuntu / Debian:UFW

# UFW 通常已安装;若没有
sudo apt install -y ufw

其他工具(可选)

# 在 RHEL 系上也可安装 iptables 命令行工具(一般无需)
sudo dnf install -y iptables
# 在 Ubuntu 上也可安装 firewalld(与 ufw 二选一,别同时乱配)
sudo apt install -y firewalld

建议:RHEL 系用 firewalld,Ubuntu 用 UFW,不要在同一个系统上同时启用两套防火墙管理工具,以免规则互相覆盖、难以排查。


一、防火墙基本概念:firewalld 与 iptables

1.1 它们到底在管什么

Linux 内核里真正做数据包过滤的是 netfilter 框架。iptablesfirewalld 都是"往 netfilter 里写规则"的工具,只是管理方式不同。

工具 定位 特点
iptables 直接面向内核 netfilter 的命令行工具 基于表(table)→ 链(chain)→ 规则(rule),每改一条规则都要手动执行命令,规则是静态
firewalld 一个守护进程 + D-Bus 服务,是更高层的管理框架 基于区域(zone)和服务(service)抽象,规则可动态生效、可运行时/永久保存,改动不丢已建立的连接
  • iptables 是"底层、静态、手写规则"。
  • firewalld 是"上层、动态、按区域管理"。RHEL 7/8/9 和 Rocky Linux 默认用 firewalld,且 RHEL 8/9 的 firewalld 底层已改用 nftables 作为后端(不再是老式 iptables 命令)。

1.2 为什么有了 iptables 还要 firewalld

  • iptables 改一条规则就是一条命令,规则多、杂时难以管理和维护;重启后规则默认不会自动保存(需要手动 iptables-save)。
  • firewalld 提供区域预定义服务(如 httpssh),用一条命令就能放行某个服务;规则可以持久化--permanent),改动即时生效且不中断现有连接(通过 --reload 热加载)。

1.3 相关命令/文件

命令 / 文件 作用
firewall-cmd firewalld 的命令行客户端
firewalld firewalld 守护进程(服务名)
/etc/firewalld/ 系统自定义配置目录(优先于内置默认)
/usr/lib/firewalld/ 内置默认配置目录
iptablesnft 底层过滤工具(firewalld 后台调用)

参考:Red Hat - Using and configuring firewalld(RHEL 8)


二、区域(zone)概念:理解放行/拒绝的前提

2.1 什么是 zone

区域(zone) 是一组命名好的信任等级与规则集合,firewalld 把每个网络接口(或来源 IP)归属到某个区域。规则是挂在区域上的,而不是挂在接口上。理解这一点是放行/拒绝的前提:

  • 一个接口(如 ens160)属于某个区域
  • 要放行某个端口,必须把规则加在该接口所在的那个区域上,否则不生效;
  • 没显式归属的接口会落到默认区域(default zone)

2.2 查看区域

# 查看默认区域(RHEL/Rocky 通常是 public)
firewall-cmd --get-default-zone

# 查看当前"有接口/来源绑定"的活动区域
firewall-cmd --get-active-zones

# 列出所有可用区域
firewall-cmd --get-zones

# 查看某个接口属于哪个区域
firewall-cmd --get-zone-of-interface=ens160

2.3 预定义区域(9 个)与信任等级

firewalld 自带 9 个预定义区域,从最严格到最宽松:

区域 目标(target) 说明
drop DROP 丢弃所有入站包,不回复(对方无法感知主机存在)
block REJECT 拒绝所有入站,但回 ICMP(主机禁止)
public REJECT 默认区域,拒绝其他入站,信任度低,适合公共网络
external REJECT 外网区域,启用 masquerade(NAT 伪装),适合网关
dmz REJECT 隔离区,只放行选定服务
work REJECT 工作网络,信任度较高
home REJECT 家庭网络,信任度较高
internal REJECT 内部网络,信任度较高
trusted ACCEPT 接受所有入站,最宽松,仅用于完全可信环境
  • target 决定"未明确放行的入站流量"怎么处理:ACCEPT 全放、REJECT 拒绝并回 ICMP、DROP 直接丢弃。
  • 每个区域里再通过 --add-port / --add-service 单独放行特定端口/服务。
  • 对默认区域 public 来说:默认拒绝其他入站,只放行显式允许的端口/服务

2.4 修改接口所属区域(一般不推荐直接改,了解即可)

# 把接口 ens160 移到 home 区域
sudo firewall-cmd --zone=home --change-interface=ens160

# 永久生效
sudo firewall-cmd --permanent --zone=home --change-interface=ens160
sudo firewall-cmd --reload

大多数场景不需要换区域,直接在默认区域 public 里加规则即可。

参考:firewalld.org - Predefined ZonesDefault Zone


三、firewall-cmd 常用操作:开放/关闭端口,临时 vs 永久

3.1 临时(runtime)与永久(permanent)

这是 firewall-cmd 最容易踩的坑,务必先理解:

类型 命令 生效时机 持久性
临时(runtime) 不带 --permanent 立即生效 重启 firewalld 或重启机器后丢失
永久(permanent) --permanent 写入配置文件,需要 --reload 才应用到运行中 重启后保留
  • 临时规则:改完立刻生效,适合临时调试,重启即失效。
  • 永久规则:写进 /etc/firewalld/,但不会立即生效,需要 --reload(或重启 firewalld)才会作用到当前运行配置。

参考:firewalld.org - Runtime versus Permanent

3.2 开放端口

# 临时放行 8080/tcp(立即生效,重启丢失)
sudo firewall-cmd --add-port=8080/tcp

# 永久放行 8080/tcp(写入配置,需 reload 生效)
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# 指定区域放行(默认加在 --get-default-zone 所在区域)
sudo firewall-cmd --zone=public --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
  • 端口要写 端口/协议,如 8080/tcp53/udp
  • 协议必须对:TCP 服务放 /tcp,UDP 服务放 /udp,写错协议照样连不上。

3.3 放行服务(service)

firewalld 内置很多预定义服务(如 httphttpsssh),一条命令即可:

# 永久放行 http 服务(对应 80/tcp)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

# 查看所有可用服务
firewall-cmd --get-services

# 查看服务对应的端口
firewall-cmd --permanent --service=http --get-ports

3.4 查看、查询、关闭

# 查看默认区域放行内容(端口、服务、源等)
firewall-cmd --list-all

# 查看某区域的完整规则
firewall-cmd --zone=public --list-all

# 查询某个端口是否已放行
firewall-cmd --query-port=8080/tcp

# 移除端口(临时/永久,与添加对应)
sudo firewall-cmd --remove-port=8080/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload

3.5 把临时规则固化为永久

想把已经在跑的一堆临时规则保存下来:

# 把当前所有运行时规则复制为永久规则
sudo firewall-cmd --runtime-to-permanent

3.6 reload 与 complete-reload 的区别

sudo firewall-cmd --reload             # 保留运行时规则,重新加载永久配置(热加载,不中断连接)
sudo firewall-cmd --complete-reload    # 丢弃运行时规则,完全按配置文件重建(可能中断)
  • 通常用 --reload 即可。
  • 改完永久配置后忘了 --reload,是"开放端口却连不上"的高频原因之一。

参考:firewalld.org - Reload firewalld


四、Ubuntu 系统的防火墙:UFW

Ubuntu/Debian 默认的防火墙管理工具是 UFW(Uncomplicated Firewall),它是对 iptables/nftables 的简单封装,底层仍是 netfilter。

4.1 启用与查看状态

sudo ufw enable          # 启用(会提示确认)
sudo ufw status          # 查看状态与规则
sudo ufw status verbose  # 详细(含默认策略)
  • UFW 默认策略是 默认拒绝入站(deny incoming)、默认允许出站(allow outgoing)——即默认拒绝外部访问,但本机可以自由对外访问。

4.2 放行与关闭端口/服务

# 放行某端口
sudo ufw allow 22/tcp
sudo ufw allow 8080

# 放行服务名
sudo ufw allow ssh
sudo ufw allow http

# 允许特定来源 IP 访问某端口
sudo ufw allow from 192.168.1.0/24 to any port 3306

# 删除规则(按编号或按规则内容)
sudo ufw status numbered          # 先列出编号
sudo ufw delete 3                 # 删除编号 3 的规则
sudo ufw delete allow 22/tcp      # 按内容删除

4.3 重置

sudo ufw reset    # 清空所有规则(慎用)

4.4 注意事项

  • 先放行 SSH 再启用 UFW,否则可能把自己锁在外面(sudo ufw allow ssh22/tcp 先做)。
  • UFW 规则也是写进 /etc/ufw/ 配置文件,ufw 命令改完即生效并持久保存,不需要额外 reload。

参考:Ubuntu - Firewall(官方文档)ufw man 手册


五、踩坑排查:开放端口却连不上

这是运维中最常见的场景:明明 --add-port 放行了,外面还是连不上。 下面按"从内到外"的顺序排查。

5.1 排查清单(按顺序走一遍)

① 服务真的在监听吗?监听的地址和端口对不对?

ss -tlnp        # 查看 TCP 监听端口
ss -ulnp        # 查看 UDP 监听端口
  • 看服务是不是根本没起来,或监听在别的端口
  • 看是不是只监听了 127.0.0.1(本机回环),那样外部永远连不上——应监听 0.0.0.0 或具体网卡 IP。
  • 应用本身如果没起来,防火墙放不放行都没用。

② 防火墙规则是临时还是永久?永久规则 reload 了吗?

firewall-cmd --query-port=8080/tcp     # 运行中是否真的放行了
firewall-cmd --list-all                # 看当前生效内容
  • 只加了 --permanent --add-port 却没 --reload运行中并没有放行(规则只在配置文件里)。
  • 只加了临时规则(没 --permanent),重启后丢失,表现为"之前能连、重启后连不上"。

③ 规则加对区域了吗?接口在哪个区域?

firewall-cmd --get-active-zones
firewall-cmd --get-zone-of-interface=ens160
  • 规则要加在接口实际所属的区域。如果接口在 public,你把端口加到了 home,就不生效。
  • 确认默认区域:firewall-cmd --get-default-zone

④ 协议对不对?TCP 还是 UDP?

  • 服务是 TCP 就放 8080/tcp,是 UDP 就放 8080/udp,别混。

⑤ 是 SELinux 在拦吗?(RHEL/Rocky 特有)

getenforce      # Enforcing / Permissive / Disabled
sudo ausearch -m avc -ts recent    # 查看被拒绝记录
  • RHEL/Rocky 默认启用 SELinux,即使防火墙放行,SELinux 也可能拦截非标准端口的服务。
  • 若确认是 SELinux 拦,可用 sudo semanage port -a -t http_port_t -p tcp 8080 放行该端口(需安装 policycoreutils-python-utils)。

⑥ 是不是云平台/外部防火墙在拦?

  • 阿里云/腾讯云/AWS 等安全组是云平台层面的独立防火墙,即使操作系统放行了,安全组没放行一样连不上。去云控制台检查安全组/网络安全组。

⑦ 本机先自测连通性

curl http://127.0.0.1:8080        # 本机测
ss -tlnp | grep 8080              # 确认在监听
  • 本机能通、外部不通,多半是防火墙/安全组/SELinux;本机也不通,多半是服务本身没起来或监听地址不对

5.2 一个完整的排查例子

假设要对外放行 8080 端口的 Web 服务:

# 1. 确认服务在监听且监听地址正确
ss -tlnp | grep 8080        # 期望看到 0.0.0.0:8080 或具体网卡 IP:8080

# 2. 永久放行并 reload
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# 3. 确认运行中已生效
firewall-cmd --query-port=8080/tcp    # 期望输出 yes

# 4. 本机测通
curl http://127.0.0.1:8080

# 5. 若本机通而外部不通:查 SELinux、云安全组、接口所属区域
getenforce
firewall-cmd --get-active-zones

排查思路:先服务后防火墙,先本机后外网,先运行时后永久,先系统后云平台。 按这个顺序,绝大多数"放行了却连不上"都能定位。


六、常见问题排查清单

  1. 放行了还是连不上 → 先看服务是否监听、监听地址是否正确(ss -tlnp)。
  2. 永久规则没生效 → 加了 --permanent忘记 --reload
  3. 重启后规则丢了 → 加的是临时规则,改用 --permanent
  4. 规则加错区域 → 用 --get-active-zones / --get-zone-of-interface 核对接口所在区域。
  5. TCP/UDP 写错 → 服务是 TCP 放 /tcp,UDP 放 /udp
  6. SELinux 拦截(RHEL 系)→ getenforceausearch -m avc、必要时 semanage port
  7. 云安全组没放行 → 操作系统防火墙之外,还要在云控制台安全组放行。
  8. Ubuntu 连不上 → 检查 sudo ufw status 是否已 ufw allow;确认先放行了 SSH 再 enable。

七、总结与对比

7.1 firewalld / UFW / iptables 速查

需求 firewalld(RHEL/Rocky) UFW(Ubuntu)
查看状态 firewall-cmd --state sudo ufw status
放行端口(临时) firewall-cmd --add-port=8080/tcp (UFW 直接持久生效)
放行端口(永久) firewall-cmd --permanent --add-port=8080/tcp; firewall-cmd --reload sudo ufw allow 8080/tcp
删除 --remove-port=8080/tcp sudo ufw delete allow 8080/tcp
放行服务 --add-service=http sudo ufw allow http
查看当前放行 --list-all sudo ufw status

7.2 工具选择

场景 工具
RHEL/Rocky/CentOS 服务器 firewalld(默认、动态、区域化管理)
Ubuntu/Debian 服务器 UFW(默认、简单)
需要底层精细规则、脚本化 iptables / nftables(底层,手工管理)
现代 RHEL 8/9 底层 firewalld 已基于 nftables

7.3 动手练习建议

# 1. RHEL/Rocky:放行一个端口并验证
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
firewall-cmd --query-port=8080/tcp
firewall-cmd --list-all

# 2. 体验临时 vs 永久
sudo firewall-cmd --add-port=9090/tcp      # 临时
firewall-cmd --query-port=9090/tcp          # yes
sudo systemctl restart firewalld            # 重启后
firewall-cmd --query-port=9090/tcp          # no(临时规则丢失)

# 3. Ubuntu:先放行 SSH 再启用
sudo ufw allow ssh
sudo ufw enable
sudo ufw status

提示:练习在虚拟机进行。改防火墙前先确认放行了 SSH,避免把自己锁在机器外;云服务器还要同步检查安全组。


参考资料