VPN が DNS を乗っ取りローカル名を壊した:リストを修正する
独自のリゾルバーを入れるトンネルは LAN の名前を隠します。インターフェースの DNS リストを直し、push を絞り、再接続後に再確認します。
トンネルが上がり、イントラネットは読み込めるのに、プリンターの名前が解決されなくなる。あるいはその逆で、社内ネットワークの中だけがタイムアウトするのにローカルの名前はまだ効いている。どちらの症状も同じ場所から来ている。VPN クライアントが接続時に書き換えたリゾルバーのリストだ。
リストを意図的に直し、そのあと push の仕組みを別に扱う。ルートは三つ目の話題で、ここで直しているものではない。
アプリが実際に使うリストはどれか
Windows はダイアログが表示する内容ではなく、インターフェース単位の設定で解決する。だから各インターフェースの有効なリストから始める。表示名よりエイリアスのほうが重要で、以下のコマンドはすべてインターフェースを指定する。エイリアスを間違えると修正は別のアダプターに当たる。次の再接続までは動いているように見え、そこでトンネル自身の項目が戻ってくる。
問題はどのサーバーが前に出たか、そして静的エントリとして来たのか DHCP リースとして来たのかだ。どちらも、選べる修正を決める。
netsh interface ipv4 show dnsservers
Get-DnsClientServerAddress -AddressFamily IPv4
トンネルのアダプターと物理アダプターの出力を読み、それぞれのすべてのアドレスを書き留める。静的エントリはポリシーやスクリプトで消せるが、DHCP が配ったものはリースに縛られて戻ってくる。だから選ぶべき修正が変わる。遠隔ネットワークの名前は広告されたリゾルバーが、ローカル LAN の名前は物理アダプターが解決し、問い合わせは先に見られるリストへ行く。
push されたサーバーを削除するか、順位を下げる
トンネルの中で必要とするものがないなら push されたサーバーを消す。物理アダプター自身のリゾルバーがまた引き継ぐからだ。遠隔ネットワークが自分のサーバーでしか答えられないゾーンを持っている場合だけ残し、その場合は手前にローカルのリゾルバーを置く。下の二つのコマンドはどちらの選択もカバーするので、両方流すのではなく状況に合うほうを選ぶ。
netsh interface ipv4 delete dnsservers name="Corp VPN" address=all validate=no
netsh interface ipv4 add dnsservers name="Corp VPN" address=172.16.20.1 index=1 validate=no
インデックス 1 が最初に見られるので、push されたアドレスは使えるままでも、すべての問い合わせの既定の答えではなくなる。validate=no フラグは、トンネルがまだ落ち着く途中でよく失敗する到達性テストを飛ばす。だから終了コードを信じるのではなく show コマンドで結果を確認する。
これに頼る前に知っておくべき限界が二つある。Windows は DHCP で netsh を通じて来たサーバーを削除しないし、その値はインターフェースのレジストリキーの下に DhcpNameServer として残る。だからレジストリの編集は最後の手段で、次のリースの後に再確認が要る。アダプターのバインド順も信頼できる順位付けの仕組みではない。VPN クライアントが自分の項目をリストの先頭に入れられるからだ。
push を絞り込める場所
より良い修正は、適用される前に選択肢を外す。Community OpenVPN クライアントは push されたディレクティブを名前で絞り込めるので、サーバーの設定はそのまま残る。
pull-filter ignore "dhcp-option DNS "
末尾の空白は一致条件の一部で、フィルターはサーバーのアドレスではなく選択肢の名前を取る。プロファイルに block-outside-dns ディレクティブも含まれるなら、それを外すのは名前解決ではなく漏洩保護を変えることになる。だから二つの編集をまとめず、別々に決める。
一つの頑固なホスト名なら、Windows の hosts ファイルの一行のほうが、マシン全体のリゾルバーを並べ替えるより安定している。次の人には見えないので、マシンの設定を文書化している場所に必ず書く。
修正を再接続のあとも残す
名前解決は二度試す必要がある一度は選んだサーバーに対して、一度はアプリが使う形で。この組が、リゾルバーの順序の問題と、まったく答えないサーバーを分ける。最初のテストを飛ばすと、二つの原因が絡まったままになる。
Resolve-DnsName intranet.corp.example -Server 172.16.20.1
Resolve-DnsName printer.lan
トンネルに再接続し、両方のコマンドを繰り返す。手で変えたものは次の接続までしか持たない。クライアントはアダプターを上げる間にリゾルバーの状態を作り直すからだ。netsh の行をクライアントが対応する接続スクリプトに入れ、そのスクリプトを正常終了させ、実行前に短い待ちを足す。スクリプトの後に DNS を適用するクライアントなら、どちらにせよ結果は上書きされる。
修正のあとで公開名は解決するのに社内名がまだ失敗するなら、リゾルバーのリストはもう容疑者ではない。問い合わせはおそらくサーバーに届いていない。それは別の DNS 設定ではなく、ルーティングかファイアウォールの規則を指す。インターフェースのエイリアスと落ち着いたアドレスを記録しておく。どちらもマシンごとに違い、どちらも単独では作り直しに耐えない。