Skip to content
此頁面由 AI 翻譯,內容可能有疏漏。歡迎到 GitHub 協助改進。

連接埠敲門 ​

與 fwknop 相容的單封包授權(SPA,Single Packet Authorization):受保護的連接埠平時無法從外部連線,用戶端先傳送一個加密、帶 HMAC 認證且防重放的敲門封包,Gately 認證通過後,只為這個來源位址在限定時間內放行。常用於保護 SSH 直連:Web 終端機用不了的情境(scp、IDE 遠端開發、連接埠轉發)也能安全地從外網連線,掃描器與暴力破解看不到連接埠。

功能 ​

  • 相容 fwknop 用戶端:直接使用 fwknop 官方用戶端(Linux、macOS、WSL),金鑰格式與 fwknop -k 產生的 KEY_BASE64、HMAC_KEY_BASE64 相同,規則頁可一鍵產生用戶端命令與 ~/.fwknoprc 設定段;
  • 安全:封包以 AES-256-CBC 加密,先驗證 HMAC(SHA-256 / 384 / 512)再解密,金鑰不符的封包不會進入解密流程;每個封包只能使用一次(防重放),時間戳超出有效期(預設 120 秒)即拒絕;可限定使用者名稱、可要求封包寫明放行位址;
  • 防火牆攔截:受保護連接埠寫入系統防火牆(nftables,核心沒有 nf_tables 時使用 iptables + ipset),只放行敲門成功的位址,保護本機 sshd 等不經過 Gately 的服務;
  • Gately 入口依敲門放行:連接埠轉發、協定分流、STUN 內建轉發的規則,以及協定分流中的單條路由,可以選擇「需要敲門」,由 Gately 自己判斷,不需要防火牆權限,Windows、macOS、沒有 NET_ADMIN 的容器也能使用;
  • 只開一個連接埠:協定分流可以識別經 TCP 送來的敲門封包(fwknop -P tcp),同一個連接埠既接收敲門,又依敲門結果放行 SSH 等路由;
  • 與入侵防護聯動:被拒絕的敲門會發布「連接埠敲門被拒絕」事件,入侵防護內建「連接埠敲門失敗」範本可依次數封鎖來源;已被封鎖的位址送來的敲門直接丟棄;
  • 目前授權一覽(剩餘時間、可撤銷),敲門成功與被拒絕都記錄在執行日誌,可在通知中心訂閱。

快速開始:保護本機 SSH ​

  1. 開啟「連接埠敲門」,新增規則:連接埠填 tcp/22,開啟「防火牆攔截」,金鑰留空會自動產生;
  2. 在規則卡片上點「用戶端」,填寫伺服器的網域或公網 IP,複製命令列或 ~/.fwknoprc 設定段;
  3. 在用戶端安裝 fwknop:macOS brew install fwknop,Debian / Ubuntu apt install fwknop-client,Windows 在 WSL 中安裝;
  4. 敲門後 30 秒內連線 SSH:
bash
fwknop -n gately-ssh && ssh user@example.com

敲門封包預設送到 UDP 62201 連接埠。Gately 部署在路由器後面時,需要把 UDP 62201 與受保護連接埠一起轉發到 Gately 所在的主機;開啟「自動放行防火牆」後,本機防火牆(OpenWrt fw4、firewalld、ufw 等)會自動放行敲門連接埠,攔截生效後也放行受保護連接埠,能否連線只由敲門決定。

避免把自己鎖在外面

  • 預設開啟「內網免敲門」:私有位址、連結本機位址與本機網卡所在的公網 IPv6 網段(網卡前綴為 /64 或更短時按該前綴,雲端主機常見的 /124、/128 只包含本機自身)無需敲門,可以在設定中追加免敲門白名單。電信級 NAT 位址 100.64.0.0/10 不在其中:同一電信業者的其他使用者也使用這段位址;Tailscale 使用者可以把 100.64.0.0/10 加到免敲門白名單;
  • 開啟防火牆攔截時已建立的連線不受影響,授權到期後已建立的連線也照常保持;
  • Gately 正常停止時會刪除攔截規則;被強制結束(kill -9、docker rm -f)時規則會保留,直到 Gately 重新啟動。請確認能從內網或其他途徑登入這台機器。

規則 ​

欄位說明
連接埠用戶端可以請求放行的連接埠,如 tcp/22、udp/51820,最多 16 個。用戶端 -A 參數中的連接埠必須全部在此清單中,否則整個敲門被拒絕
防火牆攔截開啟後在系統防火牆中攔截這些連接埠,只放行敲門成功的位址;關閉時不更動防火牆,規則只供「需要敲門」的入口引用
加密金鑰 / HMAC 金鑰base64 編碼,留空自動產生(32 / 64 位元組,與 fwknop -k 相同),也可以填寫既有 fwknop 伺服器端的金鑰。複製規則會產生新金鑰;修改、停用或刪除規則會撤銷它產生的全部授權
HMAC 演算法SHA-256(fwknop 預設)、SHA-384、SHA-512,需與用戶端的 --hmac-digest-type 一致
放行時長敲門成功後可以建立新連線的時間,預設 30 秒
用戶端最長時長用戶端以 -f 請求更長時長時的上限(預設 300 秒),0 表示忽略用戶端請求的時長;請求比放行時長短時一律採用
限定使用者名稱只接受封包中使用者名稱為此值的敲門(fwknop 預設傳送本機登入名稱,可用 -U 指定)
要求寫明位址拒絕不帶位址的封包(fwknop -s),用戶端必須用 -R 或 -a 寫明放行位址

被連接埠轉發、協定分流或 STUN 引用的規則無法刪除,卡片上會列出引用方。

放行哪個位址 ​

  • -R(建議):用戶端先查詢自己的公網 IPv4 寫入封包,封包即使在途中被攔截,也無法用於其他位址;
  • -s:封包不帶位址,放行封包的來源位址。攔截封包的人有機會搶先從自己的位址重放,規則可開啟「要求寫明位址」拒絕這種封包;
  • -a 位址:放行指定的位址,例如替另一台裝置敲門。

fwknop 2.6 用戶端只能經 IPv4 傳送敲門封包、放行 IPv4 位址,伺服器需要能經 IPv4 存取;Gately 本身也接受經 IPv6 傳來的敲門封包,放行其來源位址。

全域設定 ​

  • UDP 敲門連接埠:預設 62201(fwknop 用戶端的預設連接埠);填 0 不監聽 UDP,只接收經協定分流送來的敲門。沒有啟用的規則時不監聽;
  • 自動放行防火牆:見上文;
  • 內網免敲門 / 免敲門白名單:只影響防火牆攔截;「需要敲門」的入口由各自的 IP 名單控制;
  • 封包有效期:封包時間戳與本機時間的最大偏差,預設 120 秒,用戶端與伺服器的時鐘都需要準確。

防火牆攔截 ​

環境防火牆攔截Gately 入口依敲門放行
Linux(root 或 CAP_NET_ADMIN,有 nftables)可用可用
Docker(host 網路 + cap_add: NET_ADMIN)可用,規則寫入主機可用
群暉 DSM 等沒有 nf_tables 的 Linux使用 iptables(legacy)+ ipset,官方 Docker 映像檔已內建可用
Windows、macOS、FreeBSD、沒有權限的 Linux無法使用,頁面頂部會給出原因可用

Gately 在 nftables 中建立獨立的 inet gately_knock 表,不更動系統既有的規則:prerouting 鏈(優先順序 -160,連線追蹤之後、目的位址轉換之前)把送往受保護連接埠的封包交給 gate 鏈,依序放行目標不是本機的流量(經本機轉發給其他裝置的連線不受影響)、回環介面、已建立的連線、TCP 中不是發起連線的封包、免敲門網段與敲門放行集合中的 位址 + 協定 + 連接埠,其餘丟棄。在 prerouting 判斷,因此對應到 Docker 容器的連接埠依對應前的連接埠攔截。放行寫入帶逾時的集合元素,到期由核心自動刪除。

沒有 nf_tables 時改用 iptables 的 mangle 表:PREROUTING 跳到 GATELY_KNOCK,每個受保護連接埠一個 ipset 集合(gkn4_tcp_22 等,帶逾時)。表或跳轉被防火牆重新載入、nft flush ruleset 等清除後 10 秒內自動重寫,並帶上仍然有效的放行。頁面上的「檢視防火牆規則」顯示目前寫入的規則。

經連接埠轉發進來的 SSH

經 Gately 連接埠轉發到本機 127.0.0.1:22 的連線來自回環介面,不受防火牆攔截。這種情況請在連接埠轉發規則上選擇「需要敲門」,或在防火牆攔截中保護對外的轉發連接埠。

注意

  • Docker 連接埠映射改寫來源位址:Gately 以橋接網路執行、敲門連接埠經 -p 62201:62201/udp 映射時,若 Docker 的 userland-proxy 處理了這個映射(例如經 IPv6、回送位址存取或關閉了 iptables 整合),Gately 看到的封包來源是 Docker 閘道位址,-s 封包放行的就是閘道位址,等於沒有放行真實用戶端,甚至可能放行經同一閘道轉發的所有連線。請讓 Gately 使用 host 網路(防火牆攔截本來也需要),或讓用戶端用 -R / -a 寫明放行位址,並開啟「要求寫明位址」;
  • 只攔截 SYN 的取捨:為了不切斷啟用前已建立、但還沒有被連線追蹤記錄的連線,TCP 只丟棄發起連線的 SYN 封包,不帶 SYN 的封包直接放行。理論上,開啟了 SYN cookie(net.ipv4.tcp_syncookies)的系統在 SYN 佇列溢位時,會接受一個能猜中 cookie 的裸 ACK 而建立連線;cookie 是用核心金鑰與時間計算出的 32 位元初始序號,實際幾乎不可能猜中;對安全要求極高的場景可以關閉 SYN cookie(sysctl net.ipv4.tcp_syncookies=0)。

Gately 入口依敲門放行 ​

連接埠轉發、協定分流與 STUN(內建轉發)的「IP 存取控制」中可以選擇一條敲門規則作為「需要敲門」:來源位址必須持有該規則未到期的授權才能建立新連線(UDP 在建立新工作階段時判斷:授權到期後 WireGuard 等既有工作階段照常轉發,與防火牆攔截保持已建立連線一致;白名單 / 黑名單仍逐封包判斷),其餘連線直接中斷;與白名單 / 黑名單同時設定時兩者都要滿足。敲門規則可以關閉「防火牆攔截」,只供這些入口使用。

協定分流還可以在單條路由上選擇「需要敲門」,例如 443 連接埠上 HTTPS 路由對所有人開放,SSH 路由只對敲門成功的位址開放。

只開放一個連接埠 ​

在協定分流規則中新增一條「連接埠敲門」路由(協定 spa),用戶端以 TCP 把敲門封包送到同一個連接埠:

bash
fwknop -A tcp/443 -P tcp -p 443 -R -D example.com --use-hmac \
  --key-base64-rijndael <加密金鑰> --key-base64-hmac <HMAC 金鑰>
ssh -p 443 user@example.com
  • 敲門路由把封包交給連接埠敲門模組,不轉發、不回覆;-A 中的連接埠需要在敲門規則的連接埠清單中(例如 tcp/443);
  • 整條規則要求敲門時,沒敲門的來源只能使用敲門路由,敲門後才能使用其他路由與預設目標;
  • 只有規則中有敲門路由時才識別敲門封包,不影響其他規則的協定識別;
  • 敲門規則的 UDP 連接埠可以設為 0,對外只開放協定分流的連接埠;
  • 帶敲門路由的協定分流連接埠與 UDP 敲門連接埠不能出現在開啟防火牆攔截的規則中(儲存、啟用時檢查;攔截後敲門封包本身無法送達),產生防火牆規則時也會自動排除這些連接埠。

與入侵防護聯動 ​

被拒絕的敲門會發布「連接埠敲門被拒絕」事件(欄位 via 為 udp 或 tcp),同一來源每 5 秒最多一次。UDP 封包的來源位址可以偽造,為了不讓攻擊者借入侵防護封鎖任意 IP,經 UDP 傳來、HMAC 認證失敗的封包只計數、不發布事件;通過 HMAC 認證(出自持有金鑰的用戶端)但被規則拒絕的(解密失敗、重放、過期、請求未授權連接埠、使用者名稱不符等)才發布。經協定分流 TCP 連接埠傳來的封包來源經過握手,無法偽造,HMAC 不符也會發布。在入侵防護中用「連接埠敲門失敗」範本建立規則(預設 10 分鐘內 5 次即封鎖 1 天),持續傳送偽造封包的來源會被封鎖,被封鎖位址的敲門直接丟棄。非敲門格式的資料(連接埠掃描、其他協定)只計數、不發布事件。

認證前先按來源網段限速(IPv4 每個 /24、IPv6 每個 /64 每秒最多 10 個封包),再受全域每秒 200 個的上限約束,超出的直接丟棄:偽造封包洪水不會占滿 CPU,單一來源的洪水也不會擠掉其他來源的正常敲門。HMAC 認證失敗的封包不逐條記錄日誌,每分鐘彙總為一條「N 個來源的 M 個無效敲門封包」。

限制 ​

  • 只支援 fwknop 的 Rijndael(AES)CBC 模式加 HMAC,不支援 GnuPG、舊版 IV 模式與不帶 HMAC 的封包;
  • 不執行命令訊息(fwknop -C),不支援 NAT 存取請求(-N);
  • 敲門授權儲存在記憶體中,Gately 重新啟動後需要重新敲門(已建立的連線不受影響)。防重放紀錄同樣只在記憶體中,因此時間戳早於本次啟動的封包在重啟後一律拒絕;用戶端時鐘比伺服器慢時,重啟後頭幾秒的敲門可能被拒絕,再敲一次即可。

以 Apache-2.0 授權條款開源發布。