誰かがプロファイルを送ってきて、あなたがそれをインポートし、三十秒後にはクライアントが誰も確認していない宛先にダイヤルしている。まずテキストエディターでファイルを読むべきだ。重要なものはすべて一握りのディレクティブに収まっている: remote、proto、port、ca、cert、tls-crypt、verify-x509-name。残りはすべて既定値であり、驚きはそこに潜んでいる。

ファイルが使えるエンドポイントをすべて列挙する

まずエンドポイントから始める。一つのプロファイルに複数含まれることがあるからだ。grep -nE '^[[:space:]]*(remote|proto|port|remote-random|connection)' profile.ovpn は候補をファイル順に出力し、インラインの <connection> ブロック内に入れ子になったものも含む。

ディレクティブがポートを省略すると、クライアントはリスナーの既定値に戻る。つまり remote vpn.example.com だけならポート1194を意味し、ファイルの後方に現れる proto には左右されない。複数の素の remote 行は代替候補だ。クライアントは remote-random が順序を混ぜない限り順番に試し、別の事業者のホストを黙って差し替えることはない。無関係なドメインを指す二つの remote 行があれば、そこが立ち止まってどちらが意図されたものかを尋ねる地点だ。

proto の綴りにも注意する。tcp はクライアント側の tcp-client の同義語として受け入れられるが、クライアントプロファイル内の tcp-server は構成エラーであり、きれいに失敗するよりもハングしやすい。

まず名前を、次にポートを確認する

dig +short vpn.example.com は名前が存在するか、どのアドレスを返すかを教えてくれる。マルチホームやプロキシ背後のエンドポイントが複数を返すのは正当なこともある。名前の解決は前提条件であって所有権の証拠ではない。誰でも名前をあるアドレスに向けられるし、一つのアドレスが多くの名前の応答を担うこともある。

次に、見つけたポートでリスナーを確認する。トランスポートに合わせること。TCPでは openssl s_client -connect vpn.example.com:1194 -servername vpn.example.com がサーバーが提示するチェーンを出力する。UDPではDTLSが必要だ。openssl s_client -dtls1_2 -connect vpn.example.com:1194 がデータグラム上で同じハンドシェイクを実行する。ハンドシェイクの完了は、何かが待ち受けていて証明書を保持していることを証明する。それはpingが示すより多く、プロファイル自身の信頼設定が要求するよりは少ない。

ハンドシェイクが失敗してホストがpingに応答するなら、ポートが誤っているかフィルターされている可能性が高い。それを正しいポートを要求する理由と捉え、近隣のポートを総当たりする誘いと受け取らないこと。nc -vzu も、何も待ち受けていないのに一部のスタックで成功を報告する。したがって背後にハンドシェイクのない裸のUDPプローブには何の意味もない。

信頼ピンはアドレスとは別に読む

アドレスはクライアントがどこへ行くかを決め、信頼ブロックは到着後に誰を信じるかを決める。verify-x509-name "vpn.example.com" name はサブジェクトのコモンネームを固定し、remote-cert-tls server は サーバー認証のための拡張鍵用途を要求する。事業者から渡されたプロファイルは両方を備えるべきだ。

ca、インラインの <ca> ブロック、そして tls-crypt か tls-auth のいずれかを探す。tls-auth を使うプロファイルは、サーバー側が方向0を使うときクライアント側に key-direction 1 を必要とし、不一致は証明書の不具合のように読めるTLSエラーでハンドシェイクを失敗させる。たった今名前を解決した事業者のものでないインラインCAは、ファイルが二つの出所から組み立てられた証拠であり、これは断固として拒否する価値のあるケースだ。

verify-x509-name は name、name-prefix、subject の各モードを取り、最後のものはサーバーが出力するのと同じ順序の完全な識別名を期待する。値の形に合うモードを選ぶこと。クライアントは惜しい不一致について警告するのではなく、あらゆる接続を拒否するからだ。自分で書いていないファイルには、単純なホスト名を伴う name が最も驚きの少ない選択だ。

静かに失敗するオプションを確認する

OpenVPN 2.6 は data-ciphers を介して暗号を交渉する。古い cipher AES-256-CBC 行だけを持つプロファイルは、制御チャネルを完了してからデータで止まることがある。その値を読めば、ファイルが接続先のサーバーより古いかどうかがわかる。2.6 の マニュアルページ には交渉順が載っているので、事業者に引用して返すとよい。

ファイル名のない auth-user-pass はクライアントが問い合わせることを意味するので、自己完結に見えるプロファイルでも資格情報が必要だ。auth-user-pass credentials.txt は、おそらく送られてきていないファイルを期待していることを意味する。nobind と resolv-retry infinite はありふれていて無害だが、explicit-exit-notify はUDP専用でTCPでは無意味だ。

これらはいずれもプロファイルがどこへ接続するかを変えないが、接続できるかどうかは変える。そしてどれもクライアントのインポート画面には表示されない。

判断し、判断した内容を記録する

この読み込みの後、結果は三つあり、インポートはそのうち一つだけだ。エンドポイントとピンが別経路で得た指示と一致するならインポートする。エンドポイントは正しそうでもピンやCAが一致しないなら、修正済みのファイルを求める。ファイルが出所の異なるエンドポイントやCA素材を混ぜているなら、削除して新しい写しを求める。

確認したハッシュを記録しておけば、次の人がファイルの変化を判別できる。sha256sum profile.ovpn を、メモのエンドポイントの隣に貼り付ける。プロファイルはアドレスの一覧ではなく全体の取り決めなので、動作する remote を他人の信頼ブロックへ、その資格情報を残したまま差し込んではならない。

メモを突き合わせる間、秘密鍵とパスワードはスクリーンショットやチャットのスレッドに残さないこと。エンドポイントと秘密でないオプションだけで的確な質問はでき、残りはファイルに置くべきだ。

それでもインポートして最初の試行が失敗したら、--verb 3 を付けてクライアントを実行し、最初の十行を読む。解決済みの remote アドレス、交渉された proto、TLS エラーがこの順に現れ、上のどの確認を飛ばしたかがわかる。

関連記事