Webしか通らないネットワークでVPNが遮断?層ごとに確かめる
ブラウザーは動くのにトンネルが死ぬ。curlの時間フェーズを読み、プロキシを試し、443が本当に許可されているかを確かめ、最後に端末から出たものを記録する。
ブラウザーが動き、あらゆるトンネルが死ぬキャンパスやホテルのネットワークは、一つの問題ではなく四つの層である。経路がTCP 443しか許さないのか、認証プロキシを要求するのか、ハンドシェイクを検査するのか、それとも方針で遠隔アクセスを禁じているのか。順に潰せば、ネットワークの規則を直すために新しいクライアントを買う必要はない。以下の手順は約十分で終わり、どの層が自分を拒否したかの書き言葉の答えにたどり着く。
どの層が接続を拒否しているかを証明する
VPNクライアントから始めない。同じホストへの素のHTTPSリクエストから始め、時間フェーズを読む、失敗するフェーズがどの機器の責任かを教えてくれる:
curl -sS -o /dev/null -w 'connect=%{time_connect} tls=%{time_appconnect} code=%{http_code}\n' \
--max-time 8 https://vpn.example.net/
応答もconnect時間もなければTCPが完了しておらず、ファイアウォール、プロキシ要求、誤った宛先のいずれかが働いている。connect時間がありtls時間がないなら、途中の何かが接続を受け入れ、それからハンドシェイクを止めた、検査プロキシはクライアント側からそう見える。
次に、実際に受け取っている証明書を見る。サーバーと話しているのか、セッションに再署名した中間装置と話しているのかを知る最速の方法だ:
openssl s_client -connect vpn.example.net:443 -servername vpn.example.net -brief </dev/null
発行者の行を読む。自分のCAならサービスに到達しており、企業や機器の発行者なら、フィルターが接続を終わらせ、次を決めている。両方の出力を時刻付きで記録する、同じ試験も一時間後のゲスト網では別の答えを返しうる。
プロキシを意識するクライアントは最初のパケットを変えるのであり、方針は変えない
ネットワークが認証プロキシ経由のCONNECTを要求するなら、VPNクライアントに伝えねばならない、さもないと経路を持たないアドレスにソケットを開こうとする。プロキシはクライアントと別に試し、失敗の説明が一つになるよう:
https_proxy=http://proxy.example.edu:3128 curl -v -o /dev/null https://vpn.example.net/
sudo openvpn --config /etc/openvpn/corp.conf --proto tcp-client \
--remote vpn.example.net 443 --verb 4
最初のコマンドはプロキシが宛先を運ぶことを証明する。二つ目はクライアントに443のTCPを使わせる、Web専用の経路がそもそも通す唯一の輸送だ。最初が成功して二つ目がまだ失敗するなら、プロキシは障害ではない。
OSのプロキシを上書きの代わりに読むクライアントもあれば、どちらも読まないクライアントもある。システム全体の設定が効くと決めつける前に、アプリ自身の文書を確認する。プロキシが扱わないリゾルバーで端点を解くクライアントもここで失敗する、だからDNSの変更が、ただの回り道でも修正に見えるのだ。
ついでに誘導の型も見ておく。フィルターされた網はベンダーの検出ホスト名に自分側の何かを返すことがあり、クライアントが選ぶプロキシ構成が変わる。その癖を前提に手順を組まない。場所ごとに違い、予告なく変わり、他人のために支えられるものではない。
ポート443は到達できるのであって、許可されているのではない
443でトンネルをTLSに包むのは到達性を解くだけで、他は何も解かない。ポートを見るフィルターは通すが、ハンドシェイクの指紋を取るフィルターは通さない、暗号化クライアントハローがサーバー名を隠すのは両端が対応するときだけだ。期待するのではなく、試験を走らせて自分がどんなフィルターの後ろにいるかを知る。
後から気づく性能の代償もある。信頼できる輸送の中の信頼できる輸送は損失を増幅する、内側のスタックが、外側がすでに再送したセグメントを再送するからだ。きれいな回線では誰も気づかない。混雑したキャンパスの無線網では、必要なまさにその時にトンネルが使えなくなり、意図的に捨てていないのにグラフはパケット損失に見える。
UDPがたいてい最初の犠牲者で、推測ではなく確認する価値がある。TCP 443が動くのにWireGuardや既定のOpenVPNがハンドシェイクを終えないなら、網はUDPを落としている、鍵の再生成では変わらない:
sudo wg show
dig +short vpn.example.net
dig +short vpn.example.net @1.1.1.1
昨日まで動いていた相手の隣でハンドシェイクの時刻が空なら、それがUDPの答えだ。二つのDNS問い合わせは別の問いに答える、ローカルのリゾルバーと公開リゾルバーが端点のアドレスで食い違うなら、誘導されており、輸送の議論は的外れだ。
端末から実際に何が出たかを確かめる
クライアントのログはクライアントの信じていることを語る。キャプチャは網が見たものを語る、この二つの差が、こうした事例の多くが解ける場所だ:
sudo tcpdump -ni any -c 20 'tcp port 443 and host 203.0.113.10'
sudo ss -tunp | grep -E ':(443|1194|51820)\b'
SYNパケットが見えてSYN-ACKがなければ、遮断は上流にありクライアントは無実だ。サーバーのものでないアドレスへの完了したハンドシェイクが見えるなら、プロキシか傍受者と話している。何も見えないなら、結論を出す前に正しいインターフェースで取ったかを確かめる。
ソケット一覧はもっと繊細な場合を捕らえる、既定経路をすでに握る第二のトンネルだ。経路表を奪い合う二つのクライアントは、遮断された網とまったく同じに見える断続的な失敗を生み、キャプチャは予想しなかったインターフェースから出る通信を示す。
元に戻すこと、そして残す価値のあるメモ
変更を、行った順の逆に戻す。プロキシ変数を外し、手で起動したクライアントを止め、加えた経路やリゾルバーの上書きを外す:
unset https_proxy http_proxy
sudo systemctl stop openvpn-client@corp
sudo ip route show default
手で起動したクライアントを動かしたままにするのが、次のオフィス訪問でノートPCが壊れた網を抱える理由だ。シェルのプロファイルに残したプロキシ変数は数週間後に無関係な道具を壊し、それを調べる人は二つの出来事を結びつけない。
そして四行書く、網、時刻、失敗したフェーズ、見た発行者。あるキャンパスで動き次で失敗する経路は普通で、次の人は違いがプロキシかリゾルバーかフィルターかを知る必要がある。答えが「網が遠隔アクセスを禁じている」なら、そこで止め、読んでいない方針に回避策を持ち込むのではなく、管理者に支持された経路を尋ねる。