OpenVPN が DNS を送っても、リゾルバが使うとは限らない
クライアントのログに DNS の値があっても、OS のリゾルバがそれを使っている証拠にはなりません。所有者を確認し、次に内部名を試します。
クライアントのログには送られた DNS サーバーが表示され、トンネルも接続済みなのに、内部名は相変わらず解決されない。送信そのものは壊れていない。オプションは届いたが、OS のリゾルバはそれを使わなかった。ほとんどの Unix クライアントでは、OpenVPN は値を受け渡すだけで、適用はプラットフォームに任せるからだ。
症状: ログには DNS が出るのに名前は解決しない
OpenVPN の dhcp-option は DNS とドメインの情報を運び、クライアントは受け取った内容を記録する。実装によってはクライアントがその設定を内部で適用するが、そうでない場合は連携スクリプトやネットワークサービスに渡すだけになる。ログの行は物語の前半しか語らない。後半はクライアントが制御しない場所で起きる。失敗はたいていそこにある。
だからこそ、接続済みのトンネルと解決できない内部名がしばしば同居する。値はあり、使う側がいないか設定が誤っており、リゾルバは接続前から使っていた公開サーバーを黙って使い続ける。
受け取ったことは適用したことではない
システムのリゾルバが別のサービスの管理下にあるまま、クライアントが送られた DNS の値を記録することはある。ブラウザが独自の暗号化 DNS ポリシーを持ち、システムのリゾルバを完全に迂回する場合もあり、一方のアプリは内部名を解決し、他方は解決しないという印象的な状況が生まれる。
どの Unix クライアントも同じファイルを書き換えると決めつけず、実装が対応している連携方法を確認する。その決めつけこそ、誰も読まないリゾルバ設定を編集してしまう理由だ。
プラットフォームごとにリゾルバの所有者を特定する
Windows では、名前解決ポリシーの表が特定のサフィックスを特定のサーバーへ振り向けられ、VPN クライアントがそこに規則を入れることがある。アダプターの DNS 一覧だけでなく、ポリシーを確認する。Linux では NetworkManager か systemd-resolved が設定を所有しうるし、どちらが所有するかで再接続時に何が保たれるかが変わる。
実際に問い合わせに答えるツールで有効な状態を読む。systemd-resolved のホストなら resolvectl query internal.example.net、あるいは各プラットフォームの同等のものを使う。そのうえで、その答えをクライアントのログが送ったと主張する DNS サーバーと比べる。
調整なしにリゾルバ設定を上書きする複数のサービスを動かすのは避ける。所有者が二人いると結果は断続的に見え、再接続のたびにランダムに直ったり壊れたりするように見える。
スクリプトと foreign_option
OpenVPN は送られたオプションを foreign_option_N という名前の変数でスクリプトへ渡し、スクリプトはそれをリゾルバのコマンドに変換できる。この仕組みは対応済みの連携であって自動的な動作ではなく、クライアント側で導入して呼び出す必要がある。
スクリプトに頼るなら、その実行と終了状態を記録する。動いてはいるが黙って失敗するスクリプトは、スクリプトがないのと同じ症状を残し、設定が揃って見えるぶん気づきにくい。スクリプトのファイルではなく、スクリプトの出力を確認する。ファイルがあることは、スクリプトが動いたことではない。
ログではなく名前を試す
接続後にクライアントから内部専用のホスト名を問い合わせ、次に公開名を問い合わせ、どちらのサーバーが答えたかを確認する。正常な構成では二つの答えは別の場所から来るべきで、どちらも設計と一致すべきだ。
名前は解決するのにサービスが失敗するなら、DNS をまた変えるのではなく ルーティングとアプリケーションのアクセス に進む。OpenVPN のマニュアル には dhcp-option とスクリプト環境が記載されている。別のリゾルバ設定を編集する前に、クライアントが何を適用すべきかを確認するために使う。