結論から言うと、LinuxのDNS設定は/etc/resolv.confを直接編集する前に、NetworkManager、Netplan、systemd-resolvedなど、どの仕組みが管理しているかを確認します。自動生成ファイルへ書いても再接続で消え、シンボリックリンクを壊すと名前解決全体が止まります。SSH接続中はバックアップ、別セッション、コンソールまたは帯域外管理経路を用意し、Ubuntuではnetplan tryを使います。ただしtimeout/cancel時にもロールバック失敗の既知事例があるため、復旧を前提にしません。
この記事の主対象は、Linux端末が問い合わせるDNSリゾルバーを確認・変更するDNSクライアント設定です。BINDをインストールして権威DNSや社内向け再帰リゾルバーを構築する作業とは別です。『Linuxで使っているDNSを知りたい』『固定DNSへ変えたい』『社内名だけ引けない』場合は、この順序で切り分けられます。
環境別の判断表
| 確認結果 | 主な管理方式 | 変更する場所 |
|---|---|---|
nmcli connection show --activeで接続が出る | NetworkManager | 接続プロファイルのipv4.dns/ipv6.dns |
Ubuntuで/etc/netplan/*.yamlがある | Netplan | 対象YAMLのnameservers |
/etc/resolv.confがstub-resolv.confへのリンク | systemd-resolved | Netplan、NetworkManager、networkd等の上流設定 |
resolvectl statusでリンク別DNSが出る | systemd-resolved | 恒久設定はリンクを管理するサービス |
| 通常ファイルで生成元の注記もない | 静的resolv.confの可能性 | 構成管理・DHCPフックを確認後に限定して編集 |
| 公開名は引けるが社内名だけ失敗 | VPN/スプリットDNS | 検索・ルーティングドメインとDNS priority |
/etc/resolv.confにnameserver 127.0.0.53だけが見える場合、それは外部DNSのアドレスではなくsystemd-resolvedのローカルスタブです。実際の上流DNSはresolvectl statusの「Current DNS Server」「DNS Servers」をリンクごとに確認します。ループバックアドレスを公開DNSへ置き換えないでください。
変更前に現在の設定を確認する
まず次のコマンドを一般ユーザーで実行します。表示だけのコマンドなので、設定は変わりません。存在しないコマンドがあっても別方式の可能性があるため、パッケージを闇雲に追加せず、使える結果を組み合わせて判断します。
readlink -f /etc/resolv.conf
ls -l /etc/resolv.conf
cat /etc/resolv.conf
resolvectl status
nmcli connection show --active
nmcli device show | grep -E 'GENERAL.CONNECTION|IP4.DNS|IP6.DNS|IP4.DOMAIN|IP6.DOMAIN'
readlinkで/run/systemd/resolve/stub-resolv.confが出れば、resolvedのスタブ構成です。nmcliの接続名は後の変更対象になるため、デバイス名と混同しないよう控えます。たとえば接続プロファイル名が「Wired connection 1」、デバイス名がenp1s0ということがあります。
名前解決の現在地をテストする
getent ahosts example.com
resolvectl query example.com
dig example.com A
dig example.com AAAA
getentは/etc/nsswitch.confに従うため、一般アプリに近い経路を確認できます。resolvectl queryはsystemd-resolved経由、digはDNS問い合わせの応答を詳しく表示します。pingだけでは、ICMPを拒否する正常なDNSサーバーを故障と誤判定するため、DNSテストの代用にしません。
NetworkManagerでDNSを永続設定する
RHEL、Fedora、デスクトップLinuxなど、NetworkManagerが接続を管理する環境では、接続プロファイルへ設定します。以下の192.0.2.53、192.0.2.54、2001:db8::53は文書用アドレスです。実際には組織・VPN・ISPから指定されたDNSへ置き換えてください。
1. 変更前の値を記録する
nmcli connection show --active
CON='接続プロファイル名'
nmcli -f ipv4.dns,ipv4.ignore-auto-dns,ipv6.dns,ipv6.ignore-auto-dns connection show "$CON"
出力を管理記録へ保存します。DNSアドレスだけでなくignore-auto-dnsも必要です。元がDHCP DNSとの併用だったか、手動DNSだけだったかで復元値が変わります。画面共有やチケットには社内DNS名・アドレスが含まれる可能性があるため、公開先を限定してください。
2. IPv4 DNSを設定する
sudo nmcli connection modify "$CON" \
ipv4.dns "192.0.2.53 192.0.2.54" \
ipv4.ignore-auto-dns yes
ipv4.ignore-auto-dns yesにすると、DHCPから受け取ったDNSと検索ドメインを無視し、手動指定だけを使います。社内ネットワークやホテルWi-Fi、VPNで必要なDNSがDHCPから配布される場合は、名前解決や認証ポータルが使えなくなる可能性があります。既存DNSへ追加するだけなら、設計を確認して+ipv4.dnsを検討します。
3. 必要な場合だけIPv6も設定する
sudo nmcli connection modify "$CON" \
ipv6.dns "2001:db8::53" \
ipv6.ignore-auto-dns yes
IPv6が有効な環境では、IPv4だけ変えてもIPv6側から受け取ったDNSが使われる場合があります。ただし、IPv6 DNSを持たない環境で架空値を入れてはいけません。resolvectl statusとネットワーク設計を確認し、提供されている場合だけ設定します。
4. 対象接続だけを再適用する
sudo nmcli connection up "$CON"
resolvectl status
getent ahosts example.com
dig @192.0.2.53 example.com A
SSH接続中のconnection upは通信を一時的に切る可能性があります。コンソール、帯域外管理、別のSSHセッションのいずれかを確保してから実行します。NetworkManagerサービス全体の再起動は、無関係な接続やVPNまで落とすため、通常のDNS変更では行いません。
NetworkManagerの設定を元に戻す
変更前に記録したipv4.dnsとipv4.ignore-auto-dnsを同じnmcli connection modifyで戻し、接続を再適用します。元がDHCP DNSだけで、手動DNSが空、ignore-auto-dnsがnoだった場合に限り、次の例で戻せます。
sudo nmcli connection modify "$CON" ipv4.dns "" ipv4.ignore-auto-dns no
sudo nmcli connection modify "$CON" ipv6.dns "" ipv6.ignore-auto-dns no
sudo nmcli connection up "$CON"
元から固定DNSがあった環境では空へ戻してはいけません。記録した値を復元してください。復旧確認後も、VPN接続時・切断時、再起動後の両方でresolvectl statusを確認します。
Ubuntu/NetplanでDNSを設定する
Ubuntu ServerではNetplanが高水準の設定を持ち、systemd-networkdまたはNetworkManagerへ反映します。最初に対象インターフェイスと構成ファイルを確認します。クラウドイメージではcloud-initが生成したファイルがあり、再プロビジョニング時に上書きされることもあるため、ファイル冒頭の注記も読みます。
sudo netplan status -a
ls -l /etc/netplan
sudo cp -a /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.before-dns
実際のファイル名は環境に合わせます。バックアップは同じ権限と所有者を保持するcp -aで作り、秘密情報を含む可能性があるためアクセス権を広げません。構成管理ツールが所有するサーバーでは、ローカル編集ではなくAnsible等の正規ソースを変更します。
Netplanの記述例
network:
version: 2
renderer: networkd
ethernets:
enp0s25:
dhcp4: true
dhcp4-overrides:
use-dns: false
nameservers:
addresses:
- 192.0.2.53
- 192.0.2.54
search:
- example.internal
この例はIPv4アドレスの割り当てにはDHCPを使いながら、DHCPから受け取るIPv4 DNSを無効にして固定DNSへ置き換える構成です。dhcp4-overridesはdhcp4と同じ階層、その子のuse-dnsはさらに2スペース下げます。networkdではuse-dnsの既定値がtrueで、DHCP nameserverが静的なnameserversより優先されます。そのため、nameserversだけを書いても固定DNSへの置換にはなりません。
DHCP配布DNSも残す目的ならdhcp4-overrides: use-dns: falseを指定せず、静的DNSは追加(additive)候補であり置き換えではないと扱います。実際の問い合わせ先と優先順位はresolvectl statusで確認してください。YAMLはタブではなくスペースで字下げし、既存のアドレス、ルート、DHCP、renderer設定を不用意に消しません。検索ドメインは必要な社内ドメインだけを指定します。
IPv6のDHCPv6とRAは別々に確認する
IPv6ではDNSがDHCPv6とRouter Advertisement(RA/RDNSS)の別経路から届く可能性があります。dhcp6: trueでDHCPv6 DNSを固定DNSへ置き換える場合は、対応するdhcp6-overridesへuse-dns: falseを指定します。RAから届くDNSはDHCPv6とは別で、Netplan 1.1以降のnetworkdではra-overridesのuse-dns: falseで受信DNSの利用を止められます。利用中のNetplanとrendererがそのキーに対応するか、適用前に公式YAMLリファレンスとnetplan infoで確認してください。
network:
version: 2
renderer: networkd
ethernets:
enp0s25:
dhcp4: true
dhcp6: true
accept-ra: true
dhcp4-overrides:
use-dns: false
dhcp6-overrides:
use-dns: false
ra-overrides:
use-dns: false
nameservers:
addresses:
- 192.0.2.53
- "2001:db8::53"
renderer: networkdでdhcp4とdhcp6を両方trueにする場合、dhcp4-overridesとdhcp6-overridesは同じキーと値を持たなければなりません。片方だけにuse-dns: falseを置いたり値を変えたりすると、エラーになり構成は適用されません。RAのra-overridesはこのDHCP4/DHCP6一致制約とは別に判断します。
構文確認と復旧確認
sudo netplan generate
sudo netplan try
netplan generateでYAMLと生成処理を確認し、その後netplan tryを使います。通常は未確認の構成をtimeout後に戻す動作ですが、公式マニュアルにはtimeoutまたはcancel時に実際には復元されない既知の不具合が記載されています。バックアップ、別のSSHセッション、コンソールまたは帯域外管理経路を準備したうえで実行し、ロールバックを唯一の復旧手段にしません。
SSHが応答しなくなった場合は構成を確認せずtimeoutを待ち、その後コンソールまたは帯域外経路で、ディスク上のYAMLと稼働中のネットワーク状態を両方確認します。netplan status -a、ip address、ip route、resolvectl statusなどを使い、実際に戻っていなければ保存済みバックアップから復旧してnetplan generateを通します。再起動の前にもディスク上の構成が意図した状態か確認してください。バックアップを丸ごと戻す前に、その後ほかの管理者が加えた変更がないかも確認します。
systemd-resolvedで確認・一時テストする
現行の操作コマンドはresolvectlです。旧記事で使われるsystemd-resolveは環境によって存在しません。resolvectl statusはリンクごとのDNS、検索ドメイン、プロトコル状態を表示し、複数NICやVPNの問い合わせ先を確認するのに向いています。
リンク単位の一時設定
IFACE='enp0s25'
sudo resolvectl dns "$IFACE" 192.0.2.53 192.0.2.54
sudo resolvectl domain "$IFACE" '~example.internal'
resolvectl status "$IFACE"
resolvectl query host.example.internal
先頭の~付きドメインは、そのリンクへ問い合わせを振り分けるルーティングドメインで、通常の検索サフィックスとは役割が異なります。これは診断用の一時設定です。恒久化はNetworkManager、Netplan、systemd-networkdなど実際の管理元へ書きます。
一時設定とキャッシュを戻す
sudo resolvectl revert "$IFACE"
sudo resolvectl flush-caches
resolvectl status "$IFACE"
revertはresolvectlで行ったリンク単位設定を戻します。flush-cachesはsystemd-resolvedが保持するDNSキャッシュだけを消し、ブラウザー独自キャッシュや上流DNSキャッシュは消しません。設定ミスをキャッシュのせいにして繰り返し消去せず、問い合わせ先と応答を比較してください。
/etc/resolv.confを直接編集してよいケース
NetworkManager、Netplan、systemd-resolved、DHCPフック、構成管理のいずれも管理しておらず、/etc/resolv.confが通常ファイルとして意図的に静的管理されている場合だけです。まずバックアップを作り、コンソールを確保します。多くの現行ディストリビューションでは例外的な構成です。
sudo cp -a /etc/resolv.conf /etc/resolv.conf.before-dns
sudoedit /etc/resolv.conf
変更後にネットワークサービスを再起動する必要は通常ありません。glibcのリゾルバーは設定を読み取ります。再起動を要求する独自アプリはそのアプリだけを確認します。再接続や再起動で上書きされたなら、直接編集を継続せず生成元を特定してください。復元はバックアップを比較して戻します。
DNS障害を結果別に切り分ける
| 結果 | 次に見る項目 |
|---|---|
| IPアドレスへの通信もできない | リンク、IPアドレス、デフォルトルート、VPN。DNS変更より前の問題 |
dig @指定DNSがタイムアウト | UDP/TCP 53、経路、ファイアウォール、DNSサーバーの待受 |
| 直接digは成功、getentは失敗 | nsswitch.conf、resolved、検索ドメイン、ローカルキャッシュ |
| 公開名は成功、社内名は失敗 | VPN、ルーティングドメイン、検索ドメイン、DNS priority |
| Aは成功、AAAAだけ失敗 | IPv6 DNS、AAAAレコード、IPv6経路。A成功を全体成功としない |
| 一つの名前だけ誤る | /etc/hosts、権威DNSレコード、TTL、負のキャッシュ |
| 再起動すると設定が戻る | NetworkManager、Netplan、cloud-init、DHCP、構成管理の生成元 |
IP疎通と経路を確認する
ip address
ip route
ip -6 route
nc -vz 192.0.2.53 53
ncはTCP 53の到達性を確認する一例ですが、通常のDNSはUDPも使うため、これだけで完全な判定にはなりません。dig @192.0.2.53 example.comの応答、タイムアウト、SERVFAIL、NXDOMAINを読み分けます。NXDOMAINは通信成功後に『名前が存在しない』と返された状態で、DNSサーバーが停止した意味ではありません。
NSSとhostsを確認する
grep '^hosts:' /etc/nsswitch.conf
grep -n '対象ホスト名' /etc/hosts
getent hosts 対象ホスト名
hosts:行では、通常filesがDNSより前に評価されます。古い/etc/hostsエントリがあれば、DNSを変えても結果は変わりません。エントリを削除する前に、その静的登録がアプリやクラスタの要件ではないか管理者へ確認します。
複数接続・VPNの優先順位を確認する
有線、無線、VPNが同時に有効な場合、DNSサーバーの並びだけでは問い合わせ先を説明できません。NetworkManagerは接続ごとのDNS priorityを使い、dnsmasqやsystemd-resolved連携では検索・ルーティングドメインに応じて問い合わせを振り分けます。低い数値ほど高優先で、負のpriorityには他の構成を除外する特別な意味があります。理解せず値を変更しないでください。
nmcli -f NAME,TYPE,DEVICE connection show --active
nmcli -f ipv4.dns-priority,ipv6.dns-priority,ipv4.dns-search,ipv6.dns-search connection show "$CON"
resolvectl status
VPN接続時だけ社内名が引けるのが正しい設計もあります。公開DNSへ固定して社内DNSを無視すると、名前解決が止まるだけでなく、内部名の問い合わせを外部へ送信するおそれがあります。社内名の漏えいと認証失敗を避けるため、VPN配布設定を優先してください。
変更後の検証と作業記録
DNS設定はコマンドが正常終了しただけでは完了ではありません。現在のシェルで名前が引けても、キャッシュに残った結果を見ている可能性があります。対象DNSへ直接問い合わせ、OS標準の名前解決を確認し、別プロセスや別セッションでも同じ結果になることを確かめます。業務で使う公開名と社内名の両方を試してください。
resolvectl statusで意図したリンクのCurrent DNS Server、DNS Servers、DNS Domainを確認します。dig @指定DNS 対象名 AとAAAAで、各DNSサーバーが応答することを確認します。getent ahosts 対象名で、実際のアプリが使うNSS経路を確認します。- VPNを接続した状態と切断した状態で、公開名・社内名の期待結果を比較します。
- 再起動後またはDHCPリース更新後にも設定が残るか確認します。
- 監視、パッケージ更新、時刻同期、認証など、DNSへ依存する代表サービスのログも確認します。
digの結果は、成功か失敗かだけでなく応答コードを読みます。NOERRORでも回答レコードが空の場合があり、NXDOMAINは問い合わせ先が『名前は存在しない』と回答した状態です。SERVFAILは上流障害、DNSSEC検証、権威サーバー等の問題を含み、単純に別DNSへ変える前に問い合わせ名・サーバー・時刻を記録します。
複数のDNSサーバーを登録しても、常に問い合わせを均等分散するとは限りません。glibcの従来リゾルバーは先頭から試し、応答しないと次へ進むのが基本です。systemd-resolvedやNetworkManager連携ではリンク、ドメイン、優先度に応じた選択があります。異なる内容を返すDNSを『予備』として混在させると、再現しにくい障害になります。
変更記録には、対象ホスト、接続プロファイルまたはインターフェイス、変更前後のDNSと検索ドメイン、作業者、承認者、作業時刻、確認結果、復元手順を残します。内部DNS情報を公開Wikiへ載せず、組織の構成管理・変更管理へ保管します。障害時に『元の値が分からない』状態を防ぐことが、最も重要なロールバック対策です。
サーバーの再起動は永続性の確認に役立ちますが、DNS変更のためだけに本番サーバーを即再起動する必要はありません。まず管理サービスの設定を再読み込みし、保守時間に再起動後テストを行います。再起動できない重要サーバーでは、次回再起動時の確認担当と監視項目を変更記録へ明記してください。
セキュリティと運用上の注意
- 公開DNSを速さだけで選ばず、運営者、ログ保持、フィルタリング、DNSSEC、利用規約、組織ポリシーを確認する。
- 社内DNSと異なる公開DNSを混在させない。同じ名前へ異なる答えが返るスプリットホライズン構成を壊す。
- DNSSEC、DNS over TLS、DNS over HTTPSは、アドレスを指定するだけで自動的に有効になるものではない。
- 検索ドメインを増やしすぎない。短い名前の問い合わせ先が増え、情報漏えいと遅延の原因になる。
- 設定ファイルと診断ログに内部ドメイン、DNSアドレス、VPN構成が含まれるため、公開チケットへ貼らない。
- キャッシュ用途でdnsmasqを導入する場合は、既存resolved、ポート53、NetworkManagerプラグインとの競合を設計してから行う。
よくある質問
8.8.8.8へ変えればDNSエラーは直りますか?
直るとは限りません。社内名やVPN名は公開DNSでは解決できず、組織のフィルタリングや監査を外れることがあります。指定DNSへの直接問い合わせが失敗するかを先に確認し、管理者指定のDNSを使ってください。公開DNSで一時比較する場合も、元の値と戻し方を記録します。
/etc/resolv.confにDNSが3個までしかないのはなぜですか?
glibcの従来リゾルバー設定ではnameserverの上限があります。一方、systemd-resolvedやNetworkManager連携では、/etc/resolv.confにローカルスタブだけを置き、リンク別の複数DNSを別管理することがあります。ファイルの行数だけで全体を判断しません。
DNSキャッシュを消す共通コマンドはありますか?
ありません。systemd-resolvedならsudo resolvectl flush-cachesですが、nscd、dnsmasq、ブラウザー、アプリ、上流DNSは別です。利用しているキャッシュ実装を確認し、設定や権威レコードの誤りをキャッシュ消去で隠さないようにします。
LinuxをDNSサーバーとして構築する手順も同じですか?
異なります。この記事はクライアント側の問い合わせ先設定です。BIND等でサーバーを構築する場合は、再帰を許可するネットワーク、ゾーン、転送先、DNSSEC、アクセス制御、UDP/TCP 53、更新、ログ、冗長化を別に設計します。インターネットへ開いたオープンリゾルバーを作らないでください。
まとめ
LinuxのDNS変更では、表示されている/etc/resolv.confより、そのファイルを生成する管理方式が重要です。readlink、resolvectl、nmcli、Netplanの状態を確認し、NetworkManagerなら接続プロファイル、UbuntuならNetplanへ永続設定します。systemd-resolvedの一時設定はresolvectl revertで戻します。
変更前の値を記録し、対象接続だけを適用し、getent、resolvectl query、dig @指定DNSで経路を分けて検証してください。SSH管理ではバックアップ、第二セッション、コンソールまたは帯域外経路を用意してnetplan tryを使い、timeout/cancel後もディスク上と稼働中の状態を確認します。公開DNSへの安易な置換、ネットワークサービス全体の再起動、管理中の/etc/resolv.conf直接編集を避けるのが安全です。

コメント