にゃみかんてっくろぐ

猫か百合を見守る壁になりたい

同じドメインに A レコードが複数あるときのクライアントの挙動 (Chrome, Safari, curl)

おことわり: TCP/IP スタックの設定値などを深追いしておらず、「こう動いたが、根拠は調べていない」というレベルのものです。

いきなりまとめ

前提条件

同一ドメインに複数の A レコードを設定する。なお、 IP アドレスは RFC5737 で規定されている仕様書やドキュメント向けの IPv4 アドレスであり、接続はできない。

$ dig roundrobin.nyamikan.net A

; <<>> DiG 9.16.1-Ubuntu <<>> roundrobin.nyamikan.net A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49795
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;roundrobin.nyamikan.net.       IN      A

;; ANSWER SECTION:
roundrobin.nyamikan.net. 0      IN      A       203.0.113.1
roundrobin.nyamikan.net. 0      IN      A       203.0.113.3
roundrobin.nyamikan.net. 0      IN      A       203.0.113.4
roundrobin.nyamikan.net. 0      IN      A       203.0.113.2

確認方法

HTTP アクセスを試み、 Wireshark でパケットキャプチャして挙動を観測する。

  • 複数の IPv4 アドレスに接続しにいくか
  • 順番に接続しにいくか、同時に接続しにいくか
  • 接続間隔( 1 IPv4 アドレスあたりのタイムアウト)はどの程度か

確認結果

OS ツール 挙動
Windows 10
バージョン 20H2
OS ビルド 19042.630
Google Chrome
87.0.4280.66
アドレスバー入力
約 21 秒間隔で順番に接続試行
その後 ERR_CONNECTION_TIMED_OUT 表示
さらに自動的にリトライ
Windows 10
バージョン 20H2
OS ビルド 19042.630
Google Chrome
87.0.4280.66
Fetch API
約 21 秒間隔で順番に接続試行
その後エラー
Ubuntu 20.04.1 LTS
Windows Subsystem for Linux 2
curl 約 32 秒間隔で順番に接続試行
その後エラー
macOS Mojave
(バージョン 10.14.6)
Google Chrome
86.0.4240.198
アドレスバー入力
約 75 秒間隔で順番に接続試行
4 分経過時点で ERR_CONNECTION_TIMED_OUT 表示
さらに自動的にリトライ
macOS Mojave
(バージョン 10.14.6)
Google Chrome
86.0.4240.198
Fetch API
約 75 秒間隔で順番に接続試行
4 分経過時点でエラー
macOS Mojave
(バージョン 10.14.6)
Safari
13.1.2 (14609.3.5.1.5)
アドレスバー入力
0.25 秒間隔で同時に接続試行
約 70 秒でエラー
macOS Mojave
(バージョン 10.14.6)
Safari
13.1.2 (14609.3.5.1.5)
Fetch API
0.25 秒間隔で同時に接続試行
約 70 秒でエラー
macOS Mojave
(バージョン 10.14.6)
curl 約 75 秒間隔で順番に接続試行
その後エラー
  • いずれのツールも複数の IPv4 アドレスに接続試行していた。
  • 順番に接続試行するものが多く、 また試行間隔が長いものが多い。
  • macOS Safari が 0.25 秒間隔で同時に接続試行している点は興味深い。

不正確な推測、憶測

詳細な確認結果

Windows 10 (バージョン 20H2, OS ビルド 19042.630)

Google Chrome (87.0.4280.66) アドレスバー入力

f:id:no_clock:20201122010334p:plain

f:id:no_clock:20201122010500p:plain

Google Chrome (87.0.4280.66) Fetch API

f:id:no_clock:20201122010408p:plain

f:id:no_clock:20201122010507p:plain

Ubuntu 20.04.1 LTS, Windows Subsystem for Linux 2, curl

$ uname -a
Linux <Machine Name> 4.19.128-microsoft-standard #1 SMP Tue Jun 23 12:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

$ curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

$ curl http://roundrobin.nyamikan.net/ -v
*   Trying 203.0.113.1:80...
* TCP_NODELAY set
* connect to 203.0.113.1 port 80 failed: Connection timed out
*   Trying 203.0.113.3:80...
* TCP_NODELAY set
* connect to 203.0.113.3 port 80 failed: Connection timed out
*   Trying 203.0.113.2:80...
* TCP_NODELAY set
* connect to 203.0.113.2 port 80 failed: Connection timed out
*   Trying 203.0.113.4:80...
* TCP_NODELAY set
* connect to 203.0.113.4 port 80 failed: Connection timed out
* Failed to connect to roundrobin.nyamikan.net port 80: Connection timed out
* Closing connection 0
curl: (28) Failed to connect to roundrobin.nyamikan.net port 80: Connection timed out

f:id:no_clock:20201122010121p:plain

macOS Mojave (バージョン 10.14.6)

Google Chrome (86.0.4240.198) アドレスバー入力

f:id:no_clock:20201122010544p:plain

f:id:no_clock:20201122010832p:plain

Google Chrome (86.0.4240.198) Fetch API

f:id:no_clock:20201122010601p:plain

f:id:no_clock:20201122010839p:plain

Safari (13.1.2 (14609.3.5.1.5)) アドレスバー入力

f:id:no_clock:20201122010622p:plain

f:id:no_clock:20201122010847p:plain

Safari (13.1.2 (14609.3.5.1.5)) Fetch API

f:id:no_clock:20201122010645p:plain

f:id:no_clock:20201122010855p:plain

curl
$ uname -a
Darwin <Machine Name> 18.7.0 Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X86_64 x86_64

$ curl --version
curl 7.54.0 (x86_64-apple-darwin18.0) libcurl/7.54.0 LibreSSL/2.6.5 zlib/1.2.11 nghttp2/1.24.1
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy

$ curl http://roundrobin.nyamikan.net/ -v
*   Trying 203.0.113.3...
* TCP_NODELAY set
* Connection failed
* connect to 203.0.113.3 port 80 failed: Operation timed out
*   Trying 203.0.113.1...
* TCP_NODELAY set
* Connection failed
* connect to 203.0.113.1 port 80 failed: Operation timed out
*   Trying 203.0.113.4...
* TCP_NODELAY set
* After 74518ms connect time, move on!
* connect to 203.0.113.4 port 80 failed: Operation timed out
*   Trying 203.0.113.2...
* TCP_NODELAY set
* After 37258ms connect time, move on!
* connect to 203.0.113.2 port 80 failed: Operation timed out
* Failed to connect to roundrobin.nyamikan.net port 80: Operation timed out
* Closing connection 0
curl: (7) Failed to connect to roundrobin.nyamikan.net port 80: Operation timed out

f:id:no_clock:20201122010310p:plain