ISP が DNS をハイジャックしていた

ホームラボのコンテナが 1 つのサイトに到達できなかった。DNS の応答は ISP 自身を指していた。Hegde が証拠を順にたどり、Unbound、DNSSEC、DoH が何を守れて何を守れないのかを明らかにする。

日本語
コピー
终端里执行 curl ipinfo.io 查询一个 IP,返回结果显示归属 org 为 AS24309 Atria Convergence Technologies,即印度宽带运营商 ACT Fibernet,机房城市为班加罗尔

ある退屈な土曜日の午後、homelab のいくつかの問題を片付けることにした。そのひとつが、Podman コンテナから外部サイトにどうしても接続できない、というものだった。

ほぼ即座に「Site cannot be reached」が出た。DNS の設定が怪しいと踏んで、そのドメインに対して dig を実行した。Google DNS、Cloudflare と、いくつかのリゾルバを片っ端から試した。ほとんどが同じ IP アドレスを返す。ところが Cloudflare の DoH エンドポイントで試すと、まったく別の IP アドレスが返ってきた。

「は?」——これがそのときの率直な反応だった。

最初の DNS 解決で得た IP の所有者を調べてみると、出てきたのはよりにもよって自分の ISP だった。そこでようやく、ISP が DNS クエリをハイジャックし、改ざんされた IP アドレスを返していることに気づいた。

平文の DNS クエリ。返ってきたのは ISP の IP アドレス

同じクエリを Cloudflare の DoH エンドポイント経由で実行。返ってきたのは本物の IP アドレス

IP 所有者の照会結果。改ざんされたアドレスは自分の ISP のものだった

明らかな解決策は DoT(DNS over TLS)か DoH(DNS over HTTPS)だ。このことをポストしたら、なぜかバズった。

だがリプライを眺めていると、誤解や疑問が少なからず見つかった。いちいち返信するのは無理だ。

というわけで、この記事でそのいくつかに答えるとともに、いくつかの誤解を解いておきたい。

Unbound を自前で立てているから安全

知らない人もいるかもしれないが、Unbound は要するに DNS リゾルバで、Cloudflare が 1.1.1.1 で動かしているものと似ている。違いは、ローカルで動かせることだ。ルートサーバーから始めて、そのドメインの権威サーバーにたどり着くまで DNS サーバーを順に問い合わせ、ドメインの IP アドレスを特定する。

問題はまさにそこにある。DNS 解決は 1 本の接続で完結しない。リゾルバが IP アドレスを特定するには複数の DNS サーバーと通信する必要があり、そうしたクエリは伝統的に平文 DNS、たいていは UDP で送られる。つまり、そう、ISP はあなたの DNS トラフィックを覗き見ることも改ざんすることもできる。

ただし、Unbound に forward-zone を設定する手はある。こうすると Unbound は自分で DNS クエリを解決せず、別の DNS リゾルバに転送する。転送先が DoT に対応していれば、その間の接続は暗号化され、ISP が転送中の DNS クエリを勝手に覗いたり改ざんしたりはできなくなる。

DNSSEC を使えばいい

ここでの防御は DNSSEC だと思っている人がいる。無理もない。名前からして DNS と Security だ。ある意味その通りだが、DNSSEC が担うのは検証であって暗号化ではない。

DNSSEC は DNS トラフィックをリゾルバに送る前に暗号化するものではない。暗号学的な署名によって、DNS データが本物で改ざんされていないことを検証する。問題は残ったままだ。DNS トラフィックは転送中も暗号化されていない。つまり ISP は相変わらず覗き見できるし、応答に手を加えることもできる。

しかも DNSSEC の検証が機能するには、問い合わせるドメイン側で DNSSEC が正しく設定され、有効な署名と信頼の連鎖が存在している必要がある。ここにもうひとつ問題がある。2026 年 10 月の Defaults.Exposed 調査によれば、評価対象ドメインのうち有効かつ完全に検証可能な DNSSEC チェーンを持つのは 7.03% にすぎない。

改ざんされた応答が DNSSEC の検証を通らなければ、リゾルバは偽の IP アドレスを渡す代わりに SERVFAIL を返す。

DoH と DoT は改ざんを防げない

その通り。DoT と DoH は、クエリの送り先の DNS リゾルバを信頼することを前提にしている。接続を暗号化するので、ISP が転送中の DNS トラフィックを勝手に覗いたり改ざんしたりはできない。だが、リゾルバ自身が応答に細工をしないという保証はない。DNS サーバーの運営者を依然として信頼していることに変わりはない。

そもそも ISP にはどのサイトか見えている

確かに。通常のインターネットトラフィックは TLS で暗号化されるが、ISP は TLS ハンドシェイク時にホスト名(SNI)を見ることができる。宛先 IP だけでどのサイトか分かることもある。

もちろん、トラフィックを VPN トンネル経由にすれば別だ。自分は Tailscale の exit node 機能で Mullvad を使っている。

とはいえ、これでは信頼の一部を VPN プロバイダに移しただけにすぎない。それはまた別の話だ。

で、自分の構成はどうなっているのか

Pi-hole/AdGuard は 3 年以上使っている。振り返れば、セルフホストに初めて触れたきっかけがこれだった。

だが、すべてのコンテナをローカル DNS サーバー経由にしていないのには、もうひとつ理由がある。コンテナを更新するとき、何か問題が起きて DNS サーバーが落ちると、それに依存する他のコンテナの DNS 解決まで巻き添えにしたくない。だから一部のコンテナには、外部 DNS リゾルバをフォールバックとして用意している。

現在、DNS には AdGuard を使っていて、上流の DNS クエリは dnscrypt-proxy が DNSCrypt で処理している。だから DNS トラフィックは転送中も暗号化されている。DNS 障害がどうしても許されないコンテナには、Cloudflare をフォールバックとして設定してある。とはいえ、プライマリ DNS は今もローカルの AdGuard だ。

サーバーでは NixOS も動かしている。興味があれば、dotfiles はオープンソースだ。

出典: Karthikey Hegde's Blog← ホームへ戻る