裝了 Tailscale 之後,本來就能透過 tailnet 連到機器上的 sshd,但還是得自己發公鑰、維護 authorized_keys、有人離開時一台台把金鑰清掉。Tailscale SSH 把這件事交給 Tailscale:誰能以哪個帳號 SSH 到哪台機器,寫在 tailnet 的 policy 裡,身分就是登入 Tailscale 的帳號,不需要另外管理 SSH 金鑰。所有方案都能使用。
本文依 2026 年 10 月的 Tailscale 官方文件整理,CLI 範例以 Tailscale v1.102 為準。
和「透過 tailnet 連 sshd」差在哪
| 透過 tailnet 連一般的 sshd | Tailscale SSH | |
|---|---|---|
| SSH 伺服器 | 機器上的 OpenSSH sshd |
tailscaled 內建的 SSH 伺服器 |
| 身分驗證 | SSH 金鑰或密碼 | Tailscale 的 node key(也就是你登入的帳號) |
| 誰能連 | ACL 管網路層,authorized_keys 管登入 |
policy 的 ssh 規則一起管 |
| 收回權限 | 要到每台機器刪金鑰 | 改 policy 存檔,幾秒內生效,連既有連線都會中斷 |
| 進階功能 | — | check 模式(定期重新驗證)、網頁 SSH console |
運作方式:在目的機器開啟 Tailscale SSH 後,tailscaled 會接管 Tailscale IP 上的 22 埠,也就是只攔截從 tailnet 進來的 SSH 連線。連線先經 WireGuard 用 node key 驗證與加密,到了 SSH 協定的驗證階段,伺服器已經知道對方是誰,就直接放行(SSH 驗證類型為 none),不再要求金鑰或密碼。
/etc/ssh/sshd_config 與 ~/.ssh/authorized_keys 都不會被修改,所以從區網 IP 或公網連到原本 sshd 的連線照常運作,兩者可以並存。
支援的平台
- 可以當伺服器(被連):Linux,以及 macOS 的開源
tailscaled版。需要 Tailscale v1.24 以上。 - 不能當伺服器:macOS 的 App Store 版與 Standalone 版(差異見 macOS 上安裝 Tailscale 的三種方法)、Windows、Synology、QNAP。
- 可以當用戶端(去連):任何裝了 Tailscale 的裝置都可以。
啟用
1. 在目的機器開啟
sudo tailscale set --ssh這會產生一組 SSH host key,把公鑰交給 Tailscale 發給其他裝置,並讓 tailscaled 開始攔截 tailnet 進來的 22 埠流量。每台機器只要做一次。
注意:執行後,原本經由這台機器 Tailscale IP 連進來的 SSH 連線會卡住。如果你現在就是透過 Tailscale IP SSH 進去操作,先準備好其他連線方式,或執行完重新連線。
2. 確認 policy 允許
一條 Tailscale SSH 連線要同時通過兩種規則:
- 網路層:
grants(或舊的acls)允許來源連到目的機器的 22 埠。 - SSH 規則:
ssh區段允許來源以指定的本機帳號 SSH 到目的機器。
沒改過 policy 的 tailnet,預設 policy 已經包含兩者,開啟後就能連自己的裝置。改過 policy 的話,兩種規則都要自己寫,語法基礎見 ACL / Grants 入門。
policy 的 ssh 規則
預設規則
"ssh": [
{
// 每個人都能用 Tailscale SSH 連自己的裝置,check 模式,root 或非 root 都可以
"action": "check",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot", "root"],
},
],修改 ssh 區段會取代這條預設規則;整段刪掉則等於在 tailnet 停用 Tailscale SSH。
欄位
| 欄位 | 說明 |
|---|---|
action |
accept:已登入 tailnet 就放行;check:要定期重新驗證身分 |
src |
從哪裡連:使用者、群組、tag、user:*@<網域>、autogroup:。不能寫 * |
dst |
連到哪裡:使用者、tag、autogroup:。不能寫 *,也不能指定連接埠(固定 22) |
users |
允許登入的本機帳號,例如 root、ubuntu;autogroup:nonroot 代表任何非 root 帳號 |
checkPeriod |
只用於 check,多久要重新驗證一次,預設 12 小時(自訂限 Premium、Enterprise 方案) |
acceptEnv |
允許用戶端用 SendEnv/SetEnv 傳入的環境變數名稱,可用 *、?(主機需 v1.76.0 以上) |
users 只能使用機器上已經存在的帳號,Tailscale 不會自動建立帳號。另外有 localpart:*@<網域>:登入帳號是 dave@example.com 的人,就以本機的 dave 登入;網域不能是 gmail.com 這類多人共用的網域。
只允許這幾種連線
不管 policy 怎麼寫,Tailscale SSH 只允許:
- 使用者連到自己的裝置。
- 使用者連到 tag 裝置(包含別人分享給你的 tag 裝置)。
- tag 裝置連到 tag 裝置(這種規則不能用 check 模式)。
換句話說,不能 SSH 到別人以使用者身分登入的裝置,tag 裝置也不能 SSH 到使用者的裝置。要讓多人共同管理的伺服器,應該讓它用 tag 身分登入。
範例:tag 伺服器
讓 group:admins 以 root 或 ubuntu 登入 tag:server 的機器,以 root 登入時需要每小時重新驗證(自訂 checkPeriod 需要 Premium 或 Enterprise 方案,其他方案拿掉這一行即使用預設的 12 小時):
{
"groups": {
"group:admins": ["alice@example.com", "bob@example.com"]
},
"tagOwners": {
"tag:server": ["group:admins"]
},
"grants": [
{
"src": ["group:admins"],
"dst": ["tag:server"],
"ip": ["22"]
}
],
"ssh": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server"],
"users": ["ubuntu"]
},
{
"action": "check",
"checkPeriod": "1h",
"src": ["group:admins"],
"dst": ["tag:server"],
"users": ["root"]
}
]
}把預設規則的 dst 從 autogroup:self 改成 tag 時,記得檢查 users:保留 autogroup:nonroot 的話,src 裡的每個人都能以那台機器上任何非 root 帳號登入。
規則重疊時
同一條連線同時符合 check 與 accept 規則時,check 優先,而且只看 check 規則裡的 users。上面的範例把 ubuntu 與 root 分在兩條規則,就是為了避免這個問題。
policy 也可以寫 sshTests 來驗證規則是否如預期。
check 模式
action 設為 check 時,連線前要先在瀏覽器重新登入身分提供者(Google、GitHub、Microsoft 等),會一併觸發多因素驗證。
checkPeriod預設 12 小時。Premium 與 Enterprise 方案可以自訂(見 方案與限制比較),範圍是 1 分鐘到 168 小時(一週),單位用分鐘或小時,例如"30m"、"20h"。- 也可以設
"always",每次連線都要驗證。但 Ansible 這類短時間開很多連線的工具會因此出問題。 - 驗證一次之後,在預設的 12 小時內連 tailnet 其他走 check 模式的機器也不用再驗證;有自訂
checkPeriod的規則,則依它自己的期限判斷。 - check 模式只用於 Tailscale SSH,一般的 SSH 或其他 TCP 連線無法使用。
連線方式
一般的 ssh
不需要額外的程式或設定,直接用 MagicDNS 名稱或 Tailscale IP:
ssh my-server
ssh ubuntu@my-server
ssh ubuntu@100.64.0.1Tailscale 會自動處理 known_hosts,第一次連線不會跳出 unknown host 的警告。scp、sftp 也能用。只能用 Tailscale IP 或 MagicDNS 名稱連,用機器的區網 IP 連到的是原本的 sshd。
有些 SSH 用戶端不接受「不需驗證」的伺服器,這時在使用者名稱後加上 +password(例如 ubuntu+password),密碼隨便輸入即可。
tailscale ssh
tailscale ssh ubuntu@my-server這是系統 ssh 的包裝,不是必要的。它會用 MagicDNS 解析名稱(即使關掉了 --accept-dns)、在 userspace networking 模式下也能用,並用 Tailscale 發的 host key 核對對方。macOS 的 App Store 版沒有這個指令,直接用 ssh 即可。
網頁 SSH console
在 Admin console 的 Machines 頁面,點機器右邊的選單選 SSH to machine,選擇本機帳號後會在瀏覽器開一個 SSH 視窗。適合手邊的裝置沒裝 Tailscale 的時候。
- 目前是 beta,所有方案都能使用,但只有 Owner、Admin、IT admin、Network admin 能用。
- 每個新的 console session 都要重新驗證身分。
- 瀏覽器會以 WebAssembly 跑一個 Tailscale 用戶端,在 tailnet 裡成為一台暫時(ephemeral)的節點,名稱像
tailscale-ssh-console-alice-example-com-xxxxx,關掉後自動移除。 - 連線全程經過 DERP relay,仍是端對端加密。
看不到 SSH 選項,代表那台機器沒開 Tailscale SSH,或 policy 不允許你連。完整的運作原理與安全限制見 Tailscale SSH 工作階段錄影與瀏覽器 SSH。
Session recording
Tailscale 曾提供把 Tailscale SSH session 錄下來、串流到 tailnet 內錄影節點(tsrecorder)的功能。官方已不再提供這個做法給新使用者,既有使用者的支援預計在 2027 年 8 月結束,之後改由 Tailscale PAM 提供 session 紀錄與特權存取管理。個人使用通常用不到,有稽核需求再參考官方文件。運作原理、tsrecorder 的設定方式與後續的 Tailscale PAM,見 Tailscale SSH 工作階段錄影與瀏覽器 SSH。
關閉
# 在這台機器關閉 Tailscale SSH
sudo tailscale set --ssh=false關閉前先確認還有其他方式能登入這台機器。要整個 tailnet 停用,就在每台機器關閉,並刪除 policy 裡的 ssh 規則。
限制
- 只能連到裝了 Tailscale 的機器,Subnet Router 後面的設備不能用 Tailscale SSH。
- 固定使用 22 埠,無法更改。
- 重新啟動
tailscaled(例如升級 Tailscale)會中斷所有進行中的 Tailscale SSH session。 - 用戶端不需要本機的 SSH 金鑰,所以用戶端機器上的任何 OS 使用者都能以你的 Tailscale 身分 SSH 出去。多人共用的機器、或跑著不信任程式的機器,不適合給它 SSH 出去的權限;可以用
checkPeriod: "always"降低風險(Premium、Enterprise 方案)。 - 靠
authorized_keys的command=限制遠端能執行的指令,在 Tailscale SSH 上不適用。
不適合 Tailscale SSH 的情況,仍然可以照舊用 OpenSSH,只是把 Tailscale 當網路層,一樣不用把 SSH 暴露在網際網路上。
疑難排解
連線被拒或要求輸入密碼時,依序檢查:
- 目的機器有沒有開啟:在目的機器執行
tailscale debug prefs | grep RunSSH,或看 Admin console 的機器詳細資料是否標示 SSH。沒開就執行sudo tailscale set --ssh。 - 是不是連到原本的
sshd:要求輸入密碼或金鑰,多半是用了區網 IP 或其他名稱。改用 MagicDNS 名稱或100.x.y.z。 - 網路層規則:
grants/acls要允許你連到目的機器的 22 埠。 - SSH 規則:
src、dst、users是否涵蓋這次的連線;記得 check 規則優先,且只看它的users。目的機器是別人以使用者身分登入的,就不能 SSH。 - 本機帳號:
users寫的帳號要在目的機器上真的存在。 - known_hosts 錯誤:Tailscale SSH 依賴主機名稱寫入的
known_hosts,DNS 解析不到時可能出錯,可以試試 Tailscale IP 或tailscale ssh。