ルーターや端末のDNSをAdGuard Homeに向ける前に、知っておきたいことがあります。それは「広告がちゃんと消えるか」よりも先に、「設定を間違えたとき、家中の名前解決がどう止まるのか」「どうやって元に戻すのか」です。家庭内DNSは一度常用すると、Web閲覧・OS更新・コンテナのpull・スマート家電まで影響が連鎖します。便利になる前に、まず小さく壊して観測しておく価値があります。
この記事は、使い捨てのDocker環境でAdGuard Homeを起動し、名前解決を止める代表的な失敗条件をdigの実応答とコンテナログで再現した検証ログです。本番ネットワーク・既存DNS・ルーターには一切触れていません。広告ブロックの導入をすすめる記事ではなく、常用前に「失敗の見え方」と「戻し方」を確認するための観測記録です。
検証環境
- 実行場所: 某所ラボの使い捨て検証VM(Docker入り、ネットワークから隔離した専用ブリッジ)
- Docker: version 29.6.0
- AdGuard Home: イメージ
adguard/adguardhome:latest(起動時バージョン v0.107.77) - 計測ツール:
dig(dnsutils / bind9-dnsutils 9.18.49) - 隔離ネットワーク:
adg-verify-net(bridge) - 観測日時: 2026-06-26(UTC)
コンテナと専用ブリッジ、コンテナランタイムの挙動が前提になるため、ネットワーク不通かつDocker非搭載の環境では正直な検証ができません。今回は使い捨てVM+Dockerのレーンで実施しています。
準備:DockerとdigとAdGuard Home
まず隔離ネットワークと作業ディレクトリを作り、digを入れます。
# docker --version
# docker network create adg-verify-net
# mkdir -p /tmp/adg-lab/work /tmp/adg-lab/conf
# docker network ls --filter name=adg-verify-net
Docker version 29.6.0, build fb59821
設定項目 ID 設定項目 設定項目 設定項目
c1305d58b1ab adg-verify-net bridge local
# apt-get update && apt-get install -y dnsutils
# dig -v
設定ファイル AdGuardHome.yaml は、無人起動でDNSを53番で待ち受ける最小構成にしました。上流DNSは 9.9.9.9、bootstrapは 1.1.1.1 です。これを永続化ディレクトリ(ホスト側の conf)に配置します。
http:
address: 0.0.0.0:3000
users: []
dns:
bind_hosts:
- 0.0.0.0
port: 53
upstream_dns:
- 9.9.9.9
bootstrap_dns:
- 1.1.1.1
upstream_mode: load_balance
filtering:
protection_enabled: true
filtering_enabled: true
user_rules: []
filters: []
schema_version: 20
# docker run -d --name adg-verify --network adg-verify-net \
-v /tmp/adg-lab/work:/opt/adguardhome/work \
-v /tmp/adg-lab/conf:/opt/adguardhome/conf \
adguard/adguardhome:latest
# docker logs adg-verify | head -40
起動ログでは config_migrator がスキーマを順次アップグレードし、webapi: initializing まで進みます。ユーザー未設定のため認証は無効、という警告も出ます(検証用なので想定どおりです)。
(0) ベースライン:正常な名前解決
まず、AdGuard Home経由で普通に名前が引けることを確認します。コンテナIPを取り出し、そこへdigを投げます。
# 設定項目=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' adg-verify)
# dig @"$設定項目" example.com
;; ->>設定項目<<- opcode: 設定項目, status: 設定項目, id: 55198
;; flags: qr rd ra ad; 設定項目: 1, 設定項目: 2, 設定項目: 0, 設定項目: 1
;; 設定項目 設定項目:
example.com. 19 IN A 104.20.23.154
example.com. 19 IN A 172.66.147.243
;; Query time: 4 msec
;; 設定項目: <redacted-ip>#53(<redacted-ip>) (UDP)
応答は status: 設定項目、設定項目 設定項目 に example.com のAレコードが2件返り、最終行の ;; 設定項目: がコンテナのIPと #53 を指していました。ここが今回いちばん重要な読みどころです。「設定項目」行が「いま誰に問い合わせたか」を示すので、AdGuard Homeを通っているかどうかは、この行で判断できます。
(1) ブロックルールの未反映 → 適用後の差分
次に、カスタムルール ||doubleclick.net^ を入れる前後の応答差を見ます。停止 → user_rules に追記 → 再起動、という流れです。
# dig @"$設定項目" doubleclick.net +short # 適用前: 実在IPが返る
142.251.24.100
142.251.24.102
142.251.24.138
...
# dig @"$設定項目" doubleclick.net # 適用後
;; ->>設定項目<<- opcode: 設定項目, status: 設定項目, id: 641
;; 設定項目 設定項目:
doubleclick.net. 10 IN A 0.0.0.0
ここで覚えておきたいのは、AdGuard Homeのブロックは「エラーを返す」のではなく、今回の構成では「0.0.0.0」というアドレスを返してブロックする点です。設定項目 で応答が返ってくるので、dig の status だけ見ると正常に見えます。設定項目 設定項目 の中身まで見て初めて「ブロックされている」と分かります。逆に、ルールを書いたつもりが反映されていなければ、適用後も実在IPが返り続けます。差分は status ではなく 設定項目 の値で確認してください。
(2) 上流DNS誤設定 → 名前解決停止と復旧
家庭内DNSで最も影響が大きいのが、上流(フォワード先)の誤設定です。ここでは上流を意図的に到達できないアドレス 192.0.2.1(RFC 5737のテスト用で応答が返らない)に変えました。
# dig @"$設定項目" example.org +time=3 +tries=1
;; communications error to <redacted-ip>#53: timed out
; (1 server found)
;; no servers could be reached
AdGuard Home自体は53番で生きていてdigの宛先は見つかっているのに、上流から答えが返らないためタイムアウトし、最終的に「到達できるサーバーがない」で終わります。digの終了コードも 9(no servers reached)でした。「AdGuard Homeが落ちた」のと「上流が死んでいる」のは症状が似ていますが、前者は宛先自体に届かず、後者は宛先には届くが答えが返らない、という違いで切り分けられます。
復旧は上流を 9.9.9.9 に戻すだけです。ここで正直な制約を1つ。今回の記録では、上流を戻したあとの「設定項目に戻った」応答そのものはログに取得できていません(検証チェーンが上流断のタイムアウトで終了コード9を返した時点で出力が途切れたためです)。設定の戻し自体は実施していますが、復旧後応答の実物は未取得です。常用前には、戻したあとに必ず正常応答を一度digで確認する運用にしてください。
(3) 永続化あり/なし → 再起動後の保持差
Docker運用でありがちなのが、設定の永続化漏れです。ホストのconfをマウントしない使い捨てコンテナを別に立て、再起動前後でconfディレクトリを見比べました。
- 永続化なし: 起動直後も再起動後も
confディレクトリは空(保存済みYAMLなし=初期セットアップ待ちの状態) - 永続化あり(ホストの
confをマウント):AdGuardHome.yaml(約3.6KB)がそのまま残る
つまり、ボリュームを当てずに「Web UIで設定したから大丈夫」と思っていると、コンテナを作り直した瞬間に上流もブロックルールも消え、初期状態に戻ります。家庭内DNSとして常用するなら、workとconfの両方をホスト側に永続化するのが前提です。
(4) クライアントがAdGuardを経由していない
最後に、よくある勘違い「広告が消えない=ブロックリストが弱い?」の正体です。端末が実は別のDNSを見ているだけ、というケースを再現します。AdGuardを経由せず、外部リゾルバへ直接問い合わせました。
# dig @9.9.9.9 doubleclick.net | grep -E '設定項目|status'
;; ->>設定項目<<- opcode: 設定項目, status: 設定項目, id: 21206
;; 設定項目: 9.9.9.9#53(9.9.9.9) (UDP)
外部リゾルバ直なので doubleclick.net は実在IPが返り、ブロックは効きません。注目は ;; 設定項目: 行が 9.9.9.9#53 を指していることです。AdGuard Homeを通しているつもりでも、ここに自分のAdGuardのIPが出ていなければ、その端末はフィルタを通っていません。「広告が消えない」と感じたら、まずdigの設定項目行で経由先を確認するのが最短の切り分けです。
結果の早見表
| 構成 | digのSERVER行 | 応答 | 見え方・リスク |
|---|---|---|---|
| AdGuard経由・正常 | AdGuardのIP#53 | 設定項目 + 実在A | 正常。ここが基準 |
| AdGuard経由・ブロック適用 | AdGuardのIP#53 | 設定項目 + A 0.0.0.0 | statusは正常。ANSWERの値で判断 |
| 上流DNS誤設定 | AdGuardのIPには届く | timed out / no servers reached | 宛先は生きているが答えが返らない |
| 外部DNS直問い合わせ | 外部リゾルバのIP#53 | 設定項目 + 実在A | AdGuard非経由。ブロックが効かない |
| 永続化なしで再起動 | (再設定待ちで未稼働) | 設定消失 | conf空=初期化。上流もルールも消える |
失敗/制約/再現条件
- 上流復旧後の正常応答は未取得: 上流を 9.9.9.9 に戻す操作は行いましたが、戻したあとの
設定項目応答そのものは今回のログに残っていません。常用前には復旧後に必ずdigで再確認してください。 - ブロックは 0.0.0.0 応答方式: 今回の構成ではブロック時も
status: 設定項目で、設定項目が0.0.0.0になります。statusだけ見ると正常に見える点に注意。 - 応答先IP・TTLは観測時の値: 記録した実在IPやTTLはこの時点の値で、恒久的なものではありません。
- 隔離環境前提: 専用ブリッジ上の使い捨てVMで実施。本番のルーター・既存DNSには触れていません。
- 再現方法: 同じ
AdGuardHome.yamlと手順を、Docker入りの使い捨てVMで同順に流せば再現できます。検証後はコンテナ・ネットワーク・作業ディレクトリをすべて削除し、残存物がないことを確認しました。
常用してよい条件 / まだ常用しない条件
常用に進んでよいのは、次がそろったときです。
confとworkをホスト側に永続化し、コンテナ再作成後も設定が残ることを確認した- 上流DNSが死んだときの症状(timed out / no servers reached)を自分の目で見て、戻し方を手順化した
digの設定項目行で、対象端末が自分のAdGuardを経由していることを確認した
逆に、永続化を当てていない、上流断の戻し手順を決めていない、設定項目行での経由確認をしていない——このどれかが欠けるなら、ルーターのDNSをAdGuardに向けるのはまだ早い段階です。広告が消えるかどうかより先に、止まったときに自分で戻せる状態を作っておくことをおすすめします。
この検証を回している環境
この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。
ラボ構成のまとめを見る →