stub-listener のままでは本番運用で何が問題になるのか
Ubuntu 20.04 以降や Fedora 系のディストリビューションでは、インストール直後から systemd-resolved が起動しており、/etc/resolv.conf は 127.0.0.53 を指すシンボリックリンクになっています。このアドレスが stub-listener と呼ばれる内部プロキシで、アプリケーションの DNS クエリを受け取り、設定済みのアップストリームサーバへ転送します。
デスクトップ用途や開発環境であれば、DHCP で受け取ったアップストリームがそのまま使われるため支障はありません。ところが本番サーバでは話が変わります。運用現場でよく見られる問題の例は次の3つです。
- 社内の権威 DNS サーバ(
10.x.x.xなど)へ直接クエリを送りたいのに、DHCP 由来のアップストリームが優先されてしまう - 特定ドメイン(
.internalなど)だけをプライベート DNS に向けたい split-DNS が機能していない - コンテナや仮想マシンのネットワークインターフェースが複数あり、インターフェースごとに名前解決先を分けたい
これらはいずれも、stub-listener の上流となるリゾルバを意図どおりに設定できていないことが根本原因です。resolv.conf を直接書き換えても systemd-resolved が上書きするため、設定が一時的にしか有効にならないケースも頻発します。
systemd-resolved の動作モードと resolv.conf の関係を整理する
設定を変更する前に、/etc/resolv.conf が現在どのモードで管理されているかを把握しておく必要があります。systemd-resolved が作成するシンボリックリンクには主に2種類あります。
- stub モード:
/run/systemd/resolve/stub-resolv.confへのリンク。nameserver 127.0.0.53が書かれており、すべてのクエリが stub-listener 経由になります。 - uplink モード(推奨):
/run/systemd/resolve/resolv.confへのリンク。systemd-resolvedが把握している実際のアップストリームアドレスが書かれます。
現在の状態は ls -la /etc/resolv.conf で確認できます。リンク先が stub-resolv.conf であれば stub モード、resolve/resolv.conf であれば uplink モードです。ファイル自体が通常ファイルであれば、systemd-resolved の管理外になっており、競合が起きやすい状態です。
多くの本番運用では stub モードを維持しつつ、アップストリームを明示的に設定する方針が安定しています。DNSSEC 検証や DNS-over-TLS(DoT)を systemd-resolved のレイヤで処理したい場合は特にそうです。stub-listener を無効化(DNSStubListener=no)する選択肢もありますが、それはポート競合が発生している特殊なケースに限定するのが望ましいです。
本番 DNS リゾルバへの切り替え手順
resolved.conf でアップストリームを明示する
メインの設定ファイルは /etc/systemd/resolved.conf です。ただし、このファイルをそのまま編集するより、/etc/systemd/resolved.conf.d/ 以下にドロップイン設定ファイルを置く方が管理しやすく、パッケージ更新時の上書きリスクも避けられます。
# /etc/systemd/resolved.conf.d/upstream.conf
[Resolve]
DNS=10.0.0.53 10.0.0.54
FallbackDNS=1.1.1.1
Domains=~.
DNSSEC=allow-downgrade
DNSOverTLS=opportunistic
DNS= に社内の権威 DNS サーバを列挙します。FallbackDNS= はプライマリが応答しない場合のバックアップです。Domains=~. はすべてのドメインをこのインターフェースのリゾルバ経由にする指定で、グローバルサーチドメインの設定と組み合わせると意図しない名前解決になる場合があるため注意してください。
設定を反映するには systemctl restart systemd-resolved を実行します。reload では一部のオプションが反映されないため、再起動が確実です。
NetworkManager 連携環境での注意点
NetworkManager が動作している環境では、接続プロファイルの DNS 設定が systemd-resolved へ渡されることがあります。resolved.conf に書いた値を NetworkManager が上書きするケースがあるため、nmcli connection show <接続名> | grep dns で競合がないかを確認しておくと安心です。NetworkManager 側で dns=systemd-resolved が明示されていれば、systemd-resolved が統合管理の窓口になります。
stub-listener の動作確認とトラブルシュート
設定変更後は resolvectl status でグローバル設定とインターフェースごとの状態を確認します。2022 年以降のディストリビューションでは systemd-resolve --status は非推奨になっており、resolvectl が標準コマンドです。
出力の Global セクションに DNS Servers: として意図したアップストリームのアドレスが表示されているかを確認します。インターフェースセクションに DNS Domain: ~. が表示されていれば、そのインターフェース経由での全ドメイン転送が有効になっています。
実際の名前解決の動作確認には resolvectl query example.com を使います。dig や nslookup は 127.0.0.53 を経由しない場合があり、systemd-resolved の挙動を直接確認するには resolvectl query の方が適切です。
stub-listener がポート 53 でリッスンしているかどうかは ss -tlnp | grep :53 で確認できます。systemd-resolved のプロセスが 127.0.0.53:53 を保持していれば正常です。もしバインドに失敗しているログが journalctl -u systemd-resolved に出ていれば、他のプロセス(bind、unbound、旧来の dnsmasq)とのポート競合を疑います。
split-DNS 設計の選択肢
社内システムのドメインだけをプライベート DNS に送り、それ以外はパブリック DNS へ転送する split-DNS 構成は、systemd-resolved の Domains= 設定で実現します。
最もシンプルな方法は、NetworkManager の接続プロファイルにドメインを紐付けることです。たとえば VPN 接続プロファイルに ipv4.dns-search corp.internal と設定すると、.corp.internal ドメインへのクエリがその VPN インターフェースの DNS にルーティングされます。resolvectl status で各インターフェースの DNS Domain 欄に反映されているかを確認するのが確実です。
ドロップイン設定ファイルで直接指定する場合、インターフェース単位での細かい制御は resolved.conf のグローバル設定では行えません。インターフェースごとの DNS 設定は NetworkManager、systemd-networkd、または resolvectl dns <インターフェース名> <DNSアドレス> コマンドで行います。ただし resolvectl dns による変更は永続化されないため、起動スクリプトや NetworkManager ディスパッチャスクリプトで自動適用する仕組みが必要です。
Domains=~corp.internal ~internal のように ~ プレフィックスを付けると、そのドメインへのクエリを「このリゾルバへルーティングする」という routing domain の指定になります。~.(チルダとドット)はすべてのドメインを意味するため、グローバル設定で ~. を指定すると、インターフェースごとの routing domain よりもグローバル設定が優先される場合があり、意図した split-DNS が崩れることがあります。設計段階で優先順位のルールを把握しておくことが重要です。
2026 年現行環境での差分と運用上の注意点
Ubuntu 24.04 LTS(Noble Numbat)では systemd 255 系が標準になっており、resolved.conf の MulticastDNS= と LLMNR= のデフォルト値が変更されています。mDNS はデフォルトで resolve(送信はしないが応答は受信する)に設定されているため、コンテナやクラスタ環境では予期しないマルチキャスト応答が届く場合があります。不要であれば MulticastDNS=no を明示的に設定します。
RHEL 9 / AlmaLinux 9 / Rocky Linux 9 では systemd-resolved はデフォルトで無効になっており、resolv.conf は NetworkManager が直接管理しています。RHEL 10 ベータ時点でも同様の方針が維持されています。Red Hat 系では systemctl enable --now systemd-resolved で有効化したうえで、nmcli general show で NetworkManager の DNS モードを確認してから設定を進める必要があります。
Kubernetes ノードとして使用するホストでは、kubelet が resolv.conf の内容をコンテナに引き継ぐ挙動があります。stub-listener の 127.0.0.53 はコンテナのネットワーク名前空間からはアクセスできないため、ノードで stub モードが有効な場合は --resolv-conf フラグで uplink モードの /run/systemd/resolve/resolv.conf を指定するのが現行の推奨手順です。kubeadm のドキュメントでも 2024 年以降この設定例が明記されています。
DNS-over-TLS を有効にする場合、DNSOverTLS=yes(厳格モード)と DNSOverTLS=opportunistic(失敗時は平文にフォールバック)の2段階があります。本番環境では証明書検証まで含めて動作確認を済ませてから yes に切り替えることを現場では推奨します。resolvectl query --type=A example.com の出力に Data was acquired via local or encrypted transport と表示されていれば、DoT が実際に機能していることを確認できます。
切り戻しが必要になった場合は、/etc/systemd/resolved.conf.d/ 配下のドロップインファイルを削除し systemctl restart systemd-resolved を実行することで、デフォルト設定に戻せます。resolv.conf のシンボリックリンクを手で書き換えた場合は resolvconf --enable-updates や systemctl restart systemd-resolved でリンクが再生成されるため、手動ファイルが残っていると競合することに注意してください。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
PR・広告
Linuxで動かしながら学ぶTCP/IPネットワーク入門(Amazon)
IPアドレス・ルーティング・名前解決などネットワークの基礎をLinux上で手を動かして学べる入門書。
※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。
