Reachability as Authorization
従来の VPN は「入れること」と「使ってよいこと」を別の仕組みで管理してきた。トンネルに入った後は、各サーバが改めて「お前は誰だ」と訊く。Tailscale はこの二つを同じ暗号鍵の上に載せ直した。だから SSH の段階で訊くべきことが残っていない。以下はその接合部を、下の層から順に開いていく。
分離の設計思想
Tailscale の構造を一言で言うと、制御面(コントロールプレーン)とデータ面(データプレーン)の分離です。この区別を掴んでおくと、後の話が全部きれいに片付きます。
制御面はハブ&スポーク型で、中央のコーディネーションサーバが各デバイスの公開鍵とポリシーだけを配ります。実トラフィックはここを通りません。データ面はメッシュ型で、可能な限りデバイス同士が直接 WireGuard トンネルを張ります。
つまり中央サーバは「名簿と入館規則を配る事務局」であって、「全員が通る一本の廊下」ではない。ここが従来の VPN 集線装置との決定的な違いです。秘密鍵は各デバイスから外に出ないので、事務局は通信内容を読めません。
従来型 VPN では、認可の判断と通信の中継が同じ箱に同居していました。だから箱が落ちれば全部止まり、箱を抜ければ内側は素通しになる。分離すると、方針の決定は中央で一元化しつつ、方針の執行は各ノードに分散できます。
WireGuard
Noise_IK
WireGuard は Noise プロトコルフレームワークの Noise_IK パターンを使います。各ピアは Curve25519 の静的鍵ペアを持ち、相手の公開鍵を事前に知っていることが接続の前提です。ハンドシェイクの時点で相互認証が完了しており、「まず繋いでから認証する」という段階が存在しません。
WireGuard の中核概念がこれです。各ピアの公開鍵に、そのピアが名乗ってよい IP アドレス範囲が紐づけられている。ある送信元 IP を持つパケットは、その IP に対応する鍵で暗号化されたセッションから届いた場合にしか受理されません。ルーティングテーブルと認可テーブルが同一物になっている、と言い換えられます。
副作用として、WireGuard は正しい鍵を持たない相手に一切応答しません。ポートスキャンに対して沈黙する。「開いているポートを見つけてから総当たり」という攻撃の入口自体が消えます。
Tailscale が
足したもの
素の WireGuard は「鍵の配布」と「相手の居場所の発見」を人間に丸投げします。ピアが10台あれば手作業で設定ファイルを書き、IP が変わるたびに直す。Tailscale が引き受けたのは主にこの運用部分です。
重要なのは最後の一行です。WireGuard 単体では公開鍵はただの数字で、それが誰のものかは人間の記憶の中にしかない。Tailscale は制御面を通じて、鍵と組織上のアイデンティティを恒常的に結びつけました。ここが SSH の話に直結します。
核心
ここが核心部分です。これは比喩ではなく、三つの事実が重なった結果として文字通りそうなっています。
① 暗号的事実:パケットが復号できたなら、送信者は対応する秘密鍵の保持者である。Noise_IK により中間者は成立しない。ここまでは WireGuard の性質。
② 身元の紐付け:その公開鍵が tailnet 上のどのユーザ/どのデバイスかは、制御面が保証している。SSO を経由しているので、組織の人事的な実体まで辿れる。
③ 認可の事前執行:ACL から生成されたフィルタが、そもそも「話しかけられる相手」を絞っている。送信側と受信側の両方で判定される。
従来モデルとの差は「順序」です。旧来の VPN は到達可能にしてから認可を問う。Tailscale は認可された相手としか到達可能にならない。だから到達可能性と認可が同一の事象になり、パケットが着いた時点で認証プロセスは既に終わっている。
| 従来型 VPN | Tailscale | |
|---|---|---|
| 境界 | ネットワーク境界(入ったら内側はフラット) | デバイス単位(各接続が個別に認可) |
| 認可の位置 | 接続後、各サービスが個別に判断 | 接続の成立条件そのもの |
| 身元の単位 | アカウント/IP アドレス | 公開鍵+SSO アイデンティティ |
| 失効 | アカウント停止(既存セッションは残りがち) | node key 失効で経路ごと消える |
| 横移動 | 内側に入れば広く到達可能 | ACL で許した経路以外は存在しない |
RFC 4251–4254
ここで SSH 側を開きます。SSH は単一のプロトコルではなく、三つの層の積み重ねです。この分解ができると、Tailscale SSH がどこを置き換えているのかが一発で見えます。
none で通過する。
「SSH の暗号がなくなる」のではありません。SSH の暗号化セッションは通常どおり張られます(結果として WireGuard と二重になる)。変わったのは認証・認可の真実の在処であって、プロトコルの層構造そのものは保たれています。
Tailscale SSH
の実装
tailscale up --ssh を有効にすると、tailnet インターフェース上の 22 番ポートに応答するのが sshd ではなく tailscaled になります。同じポート番号、別のデーモン、別の認証経路。物理 NIC 側の sshd はそのまま従来どおり動きます。
tailscaled は接続元のノード鍵から相手の tailnet アイデンティティを既に知っているので、SSH の認証フェーズを引き取り、追加の証明を求めません。代わりに参照するのが、ポリシーファイルの ssh セクションです。
// tailnet policy (HuJSON) { "ssh": [ { // 通常のオペレーション用 "action": "accept", "src": ["autogroup:member"], "dst": ["tag:infra"], "users": ["autogroup:nonroot", "ubuntu"] }, { // root は SSO 再認証を要求する "action": "check", "checkPeriod": "12h", "src": ["autogroup:member"], "dst": ["tag:infra"], "users": ["root"] } ] }
ssh セクションに明示的なルールがなければ、誰も SSH できません。「書き忘れたら開いてしまう」ではなく「書かなければ閉じている」側に倒れています。
最も
混同される点
議論が噛み合わなくなる原因の大半がここです。名前が似ていますが、まったく別の話です。
| SSH over Tailscale | Tailscale SSH | |
|---|---|---|
| 意味 | tailnet の IP に向けて普通に ssh する | --ssh で有効化する機能 |
| 22番の応答 | 従来どおり sshd | tailscaled |
| ユーザ認証 | 従来どおり SSH 公開鍵 | tailnet アイデンティティ(鍵不要) |
| authorized_keys | 維持が必要 | 不要 |
| 得られるもの | 経路の秘匿と到達性 | 経路+鍵管理の廃止+中央集権的な認可 |
前者でも「インターネットに 22 番を晒さない」という主要な利益は既に得られます。後者はそこから一歩進んで、鍵の配布と失効という運用問題そのものを消す提案です。段階的に移行できるので、まず前者だけで運用してから後者を検討する、という順序は合理的です。
何を
信頼しているか
「通れること=認証」が成立するということは、裏返せば信頼の重心がデバイスと制御面に移ったということです。以下は誇張なく認識しておくべき前提です。
users の写像設計を雑にすると、中央 ACL が厳密でもサーバ内で意味がなくなります。
Tailscale がやったのは、暗号プリミティブの発明ではありません。既に鍵で相互認証しているのだから、その上でもう一度認証をやり直す理由がないという、層の重複の除去です。SSH 鍵という30年物の運用負債が消えたのは、その除去の副産物として出てきた。
逆に言えば、この設計の説得力は「下の層の認証が本当に信頼できるか」に全面的に乗っています。WireGuard の暗号的健全性と、制御面の運営主体への信頼。検討すべき論点は結局この二点に収束します。