従来の 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 です。
- POST の場合、URL は
JSON API –
https://dns.google/resolve{?name}{&type,cd,do,…}
- その他の GET パラメータについては、JSON API のページをご覧ください。
name
パラメータのみが必須です。
- その他の GET パラメータについては、JSON API のページをご覧ください。
クライアント
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 アプリケーションに関する推奨事項は次のとおりです。
- Google Public DNS DoT または DoH サービスへの接続用に、dns.google ホスト名を SNI として送信します。
- 使用可能なホスト名がない場合(たとえば、日和見的な DoT を行っているアプリケーションの場合)は、空白のままにするのではなく、SNI で IP アドレスを送信することをおすすめします。
- IPv6 アドレスは、
Host
ヘッダーで[2001:db8:1234::5678]
角かっこで囲んで指定する必要がありますが、SNI では角かっこなしで指定する必要があります。
DNS レスポンスの切り捨て
通常、Google Public DNS は DoT クエリや DoH クエリへのレスポンスを切り捨てませんが、次の 2 つの状況が考えられます。
Google Public DNS が権威ネームサーバーから完全な切り捨て型でないレスポンスを取得できない場合は、レスポンスに TC フラグを設定します。
DNS レスポンス(バイナリ DNS メッセージ フォーム)が TCP DNS メッセージの 64 KiB の上限を超える場合、Google Public DNS は、RFC 標準で義務付けられているように TC(切り捨て)フラグを設定することがあります。
ただし、これらのケースでは、結果が同じになるため、クライアントはプレーン TCP やその他のトランスポートを使用して再試行する必要はありません。