Tailscaleを使って自宅LANへ接続する設定をしていたときに、少し疑問に思ったことがあります。
SSHやRDPはTCP通信です。
それなのに、TailscaleやWireGuardはUDPを使って通信しています。
「TCPの通信をするなら、VPN側もTCPでよいのでは?」と思ったのですが、調べてみると、VPNでUDPが使われるのにはきちんと理由がありました。
SSHやRDPはTCP通信
SSHやRDP、HTTPSなどは基本的にTCPを使います。
TCPは、通信の信頼性を確保する仕組みを持っています。
例えば、
- データが届いたか確認する
- 届かなかったデータを再送する
- 順番どおりに並べる
といった処理を行います。
そのため、SSHやファイル転送のように「データが正しく届くこと」が重要な通信に向いています。
TailscaleやWireGuardはUDPを使う
一方で、Tailscaleの内部で使われているWireGuardはUDPを使います。
ここで重要なのは、SSHのTCP通信をそのままUDPに置き換えているわけではない、という点です。
実際には、
SSH
↓
TCP
↓
Tailscale / WireGuard
↓
UDP
↓
インターネット
という形になります。
つまり、アプリケーション側ではTCP通信のままです。
そのTCP通信をVPNで暗号化して、外側をUDPで運んでいます。
イメージとしては、
SSHのTCP通信 = 荷物
WireGuardのUDP通信 = 配送用の箱
のようなものです。
なぜTCPではなくUDPなのか
最初は、TCPの方が再送や順番保証があるので、VPNにも向いているのではないかと思いました。
しかし、VPNの外側までTCPにすると問題が起きやすくなります。
例えば、
SSH
↓
TCP
↓
VPN
↓
TCP
↓
インターネット
のようになります。
この場合、内側のTCPと外側のTCPの両方が、
- 再送
- 順番制御
- 速度調整
を行います。
その結果、パケットロスが発生したときに処理が二重になり、通信が詰まったり、遅延が大きくなったりします。
これを TCP over TCP問題 と呼びます。
UDPなら内側のTCPに任せられる
UDPには、TCPのような再送や順番保証はありません。
そのため、
SSH
↓
TCP
↓
WireGuard
↓
UDP
のようにすると、通信の信頼性は内側のTCPに任せることができます。
外側のVPNは、余計な再送制御をせず、暗号化したパケットを運ぶだけです。
そのため、VPNではUDPの方が効率が良くなります。
UDPでも大きなデータは送れるのか
UDPは1つのパケットで送れるサイズに上限があります。
ただし、SSHやRDPの通信全体を1つのUDPパケットで送るわけではありません。
実際には、通信はMTUに合わせて細かく分割されます。
大きなデータ
↓
小さなTCPパケット
↓
WireGuardのUDPパケット
という形で送信されます。
そのため、SSHやRDP、ファイル転送なども問題なく利用できます。
Tailscaleがつながりやすい理由
Tailscaleは、UDPホールパンチングという仕組みも使います。
通常、家庭用ルーターやモバイル回線のCGNAT環境では、外部から自宅の機器へ直接アクセスすることはできません。
しかしTailscaleでは、両方の端末が先に外向きの通信を行います。
ノートPC → 外へ通信
自宅ルーター → 外へ通信
そうすると、それぞれのルーターやNATに一時的な通信経路ができます。
Tailscaleはその情報を使って、端末同士が直接UDP通信できるようにします。
これがUDPホールパンチングです。
直接つながらない場合
環境によっては、UDPホールパンチングが成功しないこともあります。
その場合、TailscaleはDERPという中継サーバーを使います。
ノートPC
↓
DERP中継サーバー
↓
自宅ルーター
直接接続より速度は落ちますが、厳しいNAT環境でも接続できる可能性が高くなります。
まとめ
SSHやRDPはTCP通信ですが、TailscaleやWireGuardでは、そのTCP通信をVPNの中に包み、外側をUDPで運んでいます。
VPNでUDPが使われる主な理由は、
- TCP over TCP問題を避けられる
- 通信が軽くなる
- UDPホールパンチングと相性が良い
- CGNAT環境でも直接接続できる可能性がある
ためです。
最初は「TCPの通信なのに、なぜUDPで運べるのか?」と思いましたが、実際にはTCPをUDPに置き換えているのではなく、TCP通信をUDPの中に包んで運んでいる、という理解が近いと思います。

コメント