1. 为什么我在 Arch Linux 上最终还是选了 UFW
先说结论:Arch Linux 默认不带任何防火墙,装上系统那一刻其实处于“裸奔”状态。很多老玩家会觉得“我局域网里没啥危险,少开服务就行”,这种想法我理解,但现实是只要你的机器连着路由器、开着 SSH 或者跑着 Docker,被扫描和试探就是迟早的事。我自己就在一次挂机下载时被扫到过,当时虽然没什么损失,但事后一想确实后怕。
UFW 全称 Uncomplicated Firewall,是 iptables/nftables 的前端封装。它不替代内核防火墙,而是把 iptables 那套复杂的链、表、规则写法,简化成几条贴近人类语法的命令。在 Arch Linux 上装 UFW 不是因为它最强大,而是因为它足够直观、适合绝大多数个人桌面和家用服务器场景。相比直接手写 iptables 规则,UFW 的学习成本低一个量级;相比 firewalld 那种带 zone 概念的方案,UFW 的思路又是直来直去——放行什么、拒绝什么,一眼就能看懂。
Arch 社区对 UFW 的接受度其实挺高,官方仓库里就有 ufw 包,维护也算积极。而且 UFW 在 Arch 上的表现和 Ubuntu/Debian 上几乎没有差别,这不奇怪,毕竟它底层调用的都是内核标准接口,发行版之间的差异主要体现在初始化脚本和服务管理方式上。这篇文章就按我在 Arch 上的实际操作路径来写,从安装、初始化、配置规则到和 Docker 共存,把我踩过的坑和验证过的做法都列出来。如果你也用的是 Arch 系(包括 Manjaro、EndeavourOS 这类衍生版),可以直接照抄。
开头先给不熟悉的朋友铺个底:UFW 默认工作方式是“默认拒绝入站,默认放行出站”,你需要显式放行想要对外开放的端口。这种“白名单优先”的思路,本身就是一种安全习惯的养成。下面从安装开始。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装与初始化:Arch 上把 UFW 跑起来
2.1 安装 ufw 包并解决服务启动问题
Arch 上安装 UFW 非常简单,pacman 一条命令就能搞定:
bash复制sudo pacman -S ufw
安装完成后不要急着启用,先做一两步检查。第一步是确认系统里没有其他防火墙在跑,比如 nftables 服务或者 firewalld,如果有,先停掉再继续。Arch 默认没有,但如果你之前折腾过,最好确认一次:
bash复制systemctl status nftables firewalld
第二步是启动并启用 UFW 服务,注意 Arch 里 UFW 的 systemd 服务名就叫 ufw:
bash复制sudo systemctl enable --now ufw
这里有个 Arch 特有的小区别:Debian/Ubuntu 上 UFW 的 systemd 服务更像辅助角色,真正的开关由 ufw enable 命令控制;Arch 上如果你只想用服务方式管理,直接 systemctl enable --now ufw 也行。不过我个人的习惯是服务常开,具体启停交给 ufw 命令,这样后续规则配置的语义更清晰。
注意:启用 UFW 服务之后,防火墙规则本身还没生效。你还需要执行
sudo ufw enable才能让内核真正的规则链挂载上。这两个“启用”不是一回事,别搞混。
2.2 先设置默认策略,再谈放行规则
我见过不少新手拿到 UFW 第一件事就是 ufw allow 22,但默认策略还是放行所有,那这防火墙基本等于摆设。正确顺序一定是先设默认策略,再放行需要的端口。
bash复制sudo ufw default deny incoming
sudo ufw default allow outgoing
default deny incoming 的含义是:所有外部主动发起的连接,只要没有显式匹配放行规则,一律拒绝。default allow outgoing 表示本机访问外部不受限制,下载更新、浏览网页、DNS 解析这些都不受影响。这也是最主流的家用和个人服务器策略,兼顾安全和使用体验。
如果你跑的是纯粹的公网服务器,且只提供有限的几个服务,我建议把 outgoing 也考虑收紧,比如限制成只放行 DNS、HTTP/HTTPS 和 NTP。但这条对普通用户不友好,排查问题会多花很多时间,所以初期先用“入站全拒、出站全放”是合理的起步配置。
确认默认策略没有写反之后,再执行:
bash复制sudo ufw enable
这一步会输出规则已经生效的提示。看到提示后,可以用下面的命令验证防火墙状态:
bash复制sudo ufw status verbose
输出大致是:
code复制Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
到这里,UFW 已经在 Arch 上正式跑起来了。接下来才是重头戏——按你的实际场景配置规则。
3. 核心规则配置:端口、IP 与黑白名单实操
3.1 放行常用端口:SSH、HTTP、HTTPS 的标准姿势
先别急着 allow 一堆端口,想清楚你的机器到底对外提供什么服务。以最常见的家庭服务器为例,假设你开了 SSH 远程管理、HTTP 网页服务、HTTPS,那规则如下:
bash复制sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
这里有两个常见疑问:第一,为什么写 22/tcp 而不是直接写 22?因为 UFW 默认情况下 allow 22 会同时放行 TCP 和 UDP,而绝大多数服务只需要 TCP。只写 UDP 的端口很少,把 UDP 也放出去等于多暴露了一个面,不是好习惯。第二,能不能用服务名代替端口号?可以,ufw allow ssh 和 ufw allow 22/tcp 效果一样,因为 UFW 会去读 /etc/services 的端口映射。但我个人更推荐直接写端口,毕竟你心里得清楚自己在放行什么。
如果你是临时放行某个端口做调试,用完后要删掉规则,命令是:
bash复制sudo ufw delete allow 22/tcp
注意 delete 后面跟的规则描述要和添加时完全一致,否则会提示找不到规则。
3.2 限制来源 IP:只允许特定地址访问 SSH
公网直接暴露 SSH 是安全大忌,哪怕密码再复杂也顶不住持续爆破。我在自己机器上的做法是只允许局域网 IP 访问 SSH,公网一律不给进:
bash复制sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp
这条规则的意思是:允许来自 192.168.1.0/24 网段的设备访问本机 22 端口的 TCP 协议。执行后,其他任何来源的 SSH 连接都会被默认拒绝策略拦在门外。
如果你有固定公网 IP,比如公司办公室的出口 IP,也可以把它加进白名单:
bash复制sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
这里 203.0.113.10 是文档示例地址,实际使用时替换成你那个固定的公网 IP。多个来源 IP 就写多行,UFW 会逐条匹配,只要命中其中一条就算放行。
这种“来源 IP + 目标端口”组合的写法好处在于,就算有人扫描到你的 SSH 端口并且尝试爆破,非白名单来源的连接在 TCP 握手阶段就被丢弃了,扫描器压根感知不到这个端口是开放的。
3.3 按网络接口限定的高级写法
如果你的机器有多个网卡,比如一个连内网、一个连外网,那么只按 IP 限定还不够,最好把接口也加进规则。UFW 支持在规则里指定接口:
bash复制sudo ufw allow in on enp2s0 to any port 22 proto tcp
这条规则只在 enp2s0 这个接口上生效,其他接口来的 SSH 流量还是走默认拒绝策略。查询接口名可以用 ip addr 或者 ip link,在 Arch 上这两个命令属于 iproute2 包,系统默认就有。
接口限定的好处我在实际中深有体会:一台机器既连着路由器内网,又通过 USB 网卡共享网络给另一台设备,如果只限定 IP 不限定接口,内网某个被攻破的设备就能借道访问你的 SSH。把接口、网段、端口三层一起限定,规则才叫完整。
3.4 拒绝特定 IP:黑名单思路在 UFW 里的实现
默认策略是拒绝所有入站,所以黑名单的实际用法一般是“拒绝某个明确的来源”。比如你发现某个 IP 在疯狂扫描:
bash复制sudo ufw deny from 198.51.100.7
这条规则会把来自 198.51.100.7 的所有流量丢弃,不管目标端口是什么。也可以细化到端口级拒绝:
bash复制sudo ufw deny from 198.51.100.7 to any port 22 proto tcp
黑名单适合少量明确敌意的来源,不建议大规模维护。真正面对大量扫描时,靠的是 fail2ban 这类动态封禁工具,它会自动分析日志、调用 UFW 添加临时规则。后面我会专门讲这个组合用法。
3.5 规则顺序与 UFW 的匹配逻辑
很多人在配置规则时忽略顺序,然后发现某条规则“失效”了。UFW 底层基于 iptables,而 iptables 是顺序匹配、命中即停。也就是说,一旦前面的规则匹配成功,后面的规则就不会再看了。
UFW 自己维护了一套默认顺序:它会把所有规则按“允许”“拒绝”“限制”等类型分组,同组内再按添加顺序排列。实际操作中你不需要太纠结规则顺序,因为 UFW 已经做了分类处理。但有一个例外需要注意:当你同时配置了白名单和黑名单,且两条规则作用范围重合时,后添加那条不一定“更优先”。UFW 实际执行时,deny 规则一般会先于 allow 规则被处理。这个行为在内核版本和 UFW 版本不同时可能会有差异,如果你遇到“为什么我 deny 了但还能访问”的怪问题,先用 sudo ufw status numbered 查看规则编号,再用 sudo ufw delete 编号 删掉需要调整的规则,重新按正确顺序添加。
提示:
ufw status numbered是按编号列出当前所有活动规则。删除规则时可以按编号删,比如sudo ufw delete 3就是删除编号为 3 的那条,比自己重新敲一遍完整规则要省事,而且不容易出错。
4. 高级用法:速率限制、日志与图形化管理
4.1 用 limit 规则防 SSH 暴力破解
UFW 自带一个很实用的速率限制功能,写法极其简单:
bash复制sudo ufw limit ssh
等价于完整写法:
bash复制sudo ufw limit 22/tcp
limit 规则的含义是:对同一个来源 IP,如果 30 秒内尝试连接超过 6 次,后续连接直接拒绝。这个机制对 SSH 防爆破效果非常明显,因为正常人类手动操作根本不可能在 30 秒内建立 6 次 SSH 会话,而自动化脚本一秒钟就能试好几次。
我在自己的 Arch 本机和服务器上都开了这条规则,用了快一年,再也没有出现过日志里一排排的 “Failed password” 刷屏。当然 limit 不是万能的,遇到分布式爆破(很多 IP 同时扫)它就有点力不从心,这时需要 fail2ban 协同。但在个人场景下,ufw limit ssh 已经能把 90% 的脚本小子挡在门外。
注意,limit 规则不要滥用。如果某个服务本身就有高频短连接的特性,比如健康检查、API 轮询,加了 limit 反而会把正常请求挡掉。在使用前想清楚这个端口的业务特征。
4.2 打开日志并看懂 UFW 的日志输出
UFW 默认日志级别是低,也就是只记录不符合规则的丢弃包。如果你在做排查,需要看更详细的信息,可以把日志级别调高:
bash复制sudo ufw logging medium
可选级别有 off、low、medium、high、full。我一般用 medium,它会记录所有入站和出站的策略命中情况,对排查问题信息量刚好。high 和 full 日志量太大,个人机器没必要。
日志写到哪?在 Arch 上走的是 systemd 的 journal,直接查看:
bash复制journalctl -u ufw --since today
也可以看内核日志中 UFW 打点的部分:
bash复制sudo dmesg | grep UFW
实际排查中,最典型的一个场景是:你明明加了一条 allow 规则,但服务还是连不上。这时打开日志,大概率会看到类似这样的丢弃记录:
code复制[UFW BLOCK] IN=eth0 OUT= MAC=... SRC=192.168.1.50 DST=192.168.1.100 PROTO=TCP DPT=8080
这行日志的含义是:来自 192.168.1.50 的数据包,目标端口 8080,被 UFW 拦了。有了这条信息,你至少可以确定不是服务本身的问题,而是防火墙规则没放行到位。
4.3 补充:图形化前端 Gufw
虽然 UFW 的命令行已经足够简单,但有些场景下,比如给不太懂命令行的室友配置电脑,图形界面会更友好。Arch 官方仓库里有 gufw 包:
bash复制sudo pacman -S gufw
Gufw 是 UFW 的 GTK 前端,启动后会显示当前状态和规则列表,通过勾选和填写表单就能完成端口放行、IP 限制等操作。它本质上还是在调用 ufw 命令,所以现有的命令行规则它能完整显示出来,不会互相冲突。
我自己日常还是用命令行,Gufw 主要是在帮别人配置时用。如果你习惯图形界面,完全可以用 Gufw 作为主要管理工具,底层逻辑不变。
4.4 备份与恢复规则
防火墙规则是累积配置的,重装系统前不备份,到时候重写一遍很痛苦。UFW 规则其实存储在 /etc/ufw/ 目录下的几个文件里,user.rules 和 user6.rules 分别对应 IPv4 和 IPv6 的规则。最简单粗暴的备份方式:
bash复制sudo cp /etc/ufw/user.rules ~/ufw-user.rules.bak
sudo cp /etc/ufw/user6.rules ~/ufw-user6.rules.bak
恢复时把文件拷回去,然后重启 UFW 服务让它重新加载:
bash复制sudo systemctl restart ufw
此外,如果你只想导出规则列表用于查看,可以:
bash复制sudo ufw status verbose > ~/ufw-status.txt
这种方式适合做变更前后的对比,排查到底是哪条规则引起的问题。
5. 与 Docker 的冲突:在 Arch 上必须重视的坑
5.1 Docker 绕过 UFW 的原因
在 Arch 上同时跑 Docker 和 UFW,大概率会遇到这个问题:明明 UFW 默认拒绝了所有入站,但 Docker 容器映射出来的端口,在外网还是能直接访问。这个现象我第一次遇到时也百思不得其解,查了半天才明白原委。
原因在于 Docker 默认使用 iptables 来管理容器网络,它会在 iptables 的 DOCKER 链里直接插入规则,而 UFW 生成的规则在 FORWARD 链上的位置和 Docker 的不完全兼容。简单说,Docker 在创建端口映射时,会在 iptables 的 nat 表和 filter 表里写入自己的规则,这些规则生效的位置先于 UFW 的 FORWARD 链检查,所以 UFW 的“默认拒绝入站”根本没机会拦截容器端口。
这带来的安全隐患很实际:你通过 docker run -p 8080:80 暴露了一个服务,按直觉理解,UFW 没有放行 8080,外部应该连不上;但实际情况是外部照样能访问,因为 Docker 的规则直接放行了。
5.2 验证问题并选择解决方案
先验证你的环境是否踩了这个坑。在宿主机上查看 UFW 状态:
bash复制sudo ufw status
然后从另一台设备访问 Docker 映射出来的端口,如果 UFW 显示规则里没有放行该端口,但连接却成功了,那基本可以确认 Docker 绕过 UFW 的问题存在。
解决方案有几种,我按推荐程度排个序:
第一种:调整 Docker 的 iptables 行为,让 Docker 完全使用 UFW 管理的链。在 /etc/docker/daemon.json 里加一行:
json复制{
"iptables": false
}
然后重启 Docker:
bash复制sudo systemctl restart docker
这样 Docker 不会自己操作 iptables,容器的网络转发完全交给宿主机的规则管理。但注意,这个方案会影响 Docker 的网络功能,比如容器之间的通信、端口映射等都需要你自己配置规则,对新手不友好。
第二种:保持 Docker 默认行为,但在 UFW 里显式放行需要暴露的端口。这种方案不解决“绕过”问题,但至少让你知道哪些端口是真正开放的,不至于留一个“我以为没开”的漏洞。
第三种:给 UFW 的 FORWARD 链设置默认策略。在 /etc/ufw/sysctl.conf 里确保 IP 转发已开启,同时把 UFW 的 FORWARD 默认策略设为拒绝,然后通过规则放行 Docker 网段。这个方案需要手动维护 Docker 网段的放行规则,配置相对复杂,但对端口控制更精细。
我目前在 Arch 服务器上的做法是方案三的简化版:保留 Docker 默认 iptables 行为,同时在 UFW 里显式放行容器端口,并在 FORWARD 链上做了限制。这样最直观,安全性也不会因为 Docker 而意外降低。
5.3 用 UFW 管理 Docker 映射端口的推荐流程
如果你也是方案三的路线,建议养成一个习惯:每启动一个新的容器映射端口,先确认这个端口是否需要对公网开放,不需要就只在 UFW 中放行内网网段:
bash复制sudo ufw allow from 192.168.1.0/24 to any port 8080 proto tcp
需要对公网开放的,再单独放行:
bash复制sudo ufw allow 8080/tcp
记着在 docker run 命令里加 --restart=unless-stopped,配合 UFW 规则让容器和防火墙都随系统自动恢复。这个组合我实测在 Arch 上跑得很稳,未出现过重启后规则丢失或容器网络异常的问题。
6. 常见问题与排查技巧实录
6.1 规则添加成功但端口依然不通
这是最高频的问题。查的时候先确认服务本身在监听:
bash复制ss -tlnp | grep 8080
如果输出里没有 8080,那问题在应用不在防火墙。如果监听正常,再看 UFW 规则是否包含正确的协议。很多人只 allow 8080,但服务监听的是 UDP,那自然不通。用 sudo ufw status 查看规则,确认是 8080/tcp 还是 8080/udp。
还有一种情况:规则里写了具体的来源 IP,但你的客户端 IP 不在范围内。检查一下你当前的公网 IP 是否变了,特别是家用宽带,IP 是动态分配的,可能昨天还好好的,今天就因为 IP 变了被拒了。
6.2 查看日志确定是不是 UFW 拦截
日志是排除问题的第一手资料。Arch 上直接:
bash复制journalctl -k --since "10 minutes ago" | grep UFW
如果看到大量 [UFW BLOCK] 且目标端口是你需要放行的端口,说明规则写得有问题。对照日志里的 SR C 和 DPT,检查你的 allow 规则是不是漏了来源 IP、协议或者目标端口。
6.3 重启后防火墙规则丢失
确认你是否执行过 sudo ufw enable。如果只是启动了 systemd 服务而没有 enable UFW,规则不会持久化。正确做法是:
bash复制sudo systemctl enable --now ufw
sudo ufw enable
这两个命令都执行过之后,规则在重启后会自动加载。如果还是丢,检查 /etc/ufw/user.rules 文件是否存在非空内容,文件丢了就恢复备份。
6.4 如何快速恢复默认配置
配置改乱了又想重来,不用一条条删,直接恢复默认:
bash复制sudo ufw reset
这个命令会清除所有规则并禁用 UFW。注意它也会把 UFW 状态重置到安装初始状态,执行前确认你不需要保留现有规则。重置后重新走一遍“默认策略 + 放行规则”的流程就好。
6.5 常见问题速查表
| 问题 | 可能原因 | 排查与解决 |
|---|---|---|
| 端口不通 | 服务未监听 | ss -tlnp 检查监听状态 |
| 端口不通 | 规则协议写错 | 确认 TCP/UDP 与日志中的 PROTO 一致 |
| 端口不通 | 来源 IP 不在白名单 | 查看规则 from 字段,确认客户端 IP |
| 规则没生效 | 未执行 ufw enable |
先执行 enable 再验证 |
| 重启后规则丢失 | 未同时启用服务和 UFW | 同时执行两个 enable 命令 |
| Docker 端口绕过了 UFW | Docker 直接改 iptables | 手动在 UFW 放行容器端口,或关闭 Docker 的 iptables 行为 |
6.6 日志占用过多磁盘空间
日志级别开太高,外加被扫描频繁时,日志文件膨胀速度会超出预期。journald 默认有大小限制,但还是建议主动给它设个上限,编辑 /etc/systemd/journald.conf:
code复制SystemMaxUse=500M
然后重启 journald:
bash复制sudo systemctl restart systemd-journald
这个配置属于锦上添花,但实际用久了就知道很重要,尤其对长期开机不重启的服务器。
7. 最后再分享一点我自己的使用习惯
UFW 用了这几年,我最深的体会是:防火墙规则一定要“说人话”。意思是每加一条规则,都要能说清楚这条规则存在的理由是什么。如果理由不明确,那就不要加。规则越少,攻击面越小,排查问题也越容易。目前我 Arch 桌面和服务器上的活动规则加起来不超过十条,每条都有对应场景。
另一个习惯是:每次修改规则后,顺手看一眼 sudo ufw status numbered,确认最终结果和预期一致。修改不是做完就完了,验证才是关键一步。尤其是从“全放行”改成“默认拒绝”的初期,很容易漏掉某个自己在用的端口,导致远程连接直接断掉。如果你正在远程操作服务器,改默认策略前务必确认防火墙放行了 SSH,否则改完你就得跑去机房了——这个教训我是真金白银换来的。
最后再给一条建议:不要一上来就追求复杂规则,先让 UFW 用最简单的方式跑通,再根据实际需求逐步加严。安全不是配置出来的,是对自己系统了解程度的一种体现。
