スプリットホライズン DNS とは何か(systemd-resolved の文脈で)
スプリットホライズン DNS(Split-Horizon DNS)は、クエリの送信元ネットワークやインターフェースに応じて、同じドメイン名に対し異なる応答を返す設計手法です。社内ネットワークからのクエリには内部 IP を、インターネット側からは公開 IP を返す構成が代表的なシナリオです。
この分離を実装する方法として、かつては dnsmasq を別途立てたり、/etc/hosts に手書きのエントリを積み重ねたりすることが多く行われていました。しかし Ubuntu 20.04 以降・RHEL 8 以降・Arch Linux など主要ディストリビューションで標準の名前解決スタブリゾルバとして採用された systemd-resolved は、ドメインルーティング(DNS domain routing)という仕組みを標準で持っており、追加ソフトウェアなしにスプリットホライズンを構成できます。
本記事では、このドメインルーティング機能を使って本番の内部 DNS を外部 DNS から分離し、フォールバック動作を確認するまでの手順を一本で整理します。
systemd-resolved がドメインルーティングを処理する仕組み
systemd-resolved はポート 53 ではなく 127.0.0.53:53 でリクエストを受け付けるスタブリゾルバです。アプリケーションや NSS はこのスタブに問い合わせ、systemd-resolved が実際の上位 DNS サーバへ転送します。
ドメインルーティングの核となるのが、設定ファイルの Domains= ディレクティブです。ここに ~(チルダ)プレフィックス付きでドメインを記述すると、そのドメインへのクエリを特定のインターフェース(リンク)に紐付いた DNS サーバへ転送します。チルダなしのエントリは検索ドメイン(サフィックス補完)として機能し、ルーティングには影響しません。
ルーティング優先度は、より具体的なドメイン名ほど優先されます。たとえば ~corp.example.com と ~example.com が共存する場合、host.corp.example.com へのクエリは前者のルールに従います。いずれにもマッチしないクエリは、グローバル設定または ~.(ドット単体)で指定されたキャッチオール DNS に転送されます。
設定ファイルの構造と主要パラメータ
systemd-resolved の設定は大きく2か所に分かれます。
/etc/systemd/resolved.conf(または/etc/systemd/resolved.conf.d/*.conf):グローバル設定。全インターフェースに共通の DNS サーバやフォールバック DNS、DNSSEC ポリシーを記述します。/etc/systemd/network/*.network:インターフェース単位の設定。networkd が管理するリンクに対し、[Network]セクションでDNS=とDomains=を指定します。NetworkManager 環境では、nmcliで設定した内容が同様の効果を持ちます。
主要パラメータを以下に整理します。
DNS=:上位 DNS サーバの IP アドレス(スペース区切りで複数指定可)。FallbackDNS=:プライマリ DNS が応答しない場合に使用するフォールバック(resolved.confのグローバル設定のみ有効)。Domains=:検索ドメインおよびルーティングドメイン。~example.internalのようにチルダ付きで指定するとルーティング専用となり、検索サフィックス補完には使われません。DNSSEC=:no/allow-downgrade/yesの3段階。内部 DNS が DNSSEC 非対応の場合はnoまたはallow-downgradeを選択します。Cache=:キャッシュを有効にするかどうか(デフォルトyes)。
本番 DNS 分離の設定手順
ここでは「corp.example.internal ドメインを社内 DNS(192.168.10.53)で解決し、それ以外はパブリック DNS(1.1.1.1)で解決する」という想定例を使って手順を示します。実際のドメインやアドレスは環境に合わせて置き換えてください。
手順 1:インターフェース設定ファイルの作成
社内ネットワークに接続するインターフェース(想定例では eth0)向けに、以下の内容でファイルを作成します。
# /etc/systemd/network/10-internal.network
[Match]
Name=eth0
[Network]
DNS=192.168.10.53
Domains=~corp.example.internal ~example.internal
チルダ付きの Domains= は「このリンクの DNS へルーティングするドメイン」を宣言するだけで、検索サフィックスとしては機能しません。社内ホスト名をサフィックス補完で引きたい場合は、チルダなしのエントリを別途追加します。
手順 2:グローバル設定でフォールバック DNS を指定
/etc/systemd/resolved.conf.d/99-fallback.conf を新規作成し、下記を記述します。既存の resolved.conf を直接編集するとパッケージ更新時に上書きされる可能性があるため、ドロップイン方式が推奨です。
[Resolve]
DNS=1.1.1.1 8.8.8.8
FallbackDNS=9.9.9.9
DNSSEC=allow-downgrade
手順 3:サービスの再起動と /etc/resolv.conf の確認
sudo systemctl restart systemd-resolved
sudo systemctl restart systemd-networkd # networkd 環境の場合
ls -la /etc/resolv.conf
/etc/resolv.conf が /run/systemd/resolve/stub-resolv.conf へのシンボリックリンクになっていることを確認します。別ファイルへのリンクや実ファイルの場合、systemd-resolved を経由しないクライアントが存在する可能性があります。
動作検証とフォールバックの確認
設定後は resolvectl コマンドで状態を確認します。systemd-resolve コマンドは非推奨となっており、2026 年時点の現行ディストリビューションでは resolvectl に統一されています。
インターフェース単位のルーティング確認
resolvectl status eth0
出力の DNS Domain 行にチルダ付きで設定したドメインが表示されていれば、ルーティング設定が反映されています。
名前解決の経路確認
# 内部ドメインのクエリが社内 DNS に向くか
resolvectl query host.corp.example.internal
# 外部ドメインがパブリック DNS に向くか
resolvectl query example.com
resolvectl query は解決に使ったサーバと DNSSEC 検証結果を表示するため、経路の確認に適しています。nslookup や dig @127.0.0.53 もスタブを経由したクエリに使えますが、使用 DNS サーバの追跡には resolvectl query が明確です。
フォールバック動作の確認(想定例)
プライマリ DNS を意図的に到達不能にする検証は本番環境では行えないため、ステージング環境で確認することを推奨します。想定例として、ファイアウォールルールで 192.168.10.53 への UDP/TCP 53 番を一時ブロックすると、systemd-resolved はタイムアウト後に FallbackDNS で指定したサーバへ切り替えます。切り替えタイミングは resolvectl statistics の Fallback DNS カウントで確認できます。
キャッシュが残っていると切り替えが見えにくいため、フォールバック試験前に resolvectl flush-caches を実行します。
切り戻し・よくあるつまずきと 2026 年の現行環境差分
設定を元に戻す場合は、作成したドロップインファイルと .network ファイルを削除し、systemd-networkd と systemd-resolved を再起動するだけです。/etc/systemd/resolved.conf 本体を編集した場合は、バックアップから復元します。
よくあるつまずき
/etc/resolv.confが実ファイルのまま:NetworkManager や他ツールが/etc/resolv.confを管理している環境では、systemd-resolved の設定が上書きされることがあります。ls -la /etc/resolv.confでシンボリックリンクの向き先を確認し、必要に応じてln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.confで再設定します。- DNSSEC による内部ドメインの解決失敗:内部 DNS が DNSSEC 非対応の場合、
DNSSEC=yesにすると内部ドメインのクエリがSERVFAILを返します。DNSSEC=allow-downgradeまたはnoに変更することで回避できます。 - チルダなしのルーティング設定:
Domains=corp.example.internal(チルダなし)は検索ドメインとして機能しますが、そのドメイン専用の DNS ルーティングとしては期待どおりに動作しないことがあります。ルーティング専用には必ずチルダを付けます。 - NetworkManager 環境でのリンク設定:RHEL 9 / Rocky Linux 9 など NetworkManager が主体の環境では
.networkファイルではなくnmcli connection modify <con> ipv4.dns "192.168.10.53" ipv4.dns-search "~corp.example.internal"で設定します。nmcli経由で設定した内容は内部的に systemd-resolved のリンク設定として渡されます。
2026 年時点の現行環境での差分
Ubuntu 24.04 LTS(Noble)は systemd 255 系を採用しており、resolved.conf の DNSOverTLS= が実用的な水準で機能します。内部 DNS が DoT をサポートしている場合は有効化を検討できます。また、MulticastDNS= はデフォルト resolve(送信なし・受信のみ)に変更されており、意図せず mDNS クエリが外部へ漏れるリスクが低減されています。
RHEL 9 / Rocky Linux 9 では、systemd-resolved はオプション扱いで NetworkManager が dnsmasq プラグインを通じて同様のスプリットホライズン機能を提供しています。resolvectl status を実行した際に Current DNS Server が表示されない場合は、systemd-resolved が有効化されていない可能性があるため、systemctl enable --now systemd-resolved の実行と /etc/resolv.conf のシンボリックリンク設定を合わせて確認します。
なお、systemd-resolve --status コマンドは systemd 249 以降で非推奨アナウンスがなされており、ディストリビューションによってはエイリアスが提供されなくなっています。スクリプトやドキュメントに systemd-resolve が残っている場合は resolvectl へ移行することを推奨します。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
PR・広告
Linuxで動かしながら学ぶTCP/IPネットワーク入門(Amazon)
IPアドレス・ルーティング・名前解決などネットワークの基礎をLinux上で手を動かして学べる入門書。
※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。
