コンテナの HTTPS が社内 VPN で止まる? DTLS 側を検証する
コンテナ内ではログインできるのに HTTPS が止まるなら、UDP データチャネルを検証する。DTLS を無効にして両方の経路を比較し、その後 MTU を確認してからフラグを残す。
社内 VPN の内側にあるコンテナでは、DNS が解決し、ログインページが読み込まれ、ヘルスエンドポイントが応答し、そのあと HTTPS リクエストがタイムアウトまで止まる。イメージを再ビルドしてもプロキシ変数を変えても何も変わらないのは、壊れている部分がイメージの中にないからだ。クライアントは一方のトランスポートで認証し、大容量データはもう一方で流し、壊れているのは後者だけである。
二つの輸送路、一つの紛らわしい症状
TLS ベースの社内クライアントは通常、ごく普通の TLS 接続で認証し、そのあとセッション用に UDP ベースの第二のデータチャネルを折衝する。この第二の脚が機能しているときは、スループットと遅延が改善する。フィルタされていたり経路に収まらないときは、大容量転送の手前までが成功し、転送そのものが止まる。これがまさに上のパターンである。
コンテナはその折衝を変えない。変わるのは外側のパケットが通る経路だ。ホストはコンテナのフローを変換するため、UDP データグラムはクライアントのローカルソケットとは別の送信元ポートから出て、確立済みの TCP フローよりずっと短いタイマーで失効する変換エントリを通って戻る。ホストではトンネルが動くのにコンテナでは失敗するなら、アプリケーションを疑う前にこの二つのフローを比較すること。その比較はイメージの再ビルドより多くを決める。
直感ではなく実験で決める
最も安上がりな実験は、UDP データチャネルを無効にして同じリクエストを繰り返すことだ。デスクトップのラッパーではなくコマンドラインクライアントを使い、フラグが実際に効くようにする: openconnect vpn.example.net --user=you --interface=tun0 --no-dtls。止まっていたリクエストがこれで完了するなら、問題は DTLS の脚であり、残りはノイズだった。
同じコンテナから両方向で結果を確認する。フラグありの大容量リクエストと、フラグなしのリクエストを 一度ずつだ。フラグに追随する挙動の変化は証拠であり、最終的に読み込めたページは証拠ではない。
フラグで直るなら、理由を決める
同じ症状を生む条件は三つあり、それぞれ対応が異なる。経路が UDP を完全にフィルタしているなら、そのネットワークではフラグが正しい恒久解になる。UDP は通すが大きなデータグラムを落とすなら、フィルタではなく MTU を示している。あるいは経路の損失が大きく UDP の脚が TCP より遅いなら、それは到達性ではなく容量の問題である。
回避策を文書化する前に、これらを切り分けること。フィルタはどのパケットサイズでも残り、MTU の問題はしきい値を超えたときだけ現れ、損失はきれいな停止ではなく再送と変動する遅延として現れる。どの試験もクライアント設定を変えずに原因を絞り込む。
回避策を残す前にパケットサイズを確認する
サイズが原因なら、トンネルのインターフェースは経路が運べないパケットを受け入れており、ペイロードが増えた瞬間にどのトランスポートでも問題が再発する。インターフェースを比較する。ホストで ip link show tun0、次にネットワークオプションに記録された MTU を読むために docker network inspect bridge を実行する。より少なく運ぶトンネルの下でコンテナブリッジが 1500 バイトのまま、というのがよくある発見だ。
トンネル内で分割禁止の試験を使い、既知の良好なサイズから上方向に探索し、そのうえでコンテナネットワークの MTU を下げるかトンネルで TCP MSS をクランプする。どちらの修正でも UDP 経路が再び使えるようになり、フラグが不要になることが多い。フィルタが原因でない場合、これがより良い結果だ。
何を引き換えにするかを決める
データチャネルを無効にすると、トンネルはペイロードを TCP 接続の内側で運ぶ。きれいな経路では単に遅くなるだけだが、損失のある経路では 一つのセグメント損失が後続すべてを遅らせ、外側の再送が内側と競合する。この取引は対話的な開発や小さな API 呼び出しに向き、大容量転送やモバイル回線での長時間セッションには向かない。
どの選択肢を取るにせよ、トンネルが最終的にどのトランスポートを使ったのか、その理由とともに記録すること。何か月も前に誰かが足したフラグに黙って依存しているコンテナは次の障害であり、それを調べる人はフラグがフィルタの回避策だったのか MTU 実験の残骸だったのか分からない。