SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

ufw 規則損壞無法 SSH?恢復存取與修復方法

被 ufw 鎖在 VPS 外?透過服務商主控台停用防火牆,讀取實際生效規則,確認 sshd 連接埠,避免重新啟用後再次失去 SSH 存取。

先恢復存取

如果 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 或 serial)相當於連接至機器的鍵盤。它不是網路路徑,因此任何防火牆規則都無法封鎖它。但它需要本機登入,這正是僅使用 cryptographic key 的設定會失敗的地方:如果您從未為 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,因為 root 分割區不一定是 /dev/vda1。重新開機進入一般系統後,ufw 仍會保持關閉,直到您手動啟用它。

最小復原流程

請依此順序操作。前4個步驟是安全的。後續步驟則不是。

  1. sudo ufw disable,卸載規則並恢復存取權。
  2. sudo ufw show added,以新增這些規則時所用的命令格式,列出您新增的規則。ufw 停用時仍可使用此命令,但 ufw status 無法使用。
  3. sudo sshd -T | grep -i '^port',確認 sshd 實際監聽的連接埠。除非您已變更設定,否則會顯示 port 22
  4. sudo ufw allow 22/tcp,使用您實際採用的連接埠,避免下一次啟用時再次鎖定自己。
  5. 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 包裝在您規則外層的框架,包括允許已建立連線的規則與 loopback 規則。
  • /etc/default/ufw:預設政策與 IPV6 開關。
  • /etc/ufw/ufw.confENABLED 與日誌層級。
  • /var/log/ufw.log:啟用日誌後遭封鎖的項目。

ufw 在重新寫入檔案前,會先建立含時間戳記的副本,因此 ls /etc/ufw/ 會累積如 user.rules.20260813_101500 的檔名。這些檔案就是復原歷程;開始還原設定前,應先讀取這些檔案。

若要查看已載入 kernel 的規則,而不是磁碟上的內容,請使用 sudo ufw show raw,或使用 sudo iptables -Ssudo ip6tables -S。在 Ubuntu 22.04 和 24.04 中,這些命令使用 nft 作為後端,因此 sudo nft list ruleset 會以較新的語法輸出相同規則。

為什麼啟用 ufw 後 SSH 工作階段會中斷?

預設的輸入流量政策是拒絕。若啟用 ufw 時沒有為 SSH 埠設定規則,所有新的連線都會被切斷。ufw 會發出警告:在未設定 SSH 允許規則的情況下回答 Command may disrupt existing ssh connections. Proceed with operation (y|n)? 是最常見的原因。y

容易混淆的地方在於延遲。/etc/ufw/before.rules 會在套用自訂規則前,接受狀態為 ESTABLISHED、RELATED 的封包,因此你輸入該指令時所使用的工作階段仍會正常運作。封鎖只會在下一次連線時出現,而這可能已經是數小時後;屆時防火牆變更看起來就不再相關。請務必先開啟第二個 SSH 工作階段並確認連線正常,再關閉第一個工作階段。

apt 與 DNS 在變更政策後為何停止運作?

sudo ufw default deny outgoing 會封鎖對外 DNS(domain name system)查詢與對外 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(transport layer security)憑證驗證失敗,因此 curl 會開始因日期而非連接埠發生錯誤。這項症狀會在變更後數天才出現,因此拒絕對外流量的政策適用於持續監控的機器,不適合只設定一次後便不再管理的主機。

為什麼我的 ufw 規則永遠不會比對成功?

ufw 會依序評估使用者規則,並在首次比對成功後停止。將 deny 加在範圍較廣的 allow 之後,永遠不會套用,因為前一條 allow 規則已決定封包的處理方式。請先列印規則編號,再插入所需的位置。

sudo ufw status numbered
sudo ufw insert 1 deny from 203.0.113.10 to any port 22
sudo ufw delete 4

sudo ufw --dry-run allow 8080/tcp 會列印即將寫入的規則,但不會進行任何變更。這是讓規則正式生效前安全查看規則的方式。

應用程式設定檔還有另一個容易踩到的問題。sudo ufw allow OpenSSH 會使用 /etc/ufw/applications.d/openssh-server 中的設定檔,而該設定檔代表 port 22。如果 sshd 監聽 2222,規則會開放沒有任何服務使用的 port,並讓你在看似正確的規則集下失去連線。移動 port 後,請改用實際的 port number。其餘語法請參閱 VPS 的 ufw 防火牆基礎

為什麼 IPv4 規則無法解釋我看到的結果?

因為其中一半的網路流量不是 IPv4。Ubuntu 會在 IPV6=yes 中啟用 /etc/default/ufw,而 ufw 會在 /etc/ufw/user6.rules 中維護平行的 v6 規則集。使用 IPv4 位址撰寫的規則,例如 ufw allow from 203.0.113.10 to any port 22,完全不會建立 v6 規則。如果您的 VPS 有 AAAA 記錄,客戶端會優先使用 IPv6,導致連線逾時;此時 ufw status 顯示的規則看起來雖然正確。使用 ssh -4 user@hostssh -6 user@host 測試兩者的差異。如果前者可用、後者不可用,問題就在 v6 規則集。

反向情況對安全性更不利。使用 IPV6=no 時,ufw 完全不管理 ip6tables,因此 v6 政策會維持核心預設的 ACCEPT。一個您以為已關閉的連接埠,仍會透過其 IPv6 位址回應,而且任何 ufw 指令都不會顯示這項設定。使用 sudo ip6tables -Sss -tlnp 檢查,並閱讀 ufw 如何處理 IPv6 連接埠,以了解完整情況。

為什麼 ufw 拒絕連線時,Docker 的連接埠仍然開放?

Docker 會將 DNAT(目的地網路位址轉譯)規則寫入 nat 表,並將自有鏈結插入 FORWARD。ufw 的規則位於 INPUT 路徑。前往容器的流量會被轉送,而不是傳送至主機,因此不會到達包含拒絕規則的鏈結。啟用 ufw 且拒絕所有流量時,docker run -p 5432:5432 仍可從網際網路存取。

sudo iptables -t nat -S DOCKER

最簡單的修正方式是繫結至 loopback:-p 127.0.0.1:5432:5432 會將主機端繫結至 127.0.0.1,因此無論 ufw 的設定為何,外部都無法存取。若服務確實需要公開,請參閱 Docker 透過 ufw 發布連接埠,了解相關情況。

在套用規則前排程回復

這是讓防火牆操作可安全執行的習慣。在進行任何具風險的變更前,先排程復原動作。如果變更導致您無法登入,系統會在 5 分鐘後自行復原,您不必開啟主控台。

sudo systemd-run --on-active=5m --unit=ufw-rollback /usr/sbin/ufw disable

systemd 會輸出 Running timer as unit: ufw-rollback.timer。現在進行變更。如果之後仍能開啟新的 SSH 工作階段,請取消回復排程:

sudo systemctl stop ufw-rollback.timer

如果無法開啟該工作階段,請稍候。ufw 會自行停止,之後再次嘗試即可建立連線。經典的 shutdown -r +5 技巧無法搭配 ufw 使用,因為 ufw 在開機時會再次載入相同的規則集。

保留第二種登入方式

  • 先登入一次供應商的主控台,確認密碼可用。從未測試過的主控台不算備援。
  • 保留另一個具備 sudo 權限的使用者,並為其設定獨立的 key,避免單一 authorized_keys 檔案損壞後完全失去存取權。
  • 確認供應商是否在管理面板中提供獨立於 ufw 的網路防火牆。它會封鎖相同的連接埠,而 ufw status 永遠不會提到它。
  • 如果該位址是動態的,不要將 ufw allow from <your home address> 設為唯一的 SSH 規則。供應商可能在夜間變更該位址,導致你無法登入。

在新伺服器上進行這些設定的成本最低,並可與 新 VPS 的前十分鐘 其他設定工作一併完成。

拒絕連線或逾時可指出發生故障的層

Connection refused 表示封包已抵達伺服器,且某個元件回傳了 TCP reset。網路路徑正常,因此 sshd 可能已停止,或正在監聽其他連接埠。防火牆通常不是原因,因為 ufw 預設會丟棄封包,而不是拒絕連線。

Connection timed out 表示完全沒有收到回應。這是封包遭丟棄的特徵,原因可能是 ufw、供應商的網路防火牆,或位址錯誤。正確解讀這兩個錯誤可省下 1 小時的猜測時間,而connection refused 與 timed out 的差異可協助排除其餘情況。

在進行下一項變更前先啟用日誌記錄

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 SYN

DPT=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 deny 規則所在的 INPUT chain。若連接埠只供主機使用,請搭配 -p 127.0.0.1:5432:5432 發佈到 loopback,並使用 sudo iptables -t nat -S DOCKER 檢查 Docker 安裝了哪些規則。

我沒有主控台密碼,也沒有救援模式。有哪些選項?

剩餘選項取決於您的供應商:從控制面板重設密碼,但通常會重新啟動伺服器;或將磁碟掛載到另一個 instance,以便從該處編輯 /etc/ufw/ufw.conf。重新建置伺服器前,請先詢問支援人員,因為重新建置會刪除其中的資料。重新登入後,執行 sudo passwd yourname,並測試一次主控台登入,這樣下次遭到鎖定時,只需花費兩分鐘即可恢復。

#ufw#firewall#lockout#console#recovery