ufw规则损坏导致SSH被锁定怎么恢复
被 ufw 锁在 VPS 外?通过服务商控制台或救援模式停用防火墙,检查实际生效规则,并确认 sshd 端口,避免重启后再次加载错误规则。
先恢复访问
如果 ufw 已将您锁定在 VPS 外,恢复访问的方式是使用服务商控制台或救援模式,因为阻断规则生效后,无法通过 SSH 修复。数据包会在 sshd 看到之前由内核丢弃,因此没有可登录的服务,也无法通过网络进行修复。打开服务商控制面板中的控制台,在提示符处登录,然后运行一条命令。
sudo ufw disable您应看到 Firewall stopped and disabled on system startup。新的 SSH 连接会在 1 到 2 秒内恢复。您配置的内容不会丢失:disable 会从内核卸载规则,并将 ENABLED=no 写入 /etc/ufw/ufw.conf;您的规则仍保存在磁盘上的 /etc/ufw/user.rules 中,等待下一次 ufw enable。
不要重启后碰运气。ufw 会在启动时自动运行,因此 ENABLED=yes 表示同一套规则会在网络启动前再次加载。重启不会改变 ufw 锁定您的状态。
控制台需要一个您可能尚未设置的密码
Web 控制台(VNC 或串行控制台)相当于连接到计算机的键盘。它不是网络路径,因此防火墙规则无法阻止它。但它需要本地登录,这正是仅使用密钥的配置会失败的地方:如果您从未为 sudo 用户设置密码,并且 root 登录已锁定,控制台会显示一个您无法回答的提示符。现在趁 SSH 仍可用,设置该密码:sudo passwd yourname。大多数面板也可以重置 root 密码,这通常会强制重启。
如果控制台无法使用,请启动服务提供商的救援系统。该系统运行在独立的操作系统中,您的磁盘处于未挂载状态,因此您可以从外部关闭 ufw。
lsblk
sudo mount /dev/vda1 /mnt
sudo sed -i 's/^ENABLED=yes/ENABLED=no/' /mnt/etc/ufw/ufw.conf
sudo umount /mnt先运行 lsblk,因为根分区不一定是 /dev/vda1。重新启动进入正常系统后,ufw 仍会保持关闭状态,直到您手动启用它。
最小恢复流程
按此顺序操作。前4步是安全的。之后的步骤不是。
- 使用
sudo ufw disable卸载规则,恢复访问权限。 - 使用
sudo ufw show added打印已添加的规则,输出格式为添加这些规则时使用的命令。ufw 处于非活动状态时也可以执行此命令,而ufw status不支持这种用法。 - 使用
sudo sshd -T | grep -i '^port'确认 sshd 实际监听的端口。除非您修改过端口,否则该命令会输出port 22。 - 使用真实端口执行
sudo ufw allow 22/tcp,这样下次启用时不会再次导致访问锁定。 - 使用
sudo ufw enable,但必须先安排回滚。具体方法见本页后文。
ufw reset 的实际作用
ufw reset 是最后手段,不应作为第一步。它会禁用防火墙,备份所有规则文件,并将默认策略恢复为拒绝入站、允许出站。执行时会为每个文件输出一行备份信息:
Backing up 'user.rules' to '/etc/ufw/user.rules.20260813_101500'重置后不会保留任何允许规则。因此,应从控制台执行,而不要通过 SSH 执行;重新启用防火墙前,先添加 SSH 规则。这些备份文件是纯文本。sudo grep -n dport /etc/ufw/user.rules.20260813_101500 可显示旧规则的内容,您可以据此重建原本不打算丢弃的规则集。
ufw 保存规则的位置
读取文件比凭记忆猜测更可靠。以下 5 个路径保存了完整状态:
/etc/ufw/user.rules和/etc/ufw/user6.rules:您添加的规则,按评估顺序排列。/etc/ufw/before.rules和/etc/ufw/after.rules,以及对应的6变体:ufw 包装在您规则外部的框架,包括允许已建立连接的规则和回环规则。/etc/default/ufw:默认策略和IPV6开关。/etc/ufw/ufw.conf:ENABLED和日志级别。/var/log/ufw.log:启用日志记录后,被阻止的内容。
ufw 在重写文件前会先创建带时间戳的副本,因此 ls /etc/ufw/ 中会积累类似 user.rules.20260813_101500 的文件名。这就是撤销历史。在开始回滚更改前,建议先查看这些文件。
要查看内核中已加载的规则,而不是磁盘上的规则,请使用 sudo ufw show raw,或使用 sudo iptables -S 和 sudo ip6tables -S。在 Ubuntu 22.04 和 24.04 中,这些命令使用 nft 后端,因此 sudo nft list ruleset 会以较新的语法输出相同的规则。
启用 ufw 后为什么 SSH 会话会中断?
默认的入站策略是 deny。在没有为 SSH 端口配置规则时启用 ufw,会阻断所有新的连接。ufw 会发出警告:Command may disrupt existing ssh connections. Proceed with operation (y|n)? 在未配置 SSH allow 规则的情况下回答 y,是本页所述问题最常见的原因。
容易误判的地方在于延迟。/etc/ufw/before.rules 会在应用您自己的规则之前接受状态为 ESTABLISHED、RELATED 的数据包,因此,您执行该命令时所在的会话通常仍能正常工作。阻断只会在下一次连接时出现,而这可能要过几小时;到那时,防火墙变更看起来已经与问题无关。关闭第一个 SSH 会话前,务必打开第二个 SSH 会话并确认其可用。
为什么策略更改后 apt 和 DNS 停止工作?
sudo ufw default deny outgoing 会阻止出站 DNS(域名系统)查询和出站 HTTP,因此名称解析失效,软件包更新也会停止。apt update 报告 Temporary failure resolving 'archive.ubuntu.com'。入站 SSH 仍然可用,因为 SSH 的响应属于 ESTABLISHED 流量,会通过框架规则。这会让人误以为防火墙没有问题,但实际原因正是防火墙。
如果要使用拒绝出站流量的策略,应放行机器实际需要的流量:
sudo ufw allow out 53
sudo ufw allow out 80/tcp
sudo ufw allow out 443/tcp
sudo ufw allow out 123/udp如果没有最后一条规则,系统时钟会逐渐产生偏差。时钟错误会导致 TLS(传输层安全)证书验证失败,因此 curl 开始因日期而不是端口失败。此症状会在策略更改数天后出现。因此,拒绝出站流量的策略适用于需要持续监控的机器,不适用于只进行一次配置的主机。
为什么我的 ufw 规则始终不匹配?
ufw 按顺序评估用户规则,并在首次匹配后停止。添加在宽泛 allow 之后的 deny 永远不会生效,因为前面的允许规则已经决定了如何处理数据包。使用带编号的方式输出规则顺序,然后插入到所需位置。
sudo ufw status numbered
sudo ufw insert 1 deny from 203.0.113.10 to any port 22
sudo ufw delete 4sudo ufw --dry-run allow 8080/tcp 会输出将要写入的规则,但不会进行任何更改。这是让规则正式生效前安全查看规则的方式。
应用程序配置文件中还存在一个容易忽略的问题。sudo ufw allow OpenSSH 使用 /etc/ufw/applications.d/openssh-server 中的配置文件,而该配置文件表示端口 22。如果 sshd 监听 2222,规则就会放行一个没有任何进程使用的端口,并使您因规则集看似正确而被锁在服务器外。端口变更后,请直接使用端口号。其余语法请参阅 VPS 的 ufw 防火墙基础知识。
为什么 IPv4 规则无法解释实际看到的现象?
因为其中一半流量并非 IPv4。Ubuntu 在 /etc/default/ufw 中提供 IPV6=yes,ufw 随后会在 /etc/ufw/user6.rules 中维护一套并行的 IPv6 规则。使用 IPv4 地址编写的规则,例如 ufw allow from 203.0.113.10 to any port 22,完全不会创建 IPv6 规则。如果您的 VPS 配置了 AAAA 记录,客户端会优先使用 IPv6,而连接超时;此时 ufw status 显示的规则看起来却是正确的。使用 ssh -4 user@host 对比 ssh -6 user@host,即可测试两者的差异。如果前者成功而后者失败,问题就在 IPv6 规则集中。
反过来的情况对安全性的影响更严重。使用 IPV6=no 时,ufw 完全不会管理 ip6tables,因此 IPv6 策略会保持内核默认值 ACCEPT。您认为已关闭的端口仍会通过 IPv6 地址响应,并且任何 ufw 命令都不会显示该端口。使用 sudo ip6tables -S 和 ss -tlnp 检查,并阅读ufw 如何处理 IPv6 端口,了解完整情况。
为什么 ufw 拒绝 Docker 端口后,该端口仍处于开放状态?
Docker 会将 DNAT(目标网络地址转换)规则写入 nat 表,并将自己的链插入 FORWARD。ufw 的规则位于 INPUT 路径中。发往容器的流量会被转发,而不是交付给主机,因此不会到达包含拒绝规则的链。即使 ufw 已启用并拒绝所有流量,docker run -p 5432:5432 仍可从互联网访问。
sudo iptables -t nat -S DOCKER最简单的解决方法是绑定到回环地址:-p 127.0.0.1:5432:5432 会将主机端绑定到 127.0.0.1,无论 ufw 如何配置,外部都无法访问它。如果服务确实需要公开访问,请参阅 绕过 ufw 发布 Docker 端口,其中介绍了相应情况。
在应用规则前安排回滚
这是让防火墙操作可恢复的习惯。在执行任何高风险更改前,先安排撤销操作。如果更改导致您失去连接,机器会在五分钟后自动恢复,您无需打开控制台。
sudo systemd-run --on-active=5m --unit=ufw-rollback /usr/sbin/ufw disablesystemd 会输出 Running timer as unit: ufw-rollback.timer。现在执行更改。如果之后仍能打开新的 SSH 会话,请取消回滚:
sudo systemctl stop ufw-rollback.timer如果无法打开该会话,请等待。ufw 会自行停止,您下次尝试时即可连接。对于 ufw,经典的 shutdown -r +5 技巧不起作用,因为 ufw 在启动时会再次加载同一规则集。
保留第二种登录途径
- 提前登录一次服务商控制台,并确认密码可用。未经过测试的控制台不能作为备用途径。
- 保留一个使用独立密钥的第二 sudo 用户,这样即使一个
authorized_keys文件损坏,也不会完全失去访问权限。 - 确认服务商是否在控制面板中运行独立于 ufw 的网络防火墙。它会阻止相同的端口,而
ufw status永远不会提到它。 - 如果该地址是动态地址,不要将
ufw allow from <your home address>设为唯一的 SSH 规则。服务商可能在夜间更换该地址,届时您将无法登录。
最适合完成这些操作的时间是新服务器刚创建时,与 新 VPS 的前十分钟中的其他初始化工作一起进行。
“拒绝连接”或“超时”可判断发生故障的层
Connection refused表示数据包已到达服务器,并且某个进程返回了 TCP 重置。网络路径正常,因此 sshd 已停止,或正在监听其他端口。防火墙通常不是原因,因为 ufw 默认会丢弃数据包,而不是拒绝连接。
Connection timed out表示完全没有收到响应。这是数据包被丢弃的特征,原因可能是 ufw、服务商网络防火墙或地址错误。正确理解这两类错误可以节省一小时的排查时间,“拒绝连接”和“连接超时”的区别可帮助处理其余情况。
在进行下一项更改前启用日志记录
sudo ufw logging on
sudo tail -f /var/log/ufw.log被阻止的数据包显示如下:
[UFW BLOCK] IN=eth0 OUT= SRC=203.0.113.10 DST=192.0.2.5 LEN=60 PROTO=TCP SPT=51234 DPT=22 WINDOW=64240 SYNDPT=22 中的自有地址出现在 SRC=,这证明阻止连接的是 ufw,而不是网络或 sshd。在没有 rsyslog 的精简镜像中,不会有 /var/log/ufw.log,相同的日志行会来自 sudo journalctl -k | grep UFW。ufw 会限制自身日志规则的记录速率,因此缺少日志行不能证明数据包已被允许。
如果发现了您从未添加过的规则
自行发生变化的规则集不是防火墙问题,而是有人使用 root 写入了这些规则。运行 sudo grep ufw /var/log/auth.log,查看执行过哪些 sudo 命令以及使用的是哪个账户;然后运行 last,查看该时间戳附近的登录记录。如果这些账户与您认识的任何人都不匹配,请停止调试防火墙,改为按照 VPS 被入侵检查清单逐项排查。在他人控制的服务器上重新启用防火墙,只会掩盖问题。
重新启用防火墙
确定原因后,以不会再次导致锁定的方式重新启用 ufw。放行实际使用的 SSH 端口,安排回滚,启用 ufw,然后从另一个终端打开全新的 SSH 会话并确认可以连接。只有在新会话成功建立后,才能关闭当前正在使用的会话。保持日志记录一整天,因为查看日志比阅读 user.rules 更快发现遗漏的放行规则。
FAQ
ufw disable 会删除我的规则吗?
不会。disable 会从内核卸载规则集,并将 ENABLED=no 写入 /etc/ufw/ufw.conf。您的规则仍保存在 /etc/ufw/user.rules 和 /etc/ufw/user6.rules 中;防火墙未启用时,sudo ufw show added 会列出这些规则。ufw reset 才是清除规则的命令,并且会先备份每个文件,同时输出类似 Backing up 'user.rules' to '/etc/ufw/user.rules.20260813_101500' 的行。
重启 VPS 会解除 ufw 导致的锁定吗?
不会。ufw 会在启动时从 /etc/ufw/ufw.conf 中的 ENABLED=yes 启动,因此相同的规则会在网络启动前加载,您仍会再次被锁定在服务器外。只有在您关闭 ufw 后,或在救援模式下挂载磁盘并编辑该文件后,重启才有帮助。请使用服务商控制台,并在那里运行 sudo ufw disable。
为什么 ufw 拒绝了端口,但仍可访问我的 Docker 容器?
Docker 会为每个发布的端口写入自己的 DNAT 和 FORWARD 规则。流量会被转发到容器,而不是交付给主机,因此不会经过包含 ufw 拒绝规则的 INPUT 链。若端口仅供主机使用,请使用 -p 127.0.0.1:5432:5432 绑定到 loopback;使用 sudo iptables -t nat -S DOCKER 查看 Docker 安装了哪些规则。
我没有控制台密码,也没有救援模式。有哪些选项?
剩余选项取决于您的服务商:从控制面板重置密码(通常会重启服务器),或将磁盘挂载到另一台实例,以便在那里编辑 /etc/ufw/ufw.conf。重建服务器前请先联系支持团队,因为重建会销毁服务器上的数据。恢复登录后,运行 sudo passwd yourname,并测试一次控制台登录,确保下次被锁定时只需花费 2 分钟即可恢复。