HTTPS RRのバイナリを読む

読むバイナリは、dig cloudflare.com type65 の結果返ってくるものの、RRの部分です。(参考)

; <<>> DiG 9.16.1-Ubuntu <<>> cloudflare.com type65
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47082
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;cloudflare.com.                        IN      TYPE65

;; ANSWER SECTION:
cloudflare.com.         107     IN      TYPE65  \# 79 000100000100180268330568332D32390568332D32380568332D3237 02683200040008681084E5681085E500060020260647000000000000 000000681084E5260647000000000000000000681085E5

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: 土  1月 15 15:52:40 JST 2022
;; MSG SIZE  rcvd: 134

読む際には、下記のバージョンのドラフトを参考にしています。

www.ietf.org

ちなみに、ある程度新しめのWiresharkだと普通に解釈してくれます。(3.6.1で確認。3.2.3にはありませんでした)

f:id:neko--suki:20220116113155p:plain
Wiresharkのキャプチャ

実装はおそらくこのあたり かと思います。

Wiresharkからcopy as Hex Stream すると以下のようになります。

\x00\x01\x00\x00\x01\x00\x18\x02\x68\x33\x05\x68\x33\x2d\x32\x39
\x05\x68\x33\x2d\x32\x38\x05\x68\x33\x2d\x32\x37\x02\x68\x32\x00
\x04\x00\x08\x68\x10\x84\xe5\x68\x10\x85\xe5\x00\x06\x00\x20\x26
\x06\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x10\x84\xe5\x26
\x06\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x10\x85\xe5

以下のように解釈できます。

\x00\x01 : SvcPriority 0 ではないので、ServiceMode
\x00:  fully-qualified Target Name. ここではroot label 

以降はSvcParam のリスト
\x00\x01: SvcParamKeys = ALPN
\x00\x18: SrvParamValueが24バイト
\x02: 長さ2のalpn-id
\x68\x33: h3
\x05: 長さ5のalpn-id
\x68\x33\x2d\x32\x39 : h3-29
\x05: 長さ5のalpn-id
\x68\x33\x2d\x32\x38: h3-28
\x05: 長さ5のalpn-id
\x68\x33\x2d\x32\x37: h3-27
\x02: 長さ2のalpn-id
\x68\x32: h2

\x00\x04: SvcPramKey = ipv4hint
\x00\x08: SvcParamValueの長さ=8バイト、2つのipv4アドレスが含まれる
\x68\x10\x84\xe5: 1つ目のIPv4アドレス
\x68\x10\x85\xe5: 2つ目のIPv4アドレス

\x00\x06: SvcParamKey=ipv6hint
\x00\x20: SvcParamValue=32バイト、2つのipv6アドレスが含まれる
\x26\x06\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x10\x84\xe5: 1つ目のipv6アドレス
\x26\x06\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x10\x85\xe5: 2つ目のipv6アドレス

SvcPriority

最初の2オクテットが、SrvPriorityを表します。0の場合は、AliasMode、それ以外の場合は、ServiceModeとなります。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-2.2-2.1

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-2.4.1-1

fully-qualified Target Name

長さがプレフィックスになっているラベルで表現されます、非圧縮のfully-qualified Target Name です。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-2.2-2.2

root labelであることは、D.2 の例から推測しました。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#appendix-D.2

厳密に見るためにRFC1035、RFC6895をたどっています。

RFC1035のnameの定義があります。

https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1

<domain> ::= <subdomain> | " "
<subdomain> ::= <label> | <subdomain> "." <label>
<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]

それに対して、RFC6895 で以下のように言及されています。

https://datatracker.ietf.org/doc/html/rfc6895#section-3.3.2

3.3.2.  Label Contents and Use

   The last label in each NAME is "ROOT", which is the zero-length
   label.  By definition, the null or ROOT label cannot be used for any
   other NAME purpose.

ここでは長さ0の名前なので、root labelということが分かります。

'.' の場合、オーナー名がeffective TargetNameとして使われています。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-2.5.2-1

SvcParamsのリスト

残りの部分は、空でなければ、SvcParamsのリストが含まれています。リストの要素はSvcParamKey=SrvParamValue のペアで定義されます。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-2.2-3

それぞれの要素は、SrvParamKeyを表す2オクテット、SrvParamValueの長さを表す2オクテット、SrvParamValueの値 から構成されています。

ALPN

SvcParamKeyが0x01のの場合にALPNであることは、15.3.2のIANA Service Parameter Keys (SvcParamKeys) に初期に登録されるものから読み解けます。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#name-initial-contents

リストのSrvParamValue全体の長さは、0x00, 0x18 から24バイトであることが分かります。

ALPNのSrvPramValueは、少なくとも1つ以上のapln-idを含んでいます。長さを表す1オクテットのプレフィックスと、alpn-idから構成されます。

ここの要素をそれぞれ読み解くと、h3, h3-29, h3-28, h3-27, h2 というリストであることが分かります。

ipv4hint

次のSvcParamKeyは、0x04なので、ipv4hintであることが分かります。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#name-initial-contents

ipv4hintの詳細は、https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#svcparamkeys-iphints に書かれています。

フォーマットは、ipアドレスのリストです。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#section-7.4-3

ここでは長さが8バイトなので2つのipv4アドレスを含んでいることが分かります。

ipv6hint

次のSvcParamKeyは0x06なので、ipv6hintであることが分かります。

https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html#name-initial-contents

ここでは、長さが32バイトなので、2つのipv6アドレスが含まれていることが分かります。