AdGuard Home は LAN アドレスから WireGuard クライアントに応答します
0.0.0.0でのバインドは、カーネルが返信元を選ぶことを可能にします。マルチホームホストでは、その応答がトンネルから到達できないアドレスから来ることがあります。
トンネルは開いており、ファイアウォールはポート53を許可しており、AdGuard Homeは稼働していますが、WireGuardクライアントでは名前が解決されません。クエリは通常通り到着し、応答も通常通り送信されるため、リゾルバのパケットカウンターは正常に見え、サービス自体は無害のように見えます。問題は、その返信の送信元アドレスにあります。返信はクライアントが要求していないローカルアドレスから送信され、クライアントのスタブリゾルバはそれを破棄します。AdGuard Homeの設定のひとつのリストがこれを決定しており、通常のデフォルトではその判断をカーネルに任せます。
クエリは到着し、応答は別の場所から送信されます
クライアントが 10.6.0.1 をリゾルバとして設定している場合、UDP クエリを 10.6.0.1 のポート 53 に送信します。そのパケットはトンネルを通過してホストに到達し、AdGuard Home がこれに応答します。しかし、通信路上では、返信は新しいパケットとなり、その送信元アドレスはクライアントの期待によるものではなく、ホストのスタックによって選ばれます。
クライアントのリゾルバが接続済みソケットの場合、これは systemd-resolved、dnsmasq、およびほとんどのスタブリゾルバが使用する方式ですが、クライアントは送信先と完全に一致するアドレスからの返信しか受け入れません。10.6.0.1 に送信されたクエリに対して 192.168.1.10 から送信された返信は、パースが行われる前に破棄されます。リゾルバは正常な応答と記録し、クライアントはタイムアウトを記録し、両方とも事実を伝えているのです。
つまり、カウンターは嘘をついておらず、クライアントも嘘をついていません。必要な証拠は三か所にあります。この順序で:リスナーにバインドされているアドレス、カーネルがクライアントへ戻るために使用するルート、そして実際の返信パケットの送信元アドレスです。
カーネルが返信元を選択する方法
にバインドされたUDPソケット0.0.0.0自身の送信元アドレスを持っていないため、各送信される返信は宛先のルート検索を引き起こします。その後、カーネルはそのルートから送信元を取得します:ルートで固定されたアドレス、または送信インターフェースの主要アドレスです。クエリの宛先アドレスについては何も記憶されません。
単一ホームのホストでは、これは目に見えません。なぜなら、もっともらしい答えはひとつしかないからです。LANアドレス、WireGuardアドレス、管理アドレスを持つマシンでは、いくつかの答えがもっともらしく、その時点のルーティングテーブルによって決まります。追加のルートを追加する、同じインターフェースに二番目のアドレスを追加する、リゾルバの前にNATリダイレクトを置く、または独自の名前空間でAdGuardをコンテナ内で実行することで、選ばれるソースはクライアントが問い合わせたものと異なる場合があります。
ss -lunp | grep :53どのゲームにいるかを示します。0.0.0.0:53のリスナーはワイルドカードの場合です;10.6.0.1:53のリスナーはすでに答えを固定しています。ソケットを読む方がYAMLを読むより速く、最後に保存されたものではなく、実際に実行されているものを反映します。
bind_hosts が実際に制御するもの
AdGuard Home のdns.bind_hostsは、DNSリスナーが使用するローカルアドレスのリストです。出荷時のデフォルトはワイルドカードで、これはすべてのローカルアドレスで受け入れ、カーネルが返信ごとに送信元を選択することを意味します。ワイルドカードをクライアントが問い合わせるアドレスに置き換えると、ソケットが変更され、それに伴いすべての回答の送信元アドレスも変更されます。
リストには複数のエントリを含めることができ、これは二つのネットワークにサービスを提供するリゾルバで重要です。10.6.0.1そして192.168.1.10をリストすると、二つのバインドされたソケットが作成され、どちらかに到着したクエリは、その到着したアドレスから回答されます。これはほとんどの人がワイルドカードで既に提供されると思っている動作です。
YAMLはプレーンであり、その中のアドレスはあなたのトンネルクライアントが使用するように指示されたものであり、ホストの主要なアドレスではありません:
dns:
bind_hosts:
- 10.6.0.1
port: 53なぜ一つのリゾルバの二つのインストールが異なる動作をするのか
この文脈で「プラグイン管理」とは、リゾルバーが別のパッケージによってインストールされ、監視されていることを意味します:ルーターファームウェアパッケージ、NASパッケージ、またはホームオートメーションのアドオンなどです。そのパッケージは通常、AdGuard HomeのYAMLの独自コピーを配布し、自動スケジュールでプロセスを再起動します。一方、スタンドアロンインスタンスは、ベンダー提供のバイナリやコンテナであり、自分で設定します。いずれの場合も、同じ上流リストと同じフィルターリストを読み込んでいても、二つの独立したプロセスがあり、それぞれ別の設定ファイルとバインドの選択肢を持つことになります。一方が特定のトンネルアドレスにバインドし、もう一方がワイルドカードを継承することができ、ウェブインターフェースの見た目はどちら側から見ても同じです。
だから「移行前には同じリゾルバが動作していた」ということは、現在のバインディングについて何も証明しません。ソケットを確認し、次に実際に実行中のプロセスが読み込んでいる設定ファイルを確認してください。他のディレクトリにある古いコピーが、編集が効果を持たないように見える一般的な理由です。
それをピンで留めてから、トンネル側からテストしてください
変更bind_hostsトンネルアドレスに接続し、サービスを再起動して、ソケットが移動したことを確認します:ss -lunp | grep :53今は表示されるはずです10.6.0.1:53およびワイルドカードの入力なし。もしそれでも表示される場合0.0.0.0、実行中のプロセスは、あなたが編集したファイルを読み込んでいません。
それからクライアントからテストしてください、なぜならそれが唯一重要な側だからです。クエリはdig @10.6.0.1 example.comユーザーが実行する経路を実行し、ホスト上でのキャプチャを行いますtcpdump -ni wg0 udp port 53ワイヤ上で返信の送信元アドレスを表示します。クライアントのリゾルバ設定のアドレスと比較してください。それらが一致すると、タイムアウトの原因はもう謎ではなくなります。
ip route get 10.6.0.2残りの奇妙な点を説明します。なぜなら、クライアントに返す際にホストが使用するインターフェースと送信元を表示するからです。その出力がLANインターフェースを示す場合、バインドの変更だけでは完全な修正にはならず、次に確認すべきはルーティングテーブルです。
バインド設定で修正できないこと
リスナーのピン固定は、トンネルサブネットを除外するアクセスリスト、クエリは許可するが返信は許可しないファイアウォールルール、またはWireGuardプールへのルート不足を修復することはできません。それらは送信元アドレスより前または後で失敗し、それぞれ異なる管理者が関わります。
また、変更できませんリゾルバがどの上流に転送するかプライベート名に対してリバインディング保護がプライベートな回答を拒否するかどうか、またはクライアントが自身の検索ドメインをどのように適用するか。それらは別々の制御です。返信元が間違っている場合はバインドアドレスを変更し、そうでない場合は別のものを変更してください。