VPN 経由の CIFS マウントが nsswitch の順序で失敗する理由
共有はアドレスでは応答し、名前では止まってしまうため、SMB が始まる前に名前解決が死にます。getent と host を比べ、次に hosts 行を順番に読んでください。
トンネルは上がっています。ファイルサーバーはアドレスでの ping には応答します。ところがホスト名を渡した mount.cifs はしばらく固まった末に、ホストに到達できないと報告します。そこで関係のない VPN プロファイルを作り直し始めるわけです。Linux では SMB パケットが一つも生まれる前に glibc が名前を解決しており、そのリゾルバ内の順序が DNS に問い合わせる前に探索を打ち切ることがあります。ここでは、クライアントではなく失敗したコマンドから始める手順を示します。
失敗を正しい場所で読む
二つのツールは同じ名前へ違う経路で向かい、比べるのに必要なのは一つのコマンドだけです。getent は設定されたネームサービススタックをたどります。一方 host と dig は DNS に直接問い合わせ、そのスタックを無視します。直接の問い合わせがアドレスを返し、getent が何も返さないなら、DNS サーバーには届いており、失敗しているのはリゾルバの設定です。
getent hosts fileserver.corp.example
host fileserver.corp.example 10.61.0.1
getent -s dns hosts fileserver.corp.example
三つ目のコマンドが決め手です。DNS を情報源として強制し、スタックの残りを飛ばします。これが通り、素の getent が通らないなら、原因は順序であり、トンネルでもサーバーでもないと証明できたことになります。
hosts 行は早く止まる並びです
glibc のリゾルバは /etc/nsswitch.conf を読み、hosts: の項目を左から右へたどります。多くのディストリビューションは、マルチキャストの探索が先に来て、そこに早期リターンの動作が付いた行を出荷しています。この動作は飾りではありません。mDNS が「見つからない」と答えると、[NOTFOUND=return] が探索全体を終わらせてしまうため、社内の名前は VPN が押し込んだリゾルバへ一度も送られません。何も記録されません。リゾルバが拒否できる問い合わせが送られていないからです。だからマウントは固まったように見え、そのあと到達不能なホストだと報告するのです。
cat /etc/nsswitch.conf | grep '^hosts:'
# illustrative repair: dns before the early-return action
hosts: files myhostname mdns4_minimal dns [NOTFOUND=return] wins mdns4
mDNS を消すのではなく、DNS を早期リターンの動作より前へ動かし、設定管理を通して変更してください。手作業の修正は次のイメージビルドまでしか持ちません。そのあと同じ件名のチケットが、修正を知らない別のマシンから届きます。
リゾルバは検索ドメインではありません
解決には、その名前を試すことも必要です。fileserver のような修飾されていない名前は、問い合わせを運ぶインターフェースに検索ドメインが付いているときだけ fileserver.corp.example になります。検索リストなしで DNS サーバーを押し込む VPN は、非常にはっきりした分裂を生みます。完全修飾名は解決し、短い名前はすべて失敗する.
プロファイルを編集する前に両方の形を試してください。二つの失敗は違う方向を指しているからです。systemd-resolved のホストでは、トンネルのリンクが独自のサーバーとルーティングドメインを持つので、グローバルなファイルではなくリンクを読んでください。
resolvectl status
resolvectl query fileserver.corp.example
resolvectl dns
resolvectl domain
問い合わせがトンネルを運ばないリンクに紐づけられているなら、DNS アドレスがあってもルーティングドメインが欠けています。これは resolved の設定におけるポリシーの問題で、トンネルのルーティングの問題ではありません。
コンテナは答えの写しを自分で持ちます
汎用イメージから作ったコンテナは、通常は固定の resolv.conf を同梱しています。ホスト側のリゾルバ変更はそこに届かず、検索ドメインも届きません。そのためトンネル越しに共有をマウントするビルド処理は失敗し、同じコマンドがコンテナの外では通ります。コンテナには compose ファイルか run の引数で独自の DNS と検索の設定を与えてください。ホストのプロファイルだけでは足りません。
イメージを責める前にコンテナの中で確かめてください。二つのコマンドで診断全体が数秒で再現でき、二つ目はどのリゾルバが実際に答えたかを示します。
そのうえで初めて共有とフィルターを見ます
名前が解決できたら、残る失敗は普通のネットワークの問題です。SMB はサーバーへの TCP 445 を必要とし、ワークグループ一覧の閲覧はトンネルがまず転送しないネームサービスに依存します。一覧が埋まるのを待つのではなくホスト名でマップし、どの段階まで進んだかをクライアントに語らせてください。接続拒否と無言のタイムアウトも分けて考える価値があります。前者は何かが答えたという意味であり、後者は何も答えなかったという意味だからです。
getent hosts fileserver.corp.example
nc -vz fileserver.corp.example 445
mount -t cifs //fileserver.corp.example/share /mnt/share \
-o vers=3.1.1,username=svc_mount,uid=1000
解決できたアドレスでポート 445 が拒否されたりタイムアウトしたりするのは、向こう側のファイアウォールかリスナーの問題です。解決できない名前はリゾルバの問題です。そして認証は通るのに権限エラーを返すマウントはどちらでもないので、セッションが確立したあとにネットワークの話を蒸し返さないでください。
結論は証拠と同じだけ狭く保ってください。アドレスが通り名前が通らないとき、トンネルは仕事をしており、直すべきはリゾルバの順序、検索ドメイン、あるいはコンテナ自身の設定です。