Dnsmasqが利用する送信元ポートによるトラブル

Dnsmasqをさくらインターネット上のVPSで構築した後、DNSの正引き・逆引きがどちらも不安定となるトラブルに陥りました。状況と対策を記録しておきます。

環境

  • Server : さくらインターネットVPS
  • OS : Ubuntu20.04.2 LTS
  • Dnsmasq : 2.80

症状

さくらインターネットのVPSにてUbuntu20のデフォルトであるDNSStubListenerからDnsmasqに変更を実施しました。 変更後、nslookupやdigをすると本来名前解決できるべきものがtimeout errorとなったり・ならなかったりと動作が安定しない状況。問題が発生するドメインや検索レコードの法則性は無く、コマンドを実行するタイミングに依存してタイムアウトが発生しているように見受けられました。

原因

結論から言いますと下記2点の組み合わせにより発生していました。

  • Dnsmasqが利用するDNSクエリの送信元ポートが1000番台~20000番台と若いものが多く、カーネルで設定されているエフェメラルポートの範囲外のポートが利用されている
  • さくらインターネットのVPSサーバのパケットフィルタ機能の仕様 (これは原因の一部ですがこれが悪いというわけではありません)

原因追及の詳細

dnsmasqやiptablesの設定を見直しするも原因がわからず、パケットキャプチャにてさらなる状況を確認。 タイムアウトエラーになる場合はDnsmasqからクエリは投げているのにレスポンスが戻ってきていない状況でした。さらにじっくりパケットを眺めていたところ、クエリが成功するパターンのパケットだけ送信元ポート番号が30000万以上のものが多く、失敗するパターンは1000番台~20000番台のものばかりであることを発見。

さくらインターネットのパケットフィルタの仕様では、UDPの場合デフォルトで123と32768-65535のポートしか開いていません。そのため、Dnsmasqが32768番ポート以下を送信元として送ったDNSクエリに対するレスポンスがフィルタに引っ掛かり、タイムアウトとなっていたことが判明。 多くのLinuxカーネルでは/proc/sys/net/ipv4/ip_local_port_rangeで設定される32768-60999を利用するようになっており、これに合わせる形でさくらインターネットのパケットフィルタの仕様も作られているように思います。(でないとVPSサーバから送信されるパケットが戻ってこれない)

というわけで、Dnsmasqは/proc/sys/net/ipv4/ip_local_port_rangeで定義された範囲よりも若いポートを使っていたということが原因でした

1$ cat /proc/sys/net/ipv4/ip_local_port_range
232768   60999

対策

dnsmasq.confにて下記を設定し、Dnsmasqが利用する下限ポート番号を指定。これにて不具合が改善しました。

1min-port=32768