Hateburo: kazeburo hatenablog

SRE / 運用系小姑 / Goを書くPerl Monger

resolv.conf におけるDNS名前解決のタイムアウト

resolv.confに記述したDNSサーバへの名前解決のタイムアウトとリトライ回数について改めて確認したので忘備録

CentOS7系およびRocky Linux 9系で確認しています。

/etc/resolv.confDNSサーバが次のように指定されている場合、

nameserver 198.51.100.3
nameserver 198.51.100.4

以下の順で利用されます。

  1. 198.51.100.3タイムアウト 5秒
  2. 198.51.100.45秒 ✖️ 2 ➗ サーバ台数 (小数点切り捨て)のタイムアウト=5 秒

これを2回繰り返し、両方接続不可能な場合、合計20秒間名前解決しようとします。

3台ある場合、

nameserver 198.51.100.3
nameserver 198.51.100.4
nameserver 198.51.100.5
  1. 198.51.100.3タイムアウト 5秒
  2. 198.51.100.45秒 x 2 ➗ サーバ台数 (小数点切り捨て)のタイムアウト=3 秒
  3. 198.51.100.52. の倍のタイムアウト=6秒

これを2回繰り返し、5秒→3秒→6秒を2回の28秒間試行します。

3台以上DNSサーバがある場合は、4台目以降は無視されます。

タイムアウトoptions timeout:N 、試行回数は options attempts:M 指定できます。それぞれ一般的なデフォルトは 5秒2回 となります。

タイムアウトを短くして試行回数を増やすのであれば、次のようにするのが良さそうです。

nameserver 198.51.100.3
nameserver 198.51.100.4
options timeout:1 attempts:3

デフォルト5秒はWebサーバ用途では長すぎるかもしれません。

また、ubuntu 22.04などでは systemd-resolvedが動作しています。こちらではローカルでキャッシュをもっていたり、接続できないDNSサーバにしばらくのアクセスをしない機能があるようです。

straceで確認

2台の場合

11:56:02.580141 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 4
11:56:02.580190 setsockopt(4, SOL_IP, IP_RECVERR, [1], 4) = 0
11:56:02.580237 connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.3")}, 16) = 0
11:56:02.580294 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
11:56:02.580337 sendto(4, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:02.580428 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:07.585638 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
11:56:07.585726 setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
11:56:07.585766 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.4")}, 16) = 0
11:56:07.585807 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
11:56:07.585837 sendto(5, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:07.585924 poll([{fd=5, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:12.591058 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
11:56:12.591182 sendto(4, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:12.591282 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:17.596483 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
11:56:17.596563 sendto(5, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:17.596629 poll([{fd=5, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:22.601778 close(4)                = 0
11:56:22.601824 close(5)                = 0

3台の場合

12:14:57.572565 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 4
12:14:57.572597 setsockopt(4, SOL_IP, IP_RECVERR, [1], 4) = 0
12:14:57.572626 connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.3")}, 16) = 0
12:14:57.572682 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
12:14:57.572731 sendto(4, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:14:57.572795 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
12:15:02.577947 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
12:15:02.578009 setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
12:15:02.578045 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.4")}, 16) = 0
12:15:02.578101 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
12:15:02.578138 sendto(5, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:02.578216 poll([{fd=5, events=POLLIN}], 1, 3000) = 0 (Timeout)
# 3秒
12:15:05.581337 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 6
12:15:05.581406 setsockopt(6, SOL_IP, IP_RECVERR, [1], 4) = 0
12:15:05.581443 connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.5")}, 16) = 0
12:15:05.581484 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}])
12:15:05.581512 sendto(6, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:05.581568 poll([{fd=6, events=POLLIN}], 1, 6000) = 0 (Timeout)
# 6秒
12:15:11.587696 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
12:15:11.587759 sendto(4, "\366\237\1\0\0\1\0\0\0\0\0\0\6sakura\2ad\2jp\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:11.587830 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
12:15:16.592954 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
12:15:16.593015 sendto(5, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:16.593077 poll([{fd=5, events=POLLIN}], 1, 3000) = 0 (Timeout)
# 3秒
12:15:19.596238 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}])
12:15:19.596327 sendto(6, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:19.596422 poll([{fd=6, events=POLLIN}], 1, 6000) = 0 (Timeout)
# 5秒
12:15:25.602566 close(4)                = 0
12:15:25.602637 close(5)                = 0
12:15:25.602668 close(6)                = 0