なぜ「VPNが遅い」のか?DTLSが解決するTCPの呪縛とSSL-VPNのリアル
インフラエンジニアの皆さん、お疲れ様です。現場で「VPN経由だとWeb APIのレスポンスが妙に遅い」「RDPやSSHの操作感が重い」といったクレームを受けた経験はありませんか?
パケットキャプチャを開いてみると、VPNトンネルを流れるTCPセッションが、パケットロス一つでまるで堰を切ったように止まっている……。そう、原因の多くは「TCP over TCP」の悪夢、すなわち「Head-of-Line(HoL)阻塞問題」にあります。
今回は、SSL-VPNのパフォーマンスを劇的に改善する救世主、DTLS(Datagram Transport Layer Security)について、現場の知見を交えて深掘りしていきましょう。
1. なぜSSL-VPNで「HoL阻塞」が起きるのか
標準的なSSL-VPN(TLSベース)は、基本的に TCP ポート443を使用します。しかし、VPNトンネルの中でさらに TCP 通信(例えばAPIのRESTリクエストなど)を行うと、問題が発生します。
- 内側のTCP: パケットロスが発生すると、再送制御のために待機する。
- 外側のTCP (VPNトンネル): 内部でロスが起きていることを知らず、順序を維持するために次のパケットを止めてしまう。
これが「HoL阻塞」です。一つのパケットが欠損しただけで、トンネル全体が「詰まり」を起こす。これこそが、VPNの体感速度を殺す真犯人です。
2. DTLS:UDPを味方につけるセキュリティ
DTLS は、まさにこの問題を解決するために設計されました。その名の通り「Datagram」すなわち UDP をベースに TLS のセキュリティ機能を乗せたものです。
DTLSの通信フロー(シーケンス)
DTLS は TLS をベースにしているため、ハンドシェイクの概念は似ていますが、UDP という信頼性の低いトランスポート層を補完するために以下の機能が追加されています。
1. シーケンス番号: パケットの順序を管理し、再送時や順序入れ替わりに対応。
2. 再送タイマー: UDP にはない「届かなかった場合の再送」をプロトコルレベルで実装。
3. ハンドシェイクの再送: ハンドシェイクパケット自体がドロップした際、タイムアウトして再送するロジックを保持。
これにより、VPNトンネル内でパケットロスが発生しても、「そのパケットだけがロスし、トンネル全体は止まらない」という、本来あるべきネットワークの挙動を取り戻せるのです。
3. 実践:DTLS環境のデバッグと確認
運用現場では「今本当にDTLSが使われているのか?」を確認することが重要です。パケットキャプチャ(tcpdump)で見てみましょう。
# インターフェースを指定して、UDPの443番ポートを監視
# SSL-VPNのゲートウェイ宛にDTLSが流れているか確認する
sudo tcpdump -i eth0 udp port 443 -vv
もし tcpdump の結果に DTLS 1.2 や DTLS 1.3 といった文字列が見えれば、正常にセッションが確立されています。もし見当たらない場合、クライアントの設定か、ゲートウェイのポリシーで UDP 通信がブロック(もしくはフォールバック)されている可能性が高いです。
4. エンジニアが押さえるべきパラメーター設定例
VPNゲートウェイ(例:Cisco AnyConnectやOpenConnectなど)を構築する際、DTLSを有効にするための設定のキモは、UDP ポートの開放とMTUの設定です。
MTUの落とし穴
UDP は断片化(フラグメンテーション)に弱いです。DTLS を使用する場合、TCP よりヘッダー分だけオーバーヘッドが増えるため、VPNトンネル内のMTUを少し下げるのが現場の鉄則です。
# 設定例:VPNゲートウェイのインターフェース設定(概念)
# 通常のイーサネットMTU 1500から、オーバーヘッド分を引いて1300〜1400に調整
interface Tunnel0
ip mtu 1350
ip tcp adjust-mss 1310 # MSSも併せて調整し、パス上の断片化を回避
この調整を怠ると、特定の環境下で「接続はできるが、大きなデータ(APIのレスポンスなど)が取得できない」という、デバッグ泣かせの障害が発生します。
5. Web API開発者へのアドバイス
もし皆さんがAPIを開発している側であれば、VPNクライアントの特性を考慮する必要があります。
特に、Fetch API を使ったクライアントアプリケーションを開発する場合、Keep-Alive の設定には注意してください。
// Fetch APIでのリクエスト例
// VPN環境ではセッションが途切れやすいため、タイムアウト設定を適切に行う
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒でタイムアウト
fetch('https://api.internal.corp/v1/data', {
signal: controller.signal,
headers: {
'Connection': 'keep-alive' // トンネルを維持しやすくする
}
})
.then(response => response.json())
.catch(err => {
if (err.name === 'AbortError') {
console.error('VPNのゆらぎによるタイムアウトの可能性を確認してください');
}
});
まとめ:泥臭いパケットの先に真実がある
VPNのトラブルは、多くの場合「プロトコルの仕様」と「現場の環境」のミスマッチから生まれます。DTLS は万能薬ではありませんが、TCP の呪縛から解放されるための最も強力な武器です。
「とりあえずVPNを繋げばいい」という時代は終わりました。パケットがUDPで飛び交い、再送制御がどう働いているかを脳内でイメージできるようになれば、皆さんのインフラ運用スキルは一段上のステージに到達するはずです。
次回は、DTLSのハンドシェイク中に発生する「MTU不整合によるパケットドロップ」の追いかけ方について、さらにディープに解説したいと思います。それでは、良いインフラライフを!
コメント