管理コンソールでの承認は最後の手順に見えますが、そうではありません。まずアプリケーションがタイムアウトし、その後にルーターがオンラインでルートが承認済みだと分かります。承認は配布の手順であり、許可でも転送の保証でもありません。パケットがサブネットルーターの背後のホストに届くまでに四つの段階が揃う必要があり、それぞれが次の段階の失敗と同時に成功することもあります。順番に確認し、成り立たない最初の段階で止めてください。

四つの段階、一つの失敗

ルーターがプレフィックスを広告し、tailnet がその広告を承認し、クライアントが受け取ったルートを受け入れ、アクセスポリシーが特定の接続を許可します。これは三つの異なるコンポーネントによる四つの別個の判断です。したがって承認済みのルートは、そのネットワークが tailnet のルーティングテーブルの一部になったことだけを意味します。

最初の三つが目に見える状態を生むため、第四段階が最も飛ばされやすいのです。ルーター自身の tailnet アドレスを覆う許可は、その背後のプライベートサブネットを自動的に覆うわけではありません。これらは別の宛先であり、ポリシーは宛先ごとに評価されます。

Linux では第三段階に、人を驚かせる既定値もあります:サブネットルートの受け入れは任意です。GUI クライアントの多くは広告されたルートを既定で受け入れるため、混在した環境では一台だけ失敗し、他は動作するように見えます。

プラットフォームを決めつけず、失敗しているマシンで設定を確認してください。動作しているマシンではルートが欠けていたことは一度もないので、tailnet 側が健全であることをそちらで証明させましょう。Tailscale の サブネットルーターのドキュメント には、承認、クライアントのルート受け入れ、ポリシーの段階が含まれています。

クライアントが動く場所でルートを確認する

ルーターではなく、失敗しているクライアントから始めます。ルートが存在すること、クライアントの設定がそもそもルートの受け入れを許可していることを確認してください。

tailscale status
tailscale debug prefs | grep -i route
ip route get 10.20.0.42

最初のコマンドはピアの一覧とサブネットルーターに到達できるかを表示し、二番目はルート受け入れフラグを含むクライアントの設定を出力し、三番目はサブネット上の実在のホストにどのインターフェースを使うかをカーネルに尋ねます。最後のコマンドが Tailscale のインターフェースではなく物理インターフェースを挙げるなら、ルートはテーブルに入っていません。ルートの欠落はクライアント側の問題であり、承認の問題ではありません。ポリシーを見る前にそれを直してください。

Linux でルートを受け入れるには、フラグが設定済みだと仮定せず、そのフラグで再接続します:tailscale up --accept-routes。別のフラグで参加したクライアントは変更するまでそれを保持するので、さらに追加する前に現在の設定を確認してください。変更後に最初のコマンドを再実行すると、テーブルにルートが表示されるはずです。

転送と戻り経路を証明する

承認はルーターにパケットの転送を設定するものではなく、応答を用意するものでもありません。どちらもルーターの LAN 側におけるホスト単位の関心事です。クライアントではなくルーターで試してください。

sysctl net.ipv4.ip_forward
iptables -t nat -L POSTROUTING -n -v
tcpdump -ni any host 10.20.0.42 and port 443

最初のコマンドは 1 を報告する必要があり、そうでなければカーネルは転送されたパケットを破棄します。二番目はサブネットルートのマスカレードが送信元を書き換えているかどうかを示し、これは既定の動作で通常は望むものです。三番目は要求が宛先に届くか何かが返ってくるかを示し、応答のない要求は戻り経路の問題であって承認の問題ではありません。どれかを変更する前に三つの結果をまとめて読んでください。

マスカレードが無効にされている場合、宛先ネットワークには tailnet のアドレスへの戻りルートが必要で、途中の各ホップがそれを知っている必要があります。マスカレードを再び有効にするのは単一サービスにとって最速の修正ですが、元のクライアントアドレスが宛先から見えなくなる代償があります。宛先が監査のために送信元アドレスを記録する場合、このトレードオフは重要なので、インシデント中にフラグをひっくり返すのではなく意図的に決めてください。次の人は二つの動作のうち片方しか見ないため、どちらを選んだかを文書化してください。

リソースのアクセスルールを読む

ルートがあり転送が証明されれば、残る容疑者はポリシーです。接続を許可するはずの許可を読み、送信元だけでなく宛先も確認してください。クライアント自身の ID もポリシーのセレクターに一致する必要があるので、失敗している同じマシンで取得してください。

tailscale status --json | head -40
tailscale ping <router-name-or-tailnet-ip>
ping -c 3 10.20.0.42

ステータス出力はクライアント自身のアドレスと、それが見えるピアを特定し、ポリシーの送信元セレクターはこれに一致する必要があります。tailscale ping はサブネットルーター自体への tailnet 経路を証明し、解決するのはピア名と tailnet アドレスであって広告されたサブネット内のホストではありません。三番目のコマンドはサブネットルート経由で通常の ICMP エコーを送るので、その結果はルーターではなく宛先を表します。tailnet レベルの拒否は通常は拒否として返り、出ていって戻らないパケットはタイムアウトします。

失敗する名前は失敗するアドレスとは別の問いなので、ルートを責める前にホストを直接解決してください。許可はサブネット全体ではなく、実際のリソース要件に合わせて書いてください。一つのアプリケーションを動かすために /24 全体を開けることが、狭い要求が後で誰も外せない広い許可になる道です。

目的がプライベートサブネットではなくインターネットへの出口だった場合、正しいコンポーネントはサブネットルーターではなく出口ノードであり、ポリシーとルーティングもそれに応じて異なります。許可を広げる前にその判断を確認してください。出口ノードは既定ルートを変えますが、サブネットルーターはプレフィックスを広告するだけです。

関連記事