2026年6月5日

2026年6月5日

ブラウザのDNSキャッシュと systemd-resolved のキャッシュ整合性を取る方法|Linuxで食い違う理由と、消す順番・確かめ方

Linuxのデスクトップや開発用マシンで、ターミナルでは新しいIPが返るのにブラウザだけ古いサーバーにつながる場合、ブラウザのDNSキャッシュと systemd-resolved のキャッシュが食い違っています。整合性を取るには、どの層が古い値を持っているかを確認したうえで、上流側の systemd-resolved から先に消し、そのあとブラウザのキャッシュと接続を消す、という順番が要点です。この記事では、食い違いが起きる仕組み、各層の値の確かめ方、消す順番、食い違いを起こしにくくする設定を説明します。ブラウザごとのキャッシュの消し方の詳細ではなく、Linux上での2つのキャッシュの関係に絞った内容です。

なぜ食い違うのか

Linux上のブラウザがホスト名を解決するとき、経路はおおむね次のようになります。

  1. ブラウザ自身のホストキャッシュ(ChromeやFirefoxが独自に持つ)
  2. OSの名前解決(glibcとNSS)。/etc/hosts や /etc/nsswitch.conf の設定に従う
  3. systemd-resolved のキャッシュ(127.0.0.53 のスタブリゾルバ、またはNSSの resolve モジュール経由)
  4. 上流のDNSサーバー(ルーター、ISP、社内DNSなど)

ブラウザは、2〜4を通って得た結果を自分のキャッシュにも保存します。したがって、ある時点で systemd-resolved が古い値を持っていれば、ブラウザのキャッシュを消しても、また同じ古い値を受け取ります。逆に、systemd-resolved だけを消しても、ブラウザが自分のキャッシュや開いたままの接続を使っている間は古いサーバーにつながります。

もう一つの原因が、ブラウザの「セキュアDNS」(DNS over HTTPS、DoH)です。これが有効だと、ブラウザは2〜4を通らず、設定されたDoHサービスへ直接問い合わせます。この場合、OS側をいくら整えても、ブラウザとOSは別々の経路で別々の結果を持つことになります。

手順1:systemd-resolved が使われているか確認する

まず、手元の環境で systemd-resolved が名前解決を担っているかを確認します。

systemctl is-active systemd-resolved
ls -l /etc/resolv.conf
grep '^hosts:' /etc/nsswitch.conf

/etc/resolv.conf が /run/systemd/resolve/stub-resolv.conf へのリンクで、中身が nameserver 127.0.0.53 なら、OSの問い合わせは systemd-resolved を通ります。nsswitch.conf の hosts: 行に resolve があれば、NSS経由でも使われます。どちらにも該当しなければ、この記事の前提とは別の構成なので、/etc/resolv.conf に書かれたDNSサーバーと、nscd などほかのキャッシュの有無を確認してください。

手順2:各層の値を並べて比べる

食い違いを解消する前に、どの層が古いのかを確かめます。下から順に見ていきます。

# 権威DNSサーバー(正しい値)
dig +short NS example.com
dig +short +norec @ns1.example-dns.net www.example.com A

# 上流のDNSサーバー(resolvectl status で表示される Current DNS Server)
resolvectl status
dig +short @192.0.2.53 www.example.com A

# systemd-resolved
resolvectl query www.example.com

# OSの名前解決(hosts ファイルを含む)
getent ahosts www.example.com

ns1.example-dns.net と 192.0.2.53 は、それぞれ実際のネームサーバー名と上流DNSのアドレスに置き換えてください。resolvectl query の出力の末尾には、結果がキャッシュから来たのかネットワークから来たのかが表示されます(Data from: cache のような行。表記は systemd のバージョンにより異なります)。

ブラウザ側の値は、次の方法で確認できます。

  • Chrome・Edge:chrome://net-internals/#dns(Edgeは edge://)で、ホスト名を入力して解決結果を見る。または開発者ツールのネットワークタブで、実際の接続先アドレスを見る
  • Firefox:about:networking#dns でキャッシュの一覧を見る。DoHで解決した項目かどうかも表示される

どこから値が変わっているかで、古い値を持っている層が分かります。たとえば、上流DNSは新しく、resolvectl query が古ければ systemd-resolved のキャッシュ、resolvectl query は新しくブラウザだけ古ければブラウザ側の問題です。getent だけが違うなら、/etc/hosts に古い行が残っていないかを確認します。

手順3:上流から順に消す

整合性を取るときは、上流側から消していきます。下流(ブラウザ)から先に消すと、上流に残った古い値をすぐに取り直してしまうためです。

まず systemd-resolved のキャッシュを消します。

resolvectl flush-caches
resolvectl statistics

statistics の Cache の欄で、現在のキャッシュ件数(Current Cache Size)が0付近に戻っていれば消えています。次に、resolvectl query www.example.com を実行し、新しい値がネットワークから取得されたことを確かめます。上流のDNSサーバー自体が古い値を返している場合は、ここで消しても同じ値が戻ってくるので、上流のTTLが切れるのを待つか、問い合わせ先を変えて確認します。

続いてブラウザ側を消します。

  • Chrome・Edge:net-internals の DNS で「Clear host cache」、Sockets で「Flush socket pools」を実行する。ソケットも消すのは、開いたままの接続が古いサーバーとの通信を続けるため
  • Firefox:about:networking#dns で「Clear DNS Cache」を実行する。ブラウザを再起動しても消える

ボタン名や画面構成はブラウザのバージョンによって変わることがあります(2026年10月現在)。最後にページを再読み込みし、開発者ツールで接続先アドレスが新しいサーバーになったことを確認します。

手順4:DoHが原因の食い違いを解消する

手順3を行ってもブラウザだけ結果が違う場合は、ブラウザのセキュアDNSを確認します。Chromeでは設定の「プライバシーとセキュリティ」内のセキュリティの項目、Firefoxでは設定のプライバシーとセキュリティにあるDNS over HTTPSの項目で状態を確認できます。項目の位置や名称は変わることがあります。

FirefoxのDoHの動作は、about:config の network.trr.mode でも確認できます。0と5はDoHを使わない、2はDoHを優先しつつ失敗時にOSへ戻す、3はDoHのみ、という意味です。切り分けの間だけDoHを使わない設定にすると、ブラウザもOSと同じ経路で問い合わせるようになり、systemd-resolved の結果と揃います。

VPNや社内ネットワークでは、systemd-resolved が「この社内ドメインは社内DNSへ」という振り分け(リンクごとのDNS設定)を行っていることがあります。ブラウザがDoHを使うと、この振り分けを通らないため、社内向けのホスト名がブラウザだけ解決できない、という食い違いになります。resolvectl status で各リンクに設定されたドメインを確認し、社内ドメインを使う環境ではDoHの設定を管理者の方針に合わせてください。

食い違いを起こしにくくする

普段から次の点を意識しておくと、食い違いの調査に時間を取られにくくなります。

  • サーバー移転のような計画作業では、事前にDNS側のTTLを短くしておく。systemd-resolved もブラウザも、TTLを目安に保持時間を決めるため、古い値が残る時間が短くなる
  • 開発用に /etc/hosts を書き換えたら、作業後に元に戻し、systemd-resolved とブラウザの両方を消す
  • ブラウザのDoHを使うかどうかを決めておく。使う場合は、OS側で確認した結果とブラウザの結果が違うことがあると理解しておく
  • systemd-resolved の設定(/etc/systemd/resolved.conf)の Cache= で、キャッシュを無効にしたり、否定応答だけキャッシュしないようにしたりできるが、問い合わせが増えるため、常用より一時的な切り分けに向いている

設定ファイルを変更するときは、事前にバックアップを取り、変更後に sudo systemctl restart systemd-resolved で反映して、resolvectl status で状態を確認してください。

キャッシュの中身を詳しく見たいとき

resolvectl query では1件ずつしか確認できません。systemd-resolved が保持しているキャッシュ全体を見たい場合は、プロセスにシグナルを送ると、キャッシュの内容がログに出力されます。

sudo pkill -USR1 systemd-resolved
journalctl -u systemd-resolved -n 200 --no-pager

対象のホスト名がどの値で残っているかを確認できます。新しいバージョンの systemd では、resolvectl にキャッシュを表示するサブコマンドが用意されている場合もあります。ログには閲覧したサイトのホスト名が含まれるため、共有のマシンでは扱いに注意してください。

まとめ

  • ブラウザは systemd-resolved から得た結果を自分のキャッシュにも保存するため、片方だけ消しても食い違いは解消しない
  • dig、resolvectl query、getent、ブラウザの内部ページで各層の値を並べ、どこが古いかを確かめる
  • 消すときは上流の systemd-resolved から先に、そのあとブラウザのホストキャッシュとソケットを消す
  • ブラウザのDoHが有効だと、OSとは別経路になり、社内ドメインの振り分けも通らない
  • 計画作業ではTTLを事前に短くし、hostsの書き換えは作業後に戻す

お気軽にご相談ください

お見積りへ お問い合わせへ
▲