はじめに
ネットワーク境界に設置しているゲートウェイサーバーで、dnsmasqを運用していて、内部ネットワークのDNSサーバーとして利用しています。
ついでのこのゲートウェイ自身の/etc/resolv.confで、自分のIPアドレスを記載し、dnsmasqを利用しています。起動時の状態によってはDNSにアクセスできない可能性もありますが、nameserver行を複数記入することで、タイムアウトまでの時間はかかると思いますが、致命的な状態は回避しています。
ネットワークの状況が動的に更新されると問題になるので、クライアント環境でよく利用されているnetwork-manager
や resolvconf
などのパッケージは削除していますが、それでもある日突然に/etc/resolv.confが更新されていることに気がつきました。
このゲートウェイサーバーに静的にIPアドレスを割り当てていれば問題なかったのですが、こちらの都合でMACアドレスからIPアドレスを割り当てているためにDHCPクライアントとしても動作しているために問題が発生していたことが分かりました。
これらの原因追跡の過程と、対応についてまとめておきます。
参考資料
環境
- Xubuntu Desktop 20.04 LTS (x86_64版)
sysdigによるファイル・システムの観察
参考資料のとおりに、sysdigを利用していきます。
## /etc/resolv.confが書き変わるまでsysdigを実行
$ sudo sysdig -w /tmp/fsdump.scap
^C
## fsdump.scapに保存したデータの解析
$ sudo sysdig -r /tmp/fsdump.scap | grep /etc/resolv.conf
....
409322 11:39:23.933925251 1 rm (17739) < execve res=0 exe=rm args=-f./etc/resolv.conf.dhclient-new.17733. tid=17739(rm) pid=17739(rm) ptid=17733(dhclient-script) cwd= fdlimit=1024 pgft_maj=0 pgft_min=16 vm_size=408 vm_rss=4 vm_swap=0 comm=rm cgroups=cpuset=/.cpu=/system.slice/ifup@ens224.service.cpuacct=/system.slice/ifup@ens... env=requested_domain_name_servers=1.requested_broadcast_address=1.new_network_num... tty=0 pgid=786(dhclient) loginuid=-1
....
このログから、dhclientが/etc/resolv.confを更新しているらしい事が分かりますので、ここからもう少し確認していきます。
dhclientによる/etc/resolv.conf更新の抑制
/sbin/dhclient-script に問題の処理が含まれていることは、少し調べると分かります。
ログファイルの中にあるユニークな文字列が含まれるファイルを探すことができます。
$ apt source isc-dhcp-client
$ cd isc-dhcp-4.4.1
$ find . -type f -exec grep dhclient-new {} \; -print 2>/dev/null
new_resolv_conf="${resolv_conf}.dhclient-new.$$"
new_resolv_conf="${resolv_conf}.dhclient-new.$$"
./debian/dhclient-script.linux
...
関連しそうなコードが dhclient-script.linux に含まれていそうなので、配置されている場所を確認します。
$ locate dhclient-script
/sbin/dhclient-script
/snap/...
...
このスクリプトの中のmake_resulv_conf関数の中で実際の処理は行なわれています。
SHELL関数の make_resolv_conf
は、頻繁に呼ばれていて、設定でresolv.confファイルの置き換えを行なわない手段はなさそうです。
動作を変更する手段は、/sbin/dhclient-scriptを直接編集しないと難しい状況になっています。
あるいは、isc-dhcp-client
パッケージ以外のクライアントを利用することしか良い方法はなさそうです。
最終的にはansibleを利用して、定期的に行なっている変更作業の中に、スクリプトの編集作業を含めることにしました。
setup-dhclient:
ansible all -m replace -b -a "path=/sbin/dhclient-script regexp='(^[ \t]+)make_resolv_conf$$' replace='\1echo _make_resolv_conf'"
make_resolv_conf自体を削除してしまうと、構文的にエラーになる箇所があるので、echoコマンドに置き換えています。
とりあえず、この方法で回避することにしました。
以上