← シリーズに戻る

Tailscale SSHと鍵ゼロ運用の3制約

Part 6 / 6 SSH接続の5方式を7軸比較(4方式実測)

authorized_keys を配らずに済ませる方法が1つあります。Tailscale SSH は認証と認可 (誰がどの機械にどのユーザー名で入ってよいかの決定) をtailnet (Tailscale でつないだ端末の集まり) のアクセス制御ポリシーに委譲するので、サーバー側に鍵を置きません。

ただし代わりに3つの制約が付きます。サーバー側のOSが限られること、ポリシーを書かないと有効化しても入れないこと、tailnetの外からは使えないことです。この3つのどれかに当たるなら、公開鍵認証を続けることになります。 tailnet 越しに公開鍵認証を使う形は、Tailscale越しのSSHとMTU 1280の章で扱いました。

何が変わるか

公開鍵認証では、認可の情報がサーバー側の authorized_keys にありました。Tailscale SSH ではそれがtailnetのポリシー側に移ります。

公開鍵認証Tailscale SSH
認可の置き場所各サーバーの authorized_keystailnet のポリシー1箇所
人を追加する全台に公開鍵を配るポリシーの src に足す
人を外す全台から該当行を消すポリシーから外す、または端末を無効化
誰が入ったかサーバーのログtailnet 側に残る。セッション録画も可能

差が出るのは削除の側です。 台数が1台なら手間は変わりませんが、20台あれば authorized_keys を20回直すか1箇所直すかの差になり、しかも20回のうち1回を忘れたことには誰も気づけません。

人を1人外すときに触る場所を比べた図。左の公開鍵認証は、機械 1〜20 のマスが並び、それぞれ「1行を消す」。機械 14 だけが赤い点線で「消し忘れ」。見出しは「触る場所 20。全台の authorized_keys から、その人の行を探して消す」。右の Tailscale SSH は、tailnet のポリシーの箱が1つ (その人を src から外す、または端末を無効化する) で、その下に機械 20台が並び authorized_keys は触らない。見出しは「触る場所 1」。下に「20回のうち1回を忘れても、誰も気づけない」「Tailscale SSH の側は公式ドキュメントからの評価で、この章は実行していません」

(たとえると、辞めた人の名前を各部屋の錠の登録から1部屋ずつ消して回るか、受付の名簿から1行消すかの違いです)

2箇所を設定する

端末側とポリシー側の両方が要ります。片方だけでは入れません。

Tailscale SSH の2箇所の設定を示す図。左の端末側 (接続を受ける機械で tailscale set --ssh) は、ホスト鍵の対を作り公開側をクライアントへ配る、tailnet から22番に向いた通信を tailscaled が横取りする、sshd_config と authorized_keys は変更しない。右のポリシー側 (tailnet のアクセス制御の ssh セクション) は action (accept か check)、src (誰が。グループ・タグ・autogroup)、dst (どの端末へ)、users (相手側のどのユーザー名で)。両方そろって、はじめて入れる。下の囲みは「ポリシーの ssh セクションを書き忘れると、端末側を有効にしても接続は拒否される」と「有効化の瞬間、その端末の Tailscale IP へ張っていた既存の SSH 接続はハングする。LAN 側の IP やコンソールを確保してから打つ」。公式ドキュメントからの整理で未実行

端末側

tailscale set --ssh

公式ドキュメントによると、このコマンドはホスト鍵の対を生成し、その公開側をコントロールプレーンに渡してクライアントへ配布し、tailnet から22番に向いた通信を tailscaled が横取りするように設定します。

/etc/ssh/sshd_config と ~/.ssh/authorized_keys は変更されません。tailnet を通らない従来のSSH接続はそのまま動きます。

ポリシー側

tailnetのアクセス制御ポリシーに ssh セクションを書きます。これが無いと、端末側を有効にしても接続は拒否されます。

{
  "ssh": [
    {
      "action": "accept",
      "src":    ["autogroup:member"],
      "dst":    ["autogroup:self"],
      "users":  ["autogroup:nonroot"]
    }
  ]
}

この例は「tailnetのメンバーが、自分の端末に、root 以外のユーザーで入れる」という意味です。フィールドは4つあります。

  • action — accept はそのまま通す、check は接続前に認証をやり直させる
  • src — 誰が。利用者・グループ・タグ・autogroup で指定し、* だけを書くことはできません
  • dst — どの端末へ。タグ、autogroup:self、または特定の利用者
  • users — 相手側のどのユーザー名で入るか

ポリシーの ssh セクションの例を1行ずつ読む図。左に JSON の例 (action は accept、src は autogroup、dst は autogroup、users は autogroup)、右に各行からの矢印で意味。action: accept = そのまま通す (check にすると接続前に認証をやり直させる)。src: tailnet のメンバーが (利用者・グループ・タグ・autogroup で指定、* 単体は不可)。dst: 自分の端末に (タグ、autogroup、または特定の利用者)。users: root 以外のユーザー名で (相手側のどのユーザー名で入るか)。下に「つなげて読むと: tailnet のメンバーが、自分の端末に、root 以外のユーザーで入れる」。公式ドキュメントからの整理で、この章は実行していない

root に入るときだけ確認を挟む

action を check にすると、接続の前に本人確認 (IDプロバイダへのサインインのやり直し) を要求できます。一度確かめると checkPeriod の間は確認なしで入れ、既定は12時間です。always にすると接続のたびに確かめます。下の例は、tag:prod の付いた端末へ root で入るときだけ、直近1時間に確認していなければ確認を挟みます。root 以外で入る規則は、前の例のように accept のまま別に書きます。

{
  "action":      "check",
  "src":         ["group:engineers"],
  "dst":         ["tag:prod"],
  "users":       ["root"],
  "checkPeriod": "1h"
}

鍵認証には無い挙動です。秘密鍵を持っているかどうかとは別に、いま本人が居るかを確かめられます。

3つの制約

1. サーバー側のOSが限られる

接続を受ける側になれるのは Linux と、オープンソース版の tailscale / tailscaled を使う macOS だけです。Windows、通常の macOS、Synology、QNAP は接続先になれません。

クライアント側は制限がなく、Tailscale が動くどの環境からでも接続できます。

2. ポリシーが無いと有効化しても入れない

端末側の tailscale set --ssh は受け入れ準備をするだけです。誰が入れるかはポリシーが決めるので、ssh セクションを書き忘れると「有効にしたのに拒否される」状態になります。

公開鍵認証の感覚だと、サーバー側の設定だけで完結すると思いがちです。認可が端末の外にあるという設計の違いは、有効化して拒否されるまで気づきにくい形をしています。

3. tailnet の中にしか効かない

サブネットルーターの奥にいて Tailscale 自体を動かしていない機械は、Tailscale SSH の接続先になれません。tailnet に参加している端末どうしだけです。

外部の取引先や、方針上 Tailscale を入れられない機械が相手に含まれるなら、その相手のぶんだけ従来のSSHを残すことになります。

Tailscale SSH の接続先になれる機械を示す図。左の「tailnet の中」の枠に、接続先になれる Linux と macOS (OSS 版 tailscaled)。その下に「Tailscale は動くが、接続先にはなれない」として Windows・通常の macOS・Synology・QNAP (赤)。枠の下部に「接続する側 (クライアント): Tailscale が動けばどこからでも」。右の「tailnet の外」の点線の枠に、サブネットルーターの奥 (Tailscale 非稼働)、外部の取引先、方針上 Tailscale を入れられない機械 (赤い点線)。下に「赤い機械が相手に含まれるなら、その分だけ従来の SSH (公開鍵認証) を残す」。公式ドキュメントからの整理で、この章は実行していない

どれを選ぶか

7軸で見ると、Tailscale SSH が強いのは鍵の配布・失効・監査の3つで、落ちるのは対応環境の1つです。

この章の外まで含めると、状況ごとの選び先は次のとおりです。

状況選ぶもの
自分1人、機械にグローバルIPがある公開鍵認証 (B)(SSHの鍵認証でパスワードを消す4手順)
機械がNATの内側、入るのは自分1人Tailscale 越しの公開鍵認証 (D)(Tailscale越しのSSHとMTU 1280)
22番をインターネットに出せないD。サーバーが全部 Linux なら Tailscale SSH (E) も
入る人が複数で出入りがあり、サーバーは全部 LinuxTailscale SSH (E)
Windows や Synology が混ざるTailscale 越しの公開鍵認証 (D)
tailnet に入れられない機械がある踏み台経由の公開鍵認証 (C)(ssh -J と config の差を踏み台で実測)

併用もできます。 sshd は触られないので、Tailscale SSH を有効にしたまま従来の鍵認証を残せます。移行中に片方だけ壊れても、もう片方で入れる状態を作れるのは実務上ありがたい性質です。

Tailscale SSH と鍵認証の併用を示す図。接続を受ける機械 (Linux) には2つの入口がある。左上の tailnet の端末から Tailscale IP の22番へ向かう通信は tailscaled が横取りし、Tailscale SSH として tailnet のポリシーが入れるかを決める。左下の tailnet を通らない接続 (LAN 側 IP の22番へ) は、いつもの sshd に届き、公開鍵認証のまま。sshd_config と authorized_keys は変更されない。下に「移行中に片方が壊れても、もう片方の入口から入れる。横取りされるのは tailnet から Tailscale IP へ向かう通信だけ」。公式ドキュメントからの整理で、この章は実行していない

このシリーズの結論

5方式を7軸で並べた結果、分かれ目になったのは暗号の強さではありませんでした。到達性と、人が抜けたときにどこを1箇所直せばいいかです。

人が1人で機械が1台なら、公開鍵認証で十分です。そこから外れた瞬間に、鍵を配る手間と、消し忘れた1台が誰にも気づかれずに残り続けることが効いてきます。自分がどちら側に居るかは、pillar のマトリクスで確かめてください。