DNS のセキュアなトランスポート

従来の DNS クエリとレスポンスは暗号化なしに UDP または TCP 経由で送信されるため、監視、なりすまし、DNS ベースのインターネット フィルタリングの対象となります。再帰リゾルバと権威ネームサーバー間のメッセージには追加の保護機能が組み込まれることが多いため、Google Public DNS などのパブリック リゾルバからのクライアントへのレスポンスは、特に多くのネットワークを通過する可能性があるため、この脆弱性が特に高くなっています。

こうした問題に対処するため、Google は 2016 年、HTTPS 経由の DNS をリリースし(現在の DoH)、HTTPS を介した DNSSEC 検証済みの DNS 解決と QUIC を提供しています。2019 年には、Android のプライベート DNS 機能で使用される DNS over TLS(DoT)標準のサポートも追加しました。

DoH と DoT は、クライアントとリゾルバ間のプライバシーとセキュリティを強化し、DNSSEC の Google Public DNS 検証を補完して、DNSSEC で署名されたドメインにエンドツーエンドの認証 DNS を提供します。Google Public DNS を使用すると、DoH と DoT の両方のクライアントで、迅速でプライベート、安全な DNS 解決が可能になります。

サポートされている TLS バージョンと暗号スイート

Google Public DNS は、DoH と DoT の両方で TLS 1.2 と TLS 1.3 をサポートしています。それより前のバージョンの TLS または SSL はサポートされていません。フォワード セキュリティと追加データによる認証暗号化(AEAD)を備えた暗号スイートのみがサポートされています。Qualys SSL Labs には、現在サポートされている暗号スイートのセットが表示されます。

エンドポイント

Google Public DNS は、DoH と DoT に次のエンドポイントを使用します。

DoT(ポート 853)dns.google

DoH(ポート 443)の URI テンプレート

  • RFC 8484 – https://dns.google/dns-query{?dns}

    • POST の場合、URL は https://dns.google/dns-query のみであり、HTTP リクエストの本文はコンテンツ タイプが application/dns-message のバイナリ UDP DNS ペイロードです。
    • GET の場合、これは https://dns.google/dns-query?dns=BASE64URL_OF_QUERY です。
  • JSON API – https://dns.google/resolve{?name}{&type,cd,do,…}

    • その他の GET パラメータについては、JSON API のページをご覧ください。name パラメータのみが必須です。

クライアント

DoT または DoH を使用するクライアント アプリケーションが多数あり

  • Android 9(Pie)の「プライベート ブラウジング」機能 – DoT
  • イントラ(Android アプリ) – DoH

dnsprivacy.org ウェブサイトには、DoT と DoH の他のクライアントがリストされていますが、通常、ある程度の技術的な構成が必要になります。

コマンドラインの例

次のコマンドラインの例は、実際のクライアントでの使用を意図したものではありません。一般的に利用できる診断ツールの例にすぎません。

ドット

次のコマンドには、Knot DNS kdig 2.3.0 以降が必要です。2.7.4 以降の場合は、+tls‑sni のコメント化を解除し、TLS 1.3 で必要な SNI を送信します。

kdig -d +noall +answer @dns.google example.com \
  +tls-ca +tls-hostname=dns.google # +tls-sni=dns.google
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(dns.google), port(853), protocol(TCP)
;; DEBUG: TLS, imported 312 system certificates
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: lQXSLnWzUdueQ4+YCezIcLa8L6RPr8Wgeqtxmw1ti+M=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=Google Internet Authority G3
;; DEBUG:      SHA-256 PIN: f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is trusted.

;; ANSWER SECTION:
example.com.            2046    IN      A       93.184.216.34
kdig -d +noall +answer @dns.google example.com \
  +tls-pin=f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78= \
  # +tls-sni=dns.google
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(dns.google), port(853), protocol(TCP)
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: lQXSLnWzUdueQ4+YCezIcLa8L6RPr8Wgeqtxmw1ti+M=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=Google Internet Authority G3
;; DEBUG:      SHA-256 PIN: f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78=, MATCH
;; DEBUG: TLS, skipping certificate verification

;; ANSWER SECTION:
example.com.            5494    IN      A       93.184.216.34

DoH

RFC 8484 の POST

このコマンドの Base64Url でエンコードされた文字列は、RFC 8484 セクション 4.1 で推奨されている DNS ID フィールドをゼロに設定して dig +noedns example.test A によって送信される DNS メッセージです。シェルコマンドは、Content-Type application/dns-message を使用して、その DNS クエリをバイナリデータの本文コンテンツとして送信します。

echo AAABAAABAAAAAAAAB2V4YW1wbGUEdGVzdAAAAQAB | base64 --decode |
 curl -is --data-binary @- -H 'content-type: application/dns-message' \
   https://dns.google/dns-query
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Wed, 29 May 2019 19:37:16 GMT
expires: Wed, 29 May 2019 19:37:16 GMT
cache-control: private, max-age=19174
content-type: application/dns-message
server: HTTP server (unknown)
content-length: 45
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

RFC 8484 GET

このコマンドの Base64Url でエンコードされた文字列は、DNS ID フィールドが 0 に設定された dig +noedns example.com A によって送信された DNS メッセージです。この場合、URL で明示的に渡されます。

curl -i https://dns.google/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Wed, 29 May 2019 19:37:16 GMT
expires: Wed, 29 May 2019 19:37:16 GMT
cache-control: private, max-age=19174
content-type: application/dns-message
server: HTTP server (unknown)
content-length: 45
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

JSON GET

ここでは DoH に JSON API を使用します。

curl -i 'https://dns.google/resolve?name=example.com&type=a&do=1'
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Thu, 30 May 2019 02:46:46 GMT
expires: Thu, 30 May 2019 02:46:46 GMT
cache-control: private, max-age=10443
content-type: application/x-javascript; charset=UTF-8
server: HTTP server (unknown)
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"
accept-ranges: none
vary: Accept-Encoding

{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": true,"CD": false,"Question":[ {"name": "example.com.","type": 1}],"Answer":[ {"name": "example.com.","type": 1,"TTL": 10443,"data": "93.184.216.34"},{"name": "example.com.","type": 46,"TTL": 10443,"data": "a 8 2 86400 1559899303 1558087103 23689 example.com. IfelQcO5NqQIX7ZNKI245KLfdRCKBaj2gKhZkJawtJbo/do+A0aUvoDM5A7EZKcF/j8SdtyfYWj/8g91B2/m/WOo7KyZxIC918R1/jvBRYQGreDL+yutb1ReGc6eUHX+NKJIYqzfal+PY7tGotS1Srn9WhBspXq8/0rNsEnsSoA="}],"Additional":[]}

IP アドレス URL の TLS 1.3 と SNI

TLS 1.3 では、クライアントはサーバー名識別(SNI)を提供する必要があります。

SNI 拡張機能は、SNI 情報が(IP アドレスではなく)DNS ドメインであることを指定します。

"HostName" はクライアントが認識する、サーバーの完全修飾 DNS ホスト名を含みます。ホスト名は、ASCII エンコードで末尾のドットのないバイト文字列として表されます。これにより、RFC5890 で定義されている A ラベルを使用して、国際化ドメイン名をサポートできます。DNS ホスト名では大文字と小文字が区別されません。ホスト名を比較するアルゴリズムについては、RFC5890 のセクション 2.3.2.4 をご覧ください。

リテラルの IPv4 アドレスと IPv6 アドレスは「HostName」では許可されません。

TLS 1.3 でセキュリティの改善を利用したい DoH または DoT アプリケーションでは、これらの要件を満たすことが難しい場合があります。現在、Google Public DNS は SNI を提供しない TLS 1.3 接続を受け入れますが、将来、運用上またはセキュリティ上の理由で、この点を変更する必要がある場合があります。

SNI に関する DoT アプリケーションまたは DoH アプリケーションに関する推奨事項は次のとおりです。

  1. Google Public DNS DoT または DoH サービスへの接続用に、dns.google ホスト名を SNI として送信します。
  2. 使用可能なホスト名がない場合(たとえば、日和見的な DoT を行っているアプリケーションの場合)は、空白のままにするのではなく、SNI で IP アドレスを送信することをおすすめします。
  3. IPv6 アドレスは、Host ヘッダーで [2001:db8:1234::5678] 角かっこで囲んで指定する必要がありますが、SNI では角かっこなしで指定する必要があります。

DNS レスポンスの切り捨て

通常、Google Public DNS は DoT クエリや DoH クエリへのレスポンスを切り捨てませんが、次の 2 つの状況が考えられます。

  1. Google Public DNS が権威ネームサーバーから完全な切り捨て型でないレスポンスを取得できない場合は、レスポンスに TC フラグを設定します。

  2. DNS レスポンス(バイナリ DNS メッセージ フォーム)が TCP DNS メッセージの 64 KiB の上限を超える場合、Google Public DNS は、RFC 標準で義務付けられているように TC(切り捨て)フラグを設定することがあります。

ただし、これらのケースでは、結果が同じになるため、クライアントはプレーン TCP やその他のトランスポートを使用して再試行する必要はありません。