エンジニアが数年ぶりにTailscaleの機能を本格活用。自宅のProxmoxサーバー上にLXCコンテナ(1 vCPU、512 MB RAM)を立てて専用のエグジットノードを構築し、tracerouteコマンドで実際のトラフィック経路を追跡した。結果、Tailscaleのトラフィックが自宅のISP経由で外部に出ていること、そしてWireGuardベースのメッシュネットワークとTailscaleのコントロールプレーンの結合により実現している仕組みを具体的に観測。
Tailscaleは「自分のデバイス間に到達するため」の用途で長年使われてきたが、エグジットノード機能はあまり活用されていなかった。しかし最近、このエグジットノード機能を試したことで、従来のVPN的に見えて、内部動作が大きく異なることに気付く。特に:
tailscale-gw、ホップ7が自宅ISPエッジとなるが理解できた。
Tailscaleは単なるWireGuardトンネルではなく、その上に制御レイヤーを乗せたもの。
コントロールプレーンの責務:
データプレーン(WireGuard): WireGuardは「道路」で、コントロールプレーンは「地図と信号機」。実際のデータ転送はWireGuardが暗号化して担当。
1. 両デバイスがTailscaleのコントロールプレーンに認証
2. コントロールプレーンが各ピアの到達可能エンドポイント(公開IP、DERPリレー候補)と暗号鍵を共有
3. 両ピアがUDPパケットを相互送信してNAT穴あけを試行
→ 成功: 直接のWireGuard暗号化パスを確立
→ 失敗: DERPリレーにフォールバック(エンドツーエンド暗号化は維持)
NATは「フロントデスク」のようなもの。誰が外に出たかを追跡するが、ランダムな外部者を直接中に入れない。ホールパンチングは両サイドが「同時に一歩外に出る」ことで、ルーターが戻りのパスを許可するように仕向ける。
エグジットノードを有効化すると、Tailscaleは以下の処理を行う:
0.0.0.0/0(IPv4)と::/0(IPv6)をアドバタイズMacBook (カフェWiFi経由) -> traceroute github.com
Hop 1: tailscale-gw (100.x.y.z) ~7ms
Hop 2: 192.168.x.1 (エグジットノードのLAN) ~7ms
Hop 3: 10.x.x.1 (ISP内部) ~9-177ms
Hop 4-6: * * * (非表示)
Hop 7: home-isp-edge.example (自宅ISP) ~11-14ms
↓ ここからインターネットバックボーン
...
Hop 12以降: github.com到達
見える信号:
MacBook (カフェWiFi) -> traceroute github.com
Hop 1: 192.168.x.1 (カフェのローカルゲートウェイ)
Hop 2-6: * * * (非表示)
Hop 7: cafe-or-local-isp-edge.example
↓ カフェWiFiのISP経由でインターネット
...
Hop 12以降: github.com到達
相違点:
LXCコンテナはデフォルトで/dev/net/tunにアクセスできず、Tailscaleが機能しない。
コンテナ設定ファイルに追加:
# /etc/pve/lxc/<CTID>.conf
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
またはProxmox 7+ UI:
コンテナ > オプション > 機能 > TUN: ON
1. IP フォワーディング有効化
# /etc/sysctl.d/99-tailscale.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
sysctl -p /etc/sysctl.d/99-tailscale.conf
2. NAT/マスカレード設定
# Tailscaleが自動設定するが、失敗時は手動で確認:
iptables -t nat -L POSTROUTING -v
3. エグジットノードをアドバタイズ
tailscale up --advertise-exit-node
4. クライアント側で選択
tailscale up --exit-node=<exit-node-name>
tailscale status: ピアが「connected」と表示
しかしインターネットアクセス失敗
原因:IP フォワーディングまたはNATが未設定
→ エグジットノードが経路の「中継」を拒否している
| 対象者 | 通常は見える | 通常は見えない |
|---|---|---|
| カフェWiFi / ローカルISP | • Tailscaleへの接続 • トラフィック量・タイミング |
• トンネル内のコンテンツ |
| エグジットノード運用者 | • 宛先IP/ドメインパターン • トラフィック量・タイミング (平文HTTP通信の場合はコンテンツも) |
• 利用者のカフェネットワークIP |
| アクセス先Webサイト | • エグジットノードのパブリックIP • リクエストコンテンツ(HTTPS未使用の場合) |
• 利用者のカフェWiFi IP |
重要な信頼の転移:
通常のネットワーク
└─信頼: カフェWiFi < 低い
Tailscale + 自宅エグジットノード
└─信頼: 自分が所有・運用するマシン(自宅Proxmox)< 高い
だからこそ、エグジットノードは最小限(1 vCPU、512 MB、Tailscaleのみ)に保つ必要がある。npmパッケージが多数あれば、サプライチェーン攻撃のリスクが増す。
エグジットノードはインターネット出口を変えるが、DNS解決先は別途設定。
Split DNS の例:
Tailscale管理画面: DNS設定
├─ .home.arpa ドメイン
│ └─ リゾルバ: AdGuard (Tailscale IP: 100.x.y.z)
│ ※ AdGuardは自宅ネットワーク上で動作
│
└─ その他のドメイン
└─ システムリゾルバ経由
(カフェWiFi接続時でも同じ)
実際の名前解決フロー:
MacBook からの DNS query
query: nas.home.arpa
↓
Tailscaleが .home.arpa を検出
↓
AdGuard (Tailscale内) へリダイレクト
↓
AdGuardが "192.168.1.100" を返す
↓
MacBook が NAS に接続可能
一方、query: github.com
↓
システムリゾルバ経由
↓
通常のDNS応答
副作用として得られるメリット:
.home.arpa の問い合わせはAdGuardを通るため、ログに記録される0.0.0.0/0 と ::/0 をアドバタイズ(すべてのインターネット)192.168.1.0/24 など特定プライベートネットワーク範囲のみ| シナリオ | 推奨 | 理由 |
|---|---|---|
| カフェから自宅ISP経由でインターネット使用 | エグジットノード | 全インターネットを自宅経由にしたい |
| リモート接続でNAS、Proxmoxにのみアクセス | サブネットルーター | 通常のブラウジングは直接、内部サービスのみVPN |
| 両方が必要(内部 + インターネット両方) | 同一マシンが両ロール | 1つの マシンで `--advertise-exit-node` と `--advertise-routes` を同時指定 |
エグジットノード有効・無効を切り替えるときの実装側チェックリスト:
# 1) 出口IP確認(最重要)
curl ifconfig.me
# 有効時: 自宅のパブリックIP
# 無効時: 現在のネットワークIP
# 2) 経路確認
traceroute github.com
# 有効時: Hop 1 が tailscale-gw
# 無効時: Hop 1 がローカルゲートウェイ
# 3) エグジットノードの疎通確認
tailscale status
tailscale ping <exit-node-name>
# 出力に direct/DERP の情報
# 4) DNS動作確認
dig <internal-domain> # .home.arpa など
dig github.com # 外部ドメイン
# 内部ドメインが正しく解決されるか
without エグジットノード:
カフェWiFi → ISP → インターネット
信頼先: カフェ管理者
with エグジットノード:
カフェWiFi ↔ [Tailscaleトンネル] ↔ 自宅エグジットノード → 自宅ISP → インターネット
信頼先: 自宅のマシンとISP
信頼の所有権が完全に自分に移る。その代わり、エグジットノード機の保守や監視も自分の責任になる。
エグジットノード経由のトラフィックがすべて同じ「自宅ISP」パスで見えるため、DNS分析ツール(AdGuardなど)のダッシュボード上で以下が可能:
結果として、複数のリモート環境で接続した場合でも、DNS周辺の観測が予測可能になる。
この記事はAI業界の最新動向を速報でお届けする「AI Heartland ニュース」です。