ufw 是 Ubuntu 提供的防火墙配置工具,全称 uncomplicated firewall。它的底层仍然是 netfilter/iptables——Linux 2.4 内核之后提供的那套包过滤框架,netfilter 工作在内核内部负责实际处理数据包,iptables 是让用户定义规则集的表结构。iptables 的规则语法偏复杂,ufw 在它之上做了一层简化封装,日常开放端口、限制来源 IP 用 ufw 就够了;更复杂的 NAT、包分割等场景仍然要回到 iptables。Ubuntu 系统默认已经安装了 ufw,没有的话装一下即可:
sudo apt-get install ufw一、常用命令速查
| 操作 | 命令 |
|---|---|
| 查看状态 | sudo ufw status |
| 查看详细规则 | sudo ufw status verbose |
| 带编号查看规则 | sudo ufw status numbered |
| 启用防火墙 | sudo ufw enable |
| 关闭防火墙 | sudo ufw disable |
| 重新加载规则 | sudo ufw reload |
| 默认拒绝入站 | sudo ufw default deny incoming |
| 默认允许出站 | sudo ufw default allow outgoing |
| 放行端口 | sudo ufw allow 22/tcp |
| 删除规则 | sudo ufw delete allow 22/tcp |
| 列出可用应用 | sudo ufw app list |
二、查看状态与启停
# 查看防火墙状态,未启用时输出 Status: inactive
sudo ufw status
# 启用后查看完整规则(含默认策略、日志设置)
sudo ufw status verbose
# 带编号查看,删除规则时按编号操作比较方便
sudo ufw status numbered关于「查看已放行的规则」,网上有些资料写的是 sudo ufw show allowed,但 ufw 并没有这个子命令,执行会报错。ufw show 真正支持的报表项是:raw、builtins、before-rules、user-rules、after-rules、logging-rules、listening、added。想确认自己加过哪些规则,用 sudo ufw show added;想看完整生效规则,用 sudo ufw status verbose。
# 开启(会写入配置,开机自动生效)
sudo ufw enable
# 关闭(同样持久化,重启后不会自动开启)
sudo ufw disable
# 手工改过规则文件后重新加载
sudo ufw reload三、默认策略
ufw 的默认策略是「拒绝入站、允许出站」,也就是外部主动连进来的请求默认被丢弃,本机主动访问外部不受限制。可以显式设置:
# 拒绝所有入站连接(ufw default deny 默认作用于 incoming)
sudo ufw default deny incoming
# 允许所有出站连接
sudo ufw default allow outgoingdefault 后面还可以跟 allow / deny / reject,方向可选 incoming / outgoing / routed,省略方向时默认是 incoming。deny 是静默丢弃,对方看到的是超时;reject 会回一个拒绝响应,排查问题时更容易定位。
四、添加规则
1. 按端口或服务名放行
# 按服务名,smtp 对应 25/tcp
sudo ufw allow smtp
# 按端口 + 协议
sudo ufw allow 22/tcp
# 只写端口号,会同时放行该端口的 tcp 和 udp
sudo ufw allow 53
sudo ufw allow 53/tcp # 只放行 tcp服务名来自系统的 /etc/services,常见的还有 ssh(22)、http(80)、https(443)。写服务名等价于写它对应的端口和协议。只写数字端口时不带协议,会让 tcp 和 udp 一起放行,如果只需要 tcp,务必加上 /tcp。
2. 按来源 IP 放行
# 允许该 IP 访问本机所有端口
sudo ufw allow from 192.168.1.100
# 只允许该 IP 访问本机 3306 端口
sudo ufw allow from 192.168.1.100 to any port 3306
# 允许 22 端口,并加注释方便日后识别
sudo ufw allow 22/tcp comment 'SSH'3. 完整规则语法
ufw 规则的完整形式是:
ufw [delete] [insert NUM] allow|deny|reject|limit [in|out [on INTERFACE]] \
[log|log-all] [proto PROTOCOL] \
[from ADDRESS [port PORT | app APPNAME]] \
[to ADDRESS [port PORT | app APPNAME]] \
[comment COMMENT]关键是关键字顺序不能乱:proto → from → to,端口写在它所修饰的地址后面。例如「允许源地址 192.168.0.1 的 53 端口访问 192.168.0.2 的 53 端口(UDP)」:
sudo ufw allow proto udp from 192.168.0.1 port 53 to 192.168.0.2 port 53如果按 iptables 的习惯写成 ufw allow proto udp 192.168.0.1 port 53 ...,会因为缺少 from 关键字直接报参数错误。多个端口可以用逗号或区间:
sudo ufw allow proto tcp from any to any port 80,443,8080:8090 comment 'web app'4. 限速放行
对 SSH 这类直接暴露的端口,用 limit 代替 allow 可以起到一定的防暴力破解作用:同一个 IP 在 30 秒内发起 6 次以上连接就会被拒绝。
sudo ufw limit 22/tcp comment 'SSH rate limit'五、删除规则
删除规则有两种方式,推荐第二种:
# 方式一:在原有规则前加 delete,规则要原样照抄
sudo ufw delete allow smtp
sudo ufw delete allow from 192.168.254.254
# 方式二:先查编号,再按编号删除
sudo ufw status numbered
sudo ufw delete 3方式一必须把原规则一字不差地写出来,规则多、带注释时很容易对不上;编号删除更可靠。注意每次删除后编号会重新排列,所以一次只删一条,删完重新 status numbered 确认。
常见的增删对照:
| 放行 | 删除 |
|---|---|
sudo ufw allow 53 | sudo ufw delete allow 53 |
sudo ufw allow 80/tcp | sudo ufw delete allow 80/tcp |
sudo ufw allow smtp | sudo ufw delete allow smtp |
sudo ufw allow from 192.168.254.254 | sudo ufw delete allow from 192.168.254.254 |
六、按应用放行
安装过 Nginx、Apache 之类的软件后,ufw 会读取它们提供的配置文件,可以直接按应用名一键放行,不用记端口:
# 列出当前系统上已注册的应用
sudo ufw app list
# 查看某个应用会开放哪些端口
sudo ufw app info 'Nginx Full'
# 按应用放行
sudo ufw allow 'Nginx Full'这些应用配置存放在 /etc/ufw/applications.d,格式是一个个 ini 段落,ports 字段用 | 分隔多个端口/协议,不写协议表示同时开放 tcp 和 udp。如果某个服务没有自带配置,新建一个文件放进去即可,sudo ufw app update <name> 刷新。
七、启用顺序:别把自己锁在门外
这是使用 ufw 最容易出事的地方。ufw enable 之后入站默认就是拒绝,如果还没有放行 SSH 端口就启用了防火墙,当前连接虽然可能还在(ufw 会提示 Command may disrupt existing ssh connections),但一旦断开就再也连不上了,云服务器只能走 VNC 或救援模式进去救。
安全的顺序是:先放行 SSH,再设默认策略,最后启用。
# 1. 先放行 SSH(用非 22 端口的话换成实际端口)
sudo ufw allow 22/tcp
# 2. 设置默认策略
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 3. 最后启用
sudo ufw enable
# 4. 确认 22 端口在列
sudo ufw status verbose另外 ufw enable 是持久化的,重启后依然生效,不需要额外配置开机自启;如果是在远程会话里操作的,建议先用 sudo ufw --dry-run enable 看看会生成哪些规则,确认无误再真正执行。
八、配置文件位置
| 路径 | 说明 |
|---|---|
/etc/ufw/ | ufw 的环境配置文件目录,包含 before.rules、after.rules、sysctl.conf、ufw.conf,以及 IPv6 对应的 before6.rules、after6.rules。一般保持默认即可 |
/etc/ufw/user.rules | 用命令添加的规则最终会以 iptables-restore 格式写在这里(IPv6 对应 user6.rules);/var/lib/ufw/ 下也有同名副本供初始化脚本使用 |
/etc/ufw/sysctl.conf | 与内核参数相关。启用 ufw 后它会覆盖默认的 /etc/sysctl.conf:如果这里面有新的赋值就以它为准,没有则仍以 /etc/sysctl.conf 为准 |
/etc/default/ufw | ufw 的主开关与默认行为配置,例如 IPv6 支持的 IPV6=yes/no、指定用哪个 sysctl 文件的 IPT_SYSCTL= |
/etc/ufw/applications.d/ | 应用配置档案,供 ufw app 系列命令使用 |
规则文件是可以直接编辑的,改完执行 sudo ufw reload 生效。不过手写 iptables-restore 格式容易出错,一旦语法有问题会导致规则整段加载失败,所以能用命令就用命令,手改只作为批量调整时的备选手段。
九、两个容易踩的坑
1. ufw 拦不住 Docker 发布的端口
如果服务器上跑了 Docker,会发现一个反常现象:明明 ufw deny 了某个端口,容器映射出来的端口却依然能从外部访问。原因是 Docker 自己直接操作 iptables,通过 NAT 转发和 DOCKER-USER、FORWARD 链处理流量,不经过 ufw 的 INPUT 链,所以 ufw 的规则对它不生效。常见的处理方式有:
- 把容器端口只绑定到本机:
ports: - "127.0.0.1:8080:8080",外部只能通过反向代理访问; - 使用
ufw-docker这类工具,把规则写进DOCKER-USER链; - 在
/etc/docker/daemon.json中设置"iptables": false(需自行接管全部端口转发,风险较高,一般不建议)。
2. 规则没生效时先看这几处
| 现象 | 排查方向 |
|---|---|
| 规则加了但端口还是不通 | 先 sudo ufw status verbose 确认规则在列;云服务器还要检查安全组/网络 ACL 是否放行 |
ufw enable 后 SSH 断连 | 未提前放行 SSH 端口,需通过控制台/救援模式进系统后补规则 |
ufw show allowed 报错 | 该子命令不存在,改用 ufw show added 或 ufw status verbose |
| 规则语法报参数错误 | 检查关键字顺序是否为 proto → from → to |
| 只放行了 tcp,udp 仍被挡 | allow 53 才会同时放行 tcp/udp,allow 53/tcp 只管 tcp |
| 删了规则编号对不上 | 每次删除后编号会重排,删一条就重新 status numbered |
小结
日常使用 ufw 记住三件事就够了:先放行 SSH 再 enable,避免把自己锁在门外;规则语法按 proto → from → to 的顺序写,端口跟在对应地址后面;删规则优先用 status numbered 加编号的方式,比原样重写规则可靠。另外如果机器上跑着 Docker,要意识到 ufw 管不住容器发布的端口,需要另外处理。
评论区