ぶていのログでぶログ

思い出したが吉日

Ubuntu18.04のDNSリゾルバをsystemd-resolvedからdnsmasqに変更する

デスクトップLinuxとして使っているUbuntu18.04で、ドメインごとに問い合わせるDNSサーバを変更したい場面が出てきた。 具体的には、VPNを接続してその接続先のドメインだけはDNSサーバを変更したいみたいな。

Ubuntu18.04ではDNSゾルバとして、systemd-resolvedを使っている。 こいつでは、やりたいことは出来ないようなのでdnsmasqに変更することにした。

なぜdnsmasqなのか?

すでにインストールされていて*1、そしてNetworkManagerが対応している。 Ubuntu18.04ではネットワーク関連の設定をNetworkManagerが管理しているので、とても都合がよい。 そんなこんなでdnsmasqを使うことにした。

systemd-resolvedを止める

止める手順としてはまず、/etc/systemd/resolved.confResolve セクションに DNSStubListner=no を設定する。

[Resolve]
DNSStubListener=no

設定を行ったら systemd-resolved を再起動する。

$ sudo systemctl restart systemd-resolved

再起動した後、digっても何も返ってこないはず。

NetworkManagerの設定をする

この状態でdnsmasqを起動してもいいのだが、NetworkManagerと連携させないとDHCPで降ってくるDNSサーバの情報を反映させることができないため、連携設定を行う。 連携設定は /etc/NetworkManager/NetworkManager.confmainセクションに dns=dnsmasq を設定する。

[main]
dns=dnsmasq

次に、NetworkManagerを再起動したいのだが、実はまだdnsmasqとの連携設定が出来ていない。 というのも /etc/resolv.conf が systemd-resolvedが生成するresolv.confへのシンボリックリンクになっている場合、NetworkManagerは自動的にsystemd-resolvedと連携するようになる。 なので、 このシンボリックリンクを削除する。

$ ls -lah /etc/resolv.conf
lrwxrwxrwx 1 root root 39  8月 10 17:32 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ sudo unlink /etc/resolv.conf

/etc/resolv.conf は作らなくてもNetworkManagerを再起動すれば作成されるので問題ない。 ということで、NetworkManagerを再起動する。

$ sudo systemctl restart NetworkManager

dnsmasqの設定を変える

ここまでの設定でdnsmasqがDNSゾルバになっているはず。 しかし、まだ当初やりたかった 特定ドメインだけDNSサーバを変える を達成していない。 NetworkManagerで起動するdnsmasqは /etc/NetworkManager/dnsmasq.d 配下にあるファイルを読み込むのでこのディレクトリ配下に設定ファイルを作成する。 ファイル名は何でも良いのだが、なんとなく default.conf にした。

$ cat /etc/NetworkManager/dnsmasq.d/default.conf
server=/example.com/192.0.2.0

設定ファイルを作成後、NetworkManagerを再起動すると反映される*2

digれない!

dnsmasqを使うようになってからdigを打ったら何も取得できない!!!

$ dig

; <<>> DiG 9.11.3-1ubuntu1.2-Ubuntu <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 57447
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: b9472f88fb4991ce (echoed)
;; QUESTION SECTION:
;.                              IN      NS

;; Query time: 3 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Fri Oct 12 19:46:35 JST 2018
;; MSG SIZE  rcvd: 40

結論からいうと、私の環境が悪かった。 dnsmasqが問い合わせに行く上位のDNSサーバ(つまりDHCPで設定されたDNSサーバ)が、DNS cookieを受け付けていなかったのであった。 よって、+nocookie オプションをつければ問題は解決された。

$ dig +nocookie

; <<>> DiG 9.11.3-1ubuntu1.2-Ubuntu <<>> +nocookie
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28281
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;.                              IN      NS

;; ANSWER SECTION:
.                       77519   IN      NS      j.root-servers.net.
.                       77519   IN      NS      k.root-servers.net.
.                       77519   IN      NS      m.root-servers.net.
.                       77519   IN      NS      h.root-servers.net.
.                       77519   IN      NS      b.root-servers.net.
.                       77519   IN      NS      l.root-servers.net.
.                       77519   IN      NS      a.root-servers.net.
.                       77519   IN      NS      e.root-servers.net.
.                       77519   IN      NS      c.root-servers.net.
.                       77519   IN      NS      d.root-servers.net.
.                       77519   IN      NS      i.root-servers.net.
.                       77519   IN      NS      g.root-servers.net.
.                       77519   IN      NS      f.root-servers.net.

;; ADDITIONAL SECTION:
j.root-servers.net.     86400   IN      A       192.58.128.30
a.root-servers.net.     26879   IN      A       198.41.0.4

;; Query time: 8 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Fri Oct 12 19:49:53 JST 2018
;; MSG SIZE  rcvd: 284

ちなみにこの問題はsystemd-resolvedのときは起こらなかった。 systemd-resolvedは上位のDNSサーバに問い合わせるときには、どうやらDNS cookieをつけていないようだった。 dnsmasqでも同じ設定ができるのかどうかは調査中…。

Tips: 現在設定されている問い合わせ先DNSサーバを知る

通常、問い合わせ先のDNSサーバは /etc/resolv.conf を見ればわかるんのだが、今回の設定によりローカルをみるようになっている。 しかし、nmcliから確認することができる。

$ nmcli d sh | grep DNS

ちなみに、systemd-resolvedでは systemd-resolv というコマンドがありこちらで確認できる。

*1:私の環境ではインストールされていた。もしかしたら、何かのついでにインストールされていたのかもしれない

*2:もしかしたらこの手順は不要かもしれないが、調査していない