Lambdaカクテル

ウェブアプリケーションエンジニアです.玉石混淆です.

SMBD - .localドメインを使うとネゴシエーションが低速化する

表題の通りです.

LAN内でsambaサーバを運用していたところ,接続時に数秒以上待たされるという事象が毎回発生していました.この原因がおおよそ分かったのでメモしておきます.

TL;DR

  • 何が起こるか分かっていないなら,.localドメインを使うな

本編

まずWiresharkでパケットキャプチャを行ったところ,速度低下の原因がmDNSにあることが判明しました. mDNS(Multicast DNS)とは,DNSサーバを介さずにホストの名前解決を行う機構です.

mDNSが支えるZeroconf

mDNSを説明するために,まずはmDNSが支えているZeroconfについて説明します.Zeroconfとは,ケーブルをつなぐだけで設定無しにIPネットワークに接続できるようにするための一連の技法の事を指します.自動的にIPアドレスが付与されるDHCPもZeroconfを支える技術です.

DHCPを使うと事前情報無しでIPアドレスを使えるようになりますが,同じように名前解決も事前情報無しで行おうというのがmDNSです. DHCPではDNSサーバの情報が配られる事が多いですが,DNSサーバ情報が受け取れない場合もあります.mDNSはそのような状況をカバーするものだと言えるでしょう.

.local ドメイン

さて,mDNSが利用できる時にmDNSが常時使われるかというと,そうではありません.mDNSが名前解決を行うのは,標準ではTLD.localとなっているホストについて名前解決をしようとする時のみです*1.そうでない時は通常のDNSが使われます.そして今回,接続に時間のかかるsambaサーバのTLD.localに設定してあったため,名前解決にmDNSが使われていることがWiresharkによるパケットキャプチャの結果分かりました.そして,名前解決が待ち時間のほぼ全てを占めていることも判明しました.このような場合では高速に名前解決できれば問題は片付くでしょう.

OS X.localドメイン以外についてもmDNSを使う方法

OS Xでは,ネットワーク環境設定のインターフェイス設定画面にある「DNS」タブの「検索ドメイン」がmDNSに探索させるドメインの一覧です.ここに追加したドメイン.localドメインとがmDNSで探索されます.

他OSについても同様の設定があるはずです.

mDNSはhostsをバイパスする(っぽい)

低速化を回避するためにまず行ったことは,/etc/hostsIPアドレスとホスト名の組を記述し,静的に名前解決させるという対処でした.これによりmDNSやDNSが名前解決する前に静的解決ができ,速度の向上が見込めると思いました.しかしこの対処を行った後も,mDNSによる名前解決は続きました.確実なソースは未確認ですが,少なくともOS X 10.11.6(El Capitan) では,mDNSが使われる場合には/etc/hostsは使われないようです.

ドメイン.localdomainに変更 (解決)

クライアントのhostsファイルの変更では事態が改善しないため,sambaサーバのホスト名をmDNSに使われないドメインを含むものに変更したところ,mDNSは使われなくなりました.今回は.localdomainを使いました.

この変更によって,少なくとも接続時のネゴシエーションに時間がかかるというトラブルが解決しました.

smb.conf

今回の設定ファイルは以下のようになりました.

# $smbd -V
# Version 4.4.4

log file = /var/log/samba/log.%m
read raw = yes
load printers = no
write raw = yes
aio read size = 16384
socket options = SO_KEEPALIVE TCP_NODELAY SO_SNDBUF=16384 SO_RCVBUF=16384
username map = /etc/samba/user.map
interfaces = # interfaces #
encrypt passwords = yes
passdb backend = tdbsam
keepalive = 60
max xmit = 262140
netbios name = # HOST.LOCALDOMAIN #
cups options = raw
min receivefile size = 16384
server string =
max protocol = SMB2
min protocol = SMB2
aio write size = 16384
workgroup = # WORKGROUP #
os level = 20
use sendfile = true
security = user
max log size = 50
log level = 1
wins support = yes

参考文献

*1:このような動作をするのは,通常のDNSでしか名前解決できない場合の混乱を防ぐためです