えんでぃの技術ブログ

えんでぃの技術ブログ

ネットワークエンジニアの視点で、IT系のお役立ち情報を提供する技術ブログです。

/etc/nsswitch.confのhosts行を理解する

multiple_switch

お伝えしたいこと

Fedora33以降で、/etc/nsswitch.confのhosts行のデフォルト値が変わりました。
その変更に伴ってLinuxの名前解決の挙動がどのように変わったかを記事前半の#サマリで紹介します。

また記事後半の#Name Service Switch以降では、Name Service Switchの概要と/etc/nsswitch.confファイルの読み方を紹介します。

サマリ

本セクションに各ディストリビューション/etc/nsswitch.confのhosts行に書かれている内容の意味を記載します。
挙動のみを知りたい場合は、本セクションのみ読めば十分です。

/etc/nsswitch.confの読み方については、本記事の後半で取り扱います。

Fedora33以降

Fedora33以降の/etc/nsswitch.confの内容は、以下のとおりです。

hosts:      files myhostname resolve [!UNAVAIL=return] dns

端的に言うと、ほとんどの場合は/etc/hostsかsystemd-resolvedによる名前解決になります。

/etc/resolv.confは、基本的に使われません。
systemd-resolved.serviceが停止している場合のみ、/etc/resolv.confによるDNS名前解決が行われます。

以下に詳細を示します。
まずは1で名前解決を試み、1で名前解決できなければ2、次に3...という流れで進みます。

  1. /etc/hostsの定義を元に名前解決する (files)
  2. 自身のホスト名やFQDNを名前解決する (myhostname)
  3. systemd-resolvedによるDNS名前解決を行う (resolve)
    • systemd-resolvedが問題なく起動していた場合、この先に進まず名前解決の結果を返す ([!UNAVAIL=return])
  4. /etc/resolv.confによるDNS名前解決を行う (dns)

Fedora33以前、RHEL7、RHEL8

Fedora32以前、RHEL7、RHEL8の/etc/nsswitch.confの内容は、以下のとおりです。
RHEL9 Bataについても同じ内容でした。

hosts:      files dns myhostname

ほとんどの場合は/etc/hosts/etc/resolv.confによる名前解決になります。

Name Service Switch

Name Service Switch (NSS) とは、GNU C Library (glibc) に含まれる名前解決手段のデータベースです1
例えばFQDNやホスト名をIPアドレスに解決する手段は、以下のとおり複数存在します。

  • /etc/hostsを参照して名前解決する
  • /etc/resolv.confに記載されたDNSサーバに問い合わせて名前解決する
  • systemd-resolved DNSクライアントの機能で名前解決する
  • (他)

NSSは、上記のような名前解決手段に優先順位付けをします。
そして、優先順位の高い順に名前解決を試みます。
多くの場合は/etc/hostsの優先順位が高く、その次に/etc/resolv.conf、またはsystemd-resolvedが使用されるようNSSに制御されます。

上記はFQDNやホスト名からIPアドレスへ名前解決する場合の例ですが、NSSの用途はもっと多岐に渡ります。
以下にNSSが提供する名前解決の対象 (※) を列挙します2
(※) 以下に列挙した名前解決の対象は、NSSの用語でdatabaseといいます

  • aliases
  • ethers
  • group
  • hosts
  • initgroups
  • netgroup
  • networks
  • passwd
  • protocols
  • publickey
  • rpc
  • services
  • shadow

Linuxでは、多くのアプリケーションが/etc/nsswitch.confを参照し、NSSによって名前解決の手段を決定します。
しかし、全てのプログラムがNSSを使うわけではありません。
「NSSが何に使われ、何に使われていないか」については、#(参考) NSSの利用例でいくつかの例を示します。

次のセクションからは、NSSの設定ファイルである/etc/nsswitch.confの読み方について詳しく説明します。

/etc/nsswitch.confの読み方

基本構造

本セクションの情報は、man nsswitch.confの内容を情報源としています。

/etc/nsswitch.confは、NSSの設定ファイルです。
1列目にdatabase、2列目以降にservice specifications (※) を列挙します。
databaseとservice specificationsの間は:で区切ります。
(※) service specificationsは、単にservicesと呼ばれることもあります

serviceは、1つ以上指定します。
左に書いてあるものほど優先順位が高く、最初に検索されます。
優先順位が高いserviceにおいて名前解決できなかった場合、次に優先順位の高いserviceで名前解決を試みます。

以下に、Fedora35の/etc/nsswitch.confのhosts database行の例を示します。
hosts databaseは、FQDNやホスト名からIPアドレスを求める、またはその逆の名前解決を行う際に参照されるdatabaseです。

hosts:      files myhostname resolve [!UNAVAIL=return] dns

上記において、hostsがdatabaseです。
そして、service specificationsは以下の通りです。
上に書いてあるものほど優先順位が高いです。

  1. files
  2. myhostname
  3. resolve [!UNAVAIL=return]
  4. dns

[]で囲まれた文字列は、actionと呼ばれるパラメータです。
service specificationの後に指定することで、デフォルトの動作を一部変えることができます。
詳細は#actionセクションにて説明します。

service specifications

本セクションでは、代表的なservice specificationsの意味を紹介します。

files

filesは、/etc/配下の設定ファイルによる名前解決を行うserviceです。
具体的にどのファイルに記述するかは、databaseによって異なります。

下表に例を示します。

database名 設定ファイル (※) 内容
hosts /etc/hosts IPアドレスとホスト名/FQDNの紐付け
passwd /etc/passwd ユーザー名と詳細情報 (※) の紐付け
(※) UID, GID, ホームディレクトリパス, ログインシェルなど
group /etc/group グループ名とGID/所属ユーザー名の紐付け
shadow /etc/shadow ユーザー名とパスワード (ハッシュ値) の紐付け
networks /etc/networks ネットワーク名とネットワークアドレスの紐付け
services /etc/services サービス名とTCP/UDPポート番号の紐付け

(※) 各databaseのfiles serviceに紐づく具体的なファイルは、manを追いかけることで推定できます。例えばhosts databaseの場合、man nsswitch.confman gethostsbynameと辿ると/etc/hostsという情報に行き着きます

各種ファイルの詳細情報は、ファイル名のmanページで確認できます。
例えば/etc/hostsの情報はman hostsで、/etc/passwdの情報はman 5 passwdで確認できます。

myhostname

myhostnameは、自分自身のホスト名をIPアドレスに名前解決します。
私達がmyhostnameの機能を直接使うことはほとんどありません。
どちらかというと、アプリケーションの内部処理で利用される機能だと思います。

myhostnameの簡単な例を示します。
以下のコマンドにより、myhostname serviceを指定してNSSを検索しています。
実行しているLinuxのホスト名はpcです。
(※) getentはNSSを参照して名前解決を行うコマンドです。詳細は#getentで説明します

getent -s myhostname ahostsv4 pc | grep STREAM
# 192.168.1.110   STREAM pc
# 192.168.122.1   STREAM 
# 192.168.100.1   STREAM 

ホスト名の他にも、以下のような名前解決が可能です。

名前 IPアドレス
※自身のホスト名
  • 自身に設定されたIPアドレス
  • IPが未設定だった場合は、以下を返す
    • 127.0.0.2 (local loopback address)
    • ::1 (localhost)
  • localhost
  • localhost.localdomain
  • *.localhost
  • *.localhost.localdomain
  • 127.0.0.1
  • ::1
_gateway デフォルトゲートウェイIPアドレス

dns

dnsは、/etc/resolv.confの記載内容に基づいてDNSによって名前解決を行うserviceです。

/etc/resolv.confの書き方については詳しく触れません。
詳細はman resolv.confに書いてあります。
nameserverとsearchを指定するのが一般的だと思います。

resolve

resolveは、systemd-resolvedというDNSクライアントによって名前解決を行うserviceです3

systemd-resolvedは、RHEL7やRHEL8においては現状使われていません。
Fedoraでは、Fedora33以降でdnsを置き換える形で使われ始めました。

systemd-resolvedは、以下の特徴を持ちます。

  • モダンなDNS機能に対応する
  • D-Bus APIに対応し、NetworkManagerなどと連携して動作できる
  • 名前解決結果をキャッシュできる
  • hosts databaseのfiles, myhostname, dnsと同等の機能を持つ
  • ドメイン名に応じたDNSサーバの使い分けができる (※)

(※) Split DNSと呼ばれる機能。systemd-resolved用語ではPer-link DNSDNS Routingとも呼ばれる

systemd-resolvedについては、以下の記事で詳細に説明します。

endy-tech.hatenablog.jp

(参考) mdns4_minimal

環境によっては、mdns4_minimal [NOTFOUND=return]がhosts databaseに含まれることもあるので、軽く触れておきます。
mdns4_minimalがhosts databaseに含まれていない場合は、本セクションごとスキップして差し支えありません。
私の環境では、Cinnamon Desktop Environmentに依存関係として含まれていました。

mdns4_minimalは、デフォルトでは/etc/nsswitch.confには書いてありませんし、書いたとしても使えません。
このserviceが表すmDNS機能は、以下のRPMパッケージをインストールすることで使えるようになります。

sudo dnf install nss-mdns

nss-mdnsをインストールすることで、/etc/nsswitch.confmdns4_minimal [NOTFOUND=return]が追記されます。
また、mDNSの動作に必要なライブラリやプログラムも追加されます。

mdns4_minimalは、ホスト名.localの名前解決を行います。
上記に該当しない名前については、そもそも名前解決のクエリ自体がスキップされます。
そして、NSSの優先順位にしたがい、次のserviceで名前解決を試みるという動きになります。

言い換えると、ホスト名.local以外の名前を使う限り、mdns4_minimalは一切関与しません。
多くの場合、mdns4_minimalを利用したり意識することはないと思います。

nss-mdnsには、他にも以下のservice specificationが含まれます4

mDNSのservice 機能
mdns IPv4/IPv6の全てのmDNS機能 (.local以外のドメインも名前解決可能)
mdns4 IPv4の全てのmDNS機能
mdns6 IPv6の全てのmDNS機能
mdns_minimal IPv4/IPv6について、.local限定のmDNS機能
mdns4_minimal IPv4について、.local限定のmDNS機能
mdns6_minimal IPv6について、.local限定のmDNS機能

2点ほど余談を挟みます。

1つ目ですが、DNSサーバの検証をする際は.local.localhost.localhost.localdomainを使わないように気をつけましょう。
.localはmDNSと競合しますし、後者の2つはmyhostname serviceと競合します。
結果として上記ドメインDNSサーバに問い合わせられず、意図せぬ結果を招くことがあります。

2つ目は、mDNS (multicast DNS) についてです。5,6
mDNSは、名前解決のクエリにマルチキャストを使います。
IPv4224.0.0.251IPv6ff02::fbを宛先にセットしてクエリします。
宛先ポート番号はUDP5353です。

通常のDNSとは異なり、DNSサーバのIPアドレスを指定せず使えるのがmDNSの利点です。
その代わり、基本的には同一ネットワーク内限定のサービスとなります。

(参考) sss

sssは、sssデーモンによる名前解決を行います。
ここでの名前解決はFQDNやホスト名ではなく、ユーザー名やグループの名前解決です。

RHEL8では、passwd databaseやgroup databaseにおいてデフォルトで使用されています。
sssを使う主なメリットは、名前解決結果のキャッシュ機構を持つことで処理が効率化されていることです。

詳細が気になる方は、RHEL8のマニュアルを参照してください。

Fedoraについては、Fedora35以降よりsssdを使わなくなりました (参考: Fedora35の変更点)。

action

actionとは、/etc/nsswitch.confにおいて[]で囲まれた部分のことです。
以下のフォーマットで記述されます。

[STATUS=ACTION]

STATUSもACTIONも複数存在しますが、最低限resolve [!UNAVAIL=return]の意味さえ理解できれば十分です。

STATUSに入る値は、下表のいずれかです。
クエリに成功した場合はreturn、何らかのエラーが発生した場合はcontinueするのがデフォルトの動作です。

STATUS名 意味
SUCCESS
  • 名前解決に成功したことを表す
  • デフォルトのACTIONはreturn
NOTFOUND
  • クエリには成功したが、名前と対応する情報が見つからなかったことを表す
  • デフォルトのActionはcontinue
UNAVAIL
  • serviceが恒久的に利用不能であることを表す
  • 例えば...
    • 名前解決を行うデーモンが起動していない
    • 名前解決の定義ファイルの読み取り権限がない
  • デフォルトのActionはcontinue
TRYAGAIN
  • serviceが一時的に利用不能であることを表す
  • 例えば...
    • デーモンのポート番号が枯渇し、一時的にリクエストを受けられない場合
    • ファイルがロックされている場合
  • デフォルトのActionはcontinue

ACTIONに入る値は、下表のいずれかです。

ACTION名 意味
return
  • その場で結果を返す
  • 次のserviceには進まない
continue 次のNSS serviceによる名前解決を行う
merge
  • service1 [SUCCESS=merge] service2のように使われる
  • 上記の場合、service1とservice2の名前解決結果の両方が返される
  • 同じ名前解決結果が存在したとしても重複削除はされない

actionは、service specificationsの後に記述することで意味を持ちます。
例えば、以下の例ではmdns4_minimalで名前解決を試みたとき、クエリ結果が "not found" だった場合はその場で結果を返します。

mdns4_minimal [NOTFOUND=return]

STATUSの前に! (否定) を記述することで、STATUS部分の意味が逆になります。
例えば以下の場合、resolveが恒久的に利用不能な場合を除けば必ず結果を返すようになります。
具体的には、systemd-resolvedサービスが停止している場合にはcontinueになりますが、そうでなければreturnになります。

resolve [!UNAVAIL=return]

getent

/etc/nsswitch.confに記述したNSSの挙動を確認するには、getentコマンドが便利です。
getentは、databaseを指定して名前解決を実行し、その結果を返すコマンドです。

syntaxは以下の通りです。

getent [-s <service>] <database> <key>

それぞれ以下の意味を持ちます。

キーワード 意味
-s <service>
  • 特定のservice specificationでのみ名前解決を行う
  • 指定しなかった場合、/etc/nsswitch.confに従う
<database>
  • database名
  • 例えばfilesmyhostnameresolvednsなど
  • 他にもahostsahostsv4ahostsv6などを指定可能
|| <key> |
  • 名前解決の対象となる文字列を指定する
  • 例えば、files databaseの場合はFQDNIPアドレスを指定する

いくつか例を示します。

hosts databaseの場合は、以下のようなコマンドが便利です。
あまり詳しくは理解していませんが、hostsを指定するとIPv6の結果が返ることが多いです。
IPv4アドレスの結果が欲しい場合は、ahostsv4が便利です。

getent hosts google.com
# 2404:6800:4004:812::200e google.com

getent ahostsv4 google.com
# 142.250.196.142 STREAM google.com
# 142.250.196.142 DGRAM  
# 142.250.196.142 RAW

STREAM、DGRAM、RAWはUnix Socketを表しています。
Unix Socketについてはあまり詳しくありませんが、TCP通信はSTREAM、UDP通信はDGRAM、ICMP通信はRAWを使うようです。7,8,9,10,11
3行とも同じ結果が出てくるので、あまり気にしなくても良いのではと思います。

もう一つ例を示します。
以下の出力では、passwd databaseの内容を表示しています。
LDAPを利用している環境では、LDAP経由で得られるユーザー情報もこのコマンドから確認できるようです。

getent passwd
# root:x:0:0:root:/root:/bin/bash
# (以下略)

(参考) その他のDNSクエリコマンド

getent以外にもDNSの名前解決をテストするコマンドはいくつかあります。
これらのコマンドは特定のserviceに特化したもので、NSSを参照しません。

  • dig
  • host
  • resolvectl query

bind-utils RPMパッケージに含まれるdighostは、/etc/resolv.confのみを参照します。12,13

systemd-resolvedを操作するresolvectl queryコマンドは、systemd-resolvedを介した名前解決を試みます14

(参考) NSSの利用例

本セクションでは、NSSが利用される具体的な場面をいくつか紹介します。
一方、NSSを使わないケースについても一部触れます。

hosts databaseの利用例

FQDNやホスト名を指定して通信を行う場合、名前解決を行ってIPアドレスに変換した上で通信します。
Linuxにおいては、このFQDN/ホスト名の名前解決手段を決めるためにNSSのhosts databaseを使用します。

具体的な挙動は、#サマリにて説明したとおりです。

passwd,shadow,group,gshadow databaseの利用例

以下のdatabaseは、ユーザー/グループの認証に使用されます。

  • passwd
  • shadow
  • group
  • gshadow

それぞれ/etc/配下の同名のファイルに従ってユーザー名やグループ名と詳細情報を紐付けます。
詳細情報とは、具体的に以下のような内容です。

LDAPなどの認証プロトコルを利用する場合は、上記databaseを書き換えることになります。

services databaseの利用例

RHEL7、RHEL8の/etc/nsswitch.confの一部を以下に抜粋します。

services:   files sss

files serviceに対応するファイルは、/etc/servicesです。
このファイルには、TCP/UDPポート番号とサービス名の紐付け情報が書かれています。
一部を抜粋します。

# (一部抜粋)
ssh             22/sctp                 # SSH

ssなどのプログラムは、ポート番号の表示にservices databaseを使用しています。
ssの実行結果を一部抜粋します。
以下の出力ではポート番号の表示にsshと表示されていますが、これは22と同じ意味です。
このsshと名前で表示する処理に、NSSのservices databaseを介して/etc/nsswitch.confが使われています(※)
(※) /etc/nsswitch.confservices: sssに書き換えたり、/etc/servicesssh行を#コメントアウトするとssの表示結果に影響を与えました。

ss -lt
# State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process       
# LISTEN  0       128     0.0.0.0:ssh         0.0.0.0:*
# LISTEN  0       128     [::]:ssh            [::]:*

networks databaseは、ipコマンドには使われていない

servicesと似たようなdatabaseとして、networksもあります。
/etc/networksは、以下のようにネットワークアドレスと和名を紐付けています。

default 0.0.0.0
loopback 127.0.0.0
link-local 169.254.0.0

ip routeコマンドで表示されるネットワークアドレスにもdefaultキーワードが出てきます。
しかし、ip routeコマンドについては/etc/nsswitch.conf/etc/networksも参照していません(※)
(※) どちらの設定ファイルをいじっても、ip routeの出力結果に影響を与えませんでした

その他

ここまで見てきたように、NSSを使っているか使っていないかを見分けることは容易ではありません。
hostsやpasswdのような重要なdatabaseについては挙動をしっかり理解しておくべきですが、他のdatabaseについてはあまり気にしないのが良いバランスなのではないかと思います。

他にも色々なdatabaseがありますが、どうしても情報が必要なケースがあれば/etc/nsswitch.confを変更しながら地道に挙動確認しようと思います。
しかし、そのようなケースはほとんどないと思います。

(参考) /etc/nsswitch.confのさらなる最適化

systemd-resolvedは、NSS hosts databaseの以下の機能を内包します。

  • files (/etc/hosts)
  • dns (DNSサーバによる名前解決。/etc/resolv.confとの互換性もある)
  • myhostname (自分のホスト名やデフォルトゲートウェイなどの名前解決)

また上記の仕組みとは異なり、systemd-resolvedは名前解決の結果を一定時間キャッシュするので、処理がより効率化されています。
唯一の弱点は、systemd-resolvedデーモンがクラッシュした場合に名前解決機能を継続できなくなることぐらいです。

こういった事情から、systemd-resolvedの作者は以下のように/etc/nsswitch.confを更新することを推奨しています15

↓更新前 (Fedora33以降)

hosts:      files myhostname resolve [!UNAVAIL=return] dns

↓更新後

hosts:      resolve [!UNAVAIL=return] files myhostname dns

「基本的には、処理が効率的なsystemd-resolvedに全て任せる。万が一systemd-resolvedがクラッシュしたときのために、filesやmyhostnameは後ろに残しておく。」

こういった設計思想のようです。
Fedoraのデフォルト値はあくまで「更新前」の状態ですが、名前解決が処理能力のボトルネックになるような状況が万が一発生した場合は「更新後」に変更することを検討しても良いのかもしれませんね。

まとめ

前半では、/etc/nsswitch.confのhosts database行の意味を解釈しました。
後半では、その解釈の根拠として/etc/nsswitch.confのファイルの読み方について、詳細に説明しました。

参考情報として、hosts以外のdatabaseやgetentコマンドについても少し触れました。

次の記事

Fedora33以降で使われ始めたsystemd-resolvedについて紹介します。
RHEL7、RHEL8ではまだ使われていませんが、そのうちスタンダードになるかもしれません。

endy-tech.hatenablog.jp


  1. The GNU C Library - System Databases and Name Service Switch

  2. man nsswitch.conf

  3. man - nss-resolve

  4. Arch Linux Wiki - Avahi

  5. ジョンのblog - vol37. mDNSとは

  6. Wikipedia - マルチキャストDNS

  7. Stack Overflow - What is SOCK_DGRAM and SOCK_STREAM?

  8. man socket

  9. man tcptcpの説明にSOCK_STREAMというキーワードが登場します

  10. man udpudpの説明にSOCK_DGRAMというキーワードが登場します

  11. man raw → SOCK_RAWの説明でICMPが言及されています。man icmpも参照

  12. man host

  13. man dig

  14. resolvectl queryがNSSではなくsystemd-resolvedを参照するというドキュメント上のエビデンスはありませんが、手元の検証で確認しました。NSSでmdns4_minimalを有効化した上でgetent hosts remote.localリモートホストのmDNSによる名前解決を試みたところ、成功しました。一方で、resolvectl query remote.localでは失敗しました。systemd-resolvedのmDNS機能はデフォルトで無効化されていることから、systemd-resolvedでmDNSの名前解決を実行しようとすると失敗するのは想定通りです。もちろん、getent -s resolve hosts remote.localでも名前解決できません。以上の結果から、resolvectl queryはNSSを利用せず、systemd-resolvedの機能のみで名前解決を行うことが確認できました。

  15. man nss-resolve