メモ的ななにか

@Maleic1618

Draft: Service binding and parameter specification via the DNS (DNS SVCB and HTTPS RRs)

こんにちは、まれいんです。

この記事は ひとりRFCの旅 Advent Calender 5日目の記事です。

qiita.com

今回はRFCではありませんが、IETFのDomain Name System Operationsというワーキンググループで議論が進行中の、HTTPSリソースレコードについてのドラフトを見て行こうと思います。執筆当時の最新バージョンは02です。

draft-ietf-dnsop-svcb-https-02

概要

最初にAbstractを引用しておきます。

   This document specifies the "SVCB" and "HTTPS" DNS resource record
   (RR) types to facilitate the lookup of information needed to make
   connections to network services, such as for HTTPS origins.  SVCB
   records allow a service to be provided from multiple alternative
   endpoints, each with associated parameters (such as transport
   protocol configuration and keys for encrypting the TLS ClientHello).
   They also enable aliasing of apex domains, which is not possible with
   CNAME.  The HTTPS RR is a variation of SVCB for HTTPS and HTTP
   origins.  By providing more information to the client before it
   attempts to establish a connection, these records offer potential
   benefits to both performance and privacy.

HTTPSに代表されるネットワークサービスについての情報をDNSから引っ張ってこれるようにするもので、 このdraftではSVCB (Service Binding) レコードとHTTPSレコードが追加されるようです。

また、HTTPSプロトコルはクライアント側がサーバ側の情報を事前に知っておいた方がいいことがいくつかあるらしいため、HTTPSレコードではそういった情報を事前に知ることができるようにすることを目指しているようです。

SVCB, HTTPSリソースレコード

SVCBリソースレコードはAliasModeとServiceModeの2種類のモードを持ちます。

モード名 用途
AliasMode ほかのドメイン名へのaliasを貼る
ServiceMode エンドポイントへの接続情報を提供する

また、以下の3つのフィールドを持ちます。

フィールド名 用途
SvcPriority 優先度(低い方が優先)、0のときはAliasMode
TargetName alias先(AliasMode) or alternative endpoint(ServiceMode)
SvcParams ServiceMode限定かつ任意でkey-value形式でtargetの情報を出せる

必要であればAdditional SectionにAレコードやAAAA, CNAMEレコードを返してもOKです。

リソースレコードタイプの番号は64です。

HTTPSはSVCBリソースレコードとほぼ同様ですが、HTTPSプロトコル特有のものを扱えるようになっています。 リソースレコードタイプの番号は65です。

wire format

wire formatは以下です。 ASCIIの図はなかったので、それっぽい感じで作ってみました。

RDATA

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                 SvcPriority                   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                 TargetName                    /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                 SvcParams                     /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

SvcParams

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                  SvcParamKey                  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|               SvcParamValueの長さ               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                 SvcParamValue                 /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

それではリソースレコードの詳細を見て行きましょう。

AliasMode

AliasModeはあるドメイン名にて指定したプロトコル、指定したポートで動作しているサービスを別のドメイン名に飛ばすものです。 例えば example.jp というドメイン名でWebサーバ(443)とDNSサーバ(53)とTFTPサーバ(69)が動いているとき、各サービスごとに別のドメイン名を用意して飛ばす、という状況を想定してください。 このとき、サービス毎にAliasModeでSVCBレコードを作ることで分散させることができます。

              |--> dns.example.com (DNSサーバ)
              |
example.com -----> www.example.com (Webサーバ)
              |
              |--> tftp.example.com (TFTPサーバ)

例えば、tftp://example.com:69 というサービスを svc4.example.net へaliasするときは、ポート番号とプロトコル名を含めた以下のようなレコードになります。

_69._tftp.example.com. 7200 IN SVCB 0 web.example.com.

HTTPSレコードはHTTPSであることが分かっているので、ポート番号とプロトコルのprefixなしで記載することができます。

example.com. 7200 IN HTTPS 0 www.example.com.

また、TargetNameに . が指定されている場合は、サービスが稼働していない or 存在しないことを表します。

_3389._rdp.example.com. 7200 IN HTTPS 0 .
# => RDPは稼働していない

ServiceMode

www.example.comwebサービスを動かしているが、裏では www[1-5].example.com という複数のサーバが動いている状況を考えてください。 (draftでいうところのmultiple endpoint)

この時、以下のようにして裏のサーバの情報を教えることができます。

www.example.net.  7200  IN SVCB 3 www1.example.net. alpn="bar" port="8004" echconfig="..."

また、一部のサーバは暗号化の種類が多いだったり新しい機能が使えるなどで優先的に使わせたい場合は、SvcPriorityを利用することで優先的に使わせることができます。

TargetNameに . が指定されている場合は、そのドメイン名でサービスが動いていることを表します。 利用イメージは以下のような感じです。(draftから引用)

   example.com.      7200  IN HTTPS 0 svc.example.net.
   svc.example.net.  7200  IN CNAME svc2.example.net.
   svc2.example.net. 7200  IN HTTPS 1 . port=8002 echconfig="..."
   svc2.example.net. 300   IN A     192.0.2.2
   svc2.example.net. 300   IN AAAA  2001:db8::2

SvcParam

ServiceModeの時にだけkey-value形式で情報を渡せるSvcParamsですが、このdraftでいくつか定義されています。

SvcParamsKey 意味
"alpn", "no-default-alpn" Application-Layer Protocol Negotiation(よく知らない)で利用
"port" サービスが提供されているポート番号
"echconfig" TLSのEncrypted Client Hello(よく知らない)の設定
"ipv4hint", "ipv6hint" ipv[46]アドレスのヒント

おまけ

cloudflareは試験的に対応しているようです。

$ dig blog.cloudflare.com -t TYPE65 @1.1.1.1

; <<>> DiG 9.16.8-Debian <<>> blog.cloudflare.com -t TYPE65 @1.1.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40109
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

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

;; ANSWER SECTION:
blog.cloudflare.com.    300     IN      TYPE65  \# 76 000100000100150568332D32390568332D32380568332D3237026832 0004000868121A2E68121B2E00060020260647000000000000000000 68121A2E26064700000000000000000068121B2E

;; Query time: 0 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Mon Nov 30 01:54:43 JST 2020
;; MSG SIZE  rcvd: 136