傳統 DNS 查詢和回覆會在未加密的情況下透過 UDP 或 TCP 傳送, 因此能夠受到監視、假冒以及 DNS 型網際網路篩選。 更特別地回應來自公開解析器 (例如 Google 公用 DNS) 的用戶端回應 訊息功能可能會透過許多網路傳送,但 遞迴解析器和權威名稱伺服器之間經常會整合 額外的保護措施
為解決這些問題,我們在 2016 年推出 DNS over HTTPS (現稱 DoH) 提供透過 HTTPS 和 QUIC 加密的 DNSSEC 驗證 DNS 解析。 我們在 2019 年開始支援適用於多種用途的 DNS over TLS (DoT) 標準, Android 的私人 DNS 功能。
DoH 和 DoT 可強化用戶端和解析器之間的隱私與安全性, 補充 Google 公用 DNS 驗證的 DNSSEC 功能,以便提供端對端 且具備 DNSSEC 簽署的網域藉由 Google 公用 DNS 致力於為 DoH 和 DoT 用戶端。
支援的 TLS 版本和加密套件
Google 公用 DNS 支援 DoH 和 DoT 的 TLS 1.2 和 TLS 1.3;不早 支援的 TLS 或 SSL 版本。只有具前瞻性的加密套件 和「以額外資料進行驗證加密」(AEAD) 的系統支援。 Qualys SSL Labs 會顯示目前支援的加密套件組合。
端點
Google 公用 DNS 針對 DoH 和 DoT 使用下列端點:
DoT (通訊埠 853) dns.google
DoH (通訊埠 443) URI 範本
RFC 8484 -
https://dns.google/dns-query{?dns}
- 如果是 POST,則網址為
https://dns.google/dns-query
,且 HTTP 要求是含有內容類型的二進位 UDP DNS 酬載 application/dns-message. - 如果是 GET,這個參數為
https://dns.google/dns-query?dns=
BASE64URL_OF_QUERY。
- 如果是 POST,則網址為
JSON API -
https://dns.google/resolve{?name}{&type,cd,do,…}
- 如要進一步瞭解 GET 參數,請參閱
JSON API 頁面。
只需要
name
參數。
- 如要進一步瞭解 GET 參數,請參閱
JSON API 頁面。
只需要
客戶
部分用戶端應用程式使用 DoT 或 DoH
- Android 9 (Pie)「私密瀏覽」功能 – DoT
- Intra (Android 應用程式) - DoH
dnsprivacy.org 網站列出 DoT 和 DoH 的其他幾個用戶端, 但通常需要中等的技術設定
指令列範例
下列指令列範例不適合用於實際用戶端 僅僅僅用於呈現常見診斷工具的插圖
DoT
下列指令需要 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 編碼字串是
dig +noedns example.test A
,並將 DNS ID 欄位設為零 (按照建議做法)
RFC 8484 第 4.1 節。殼層指令會將 DNS 查詢當做
二進位資料主體內容,使用 Content-Type application/dns-message
。
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 編碼字串是
dig +noedns example.com A
,將 DNS ID 欄位設為零。在本例中
明確透過網址傳遞
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 位址網址適用的 TLS 1.3 和 SNI
TLS 1.3 要求用戶端 提供伺服器名稱識別 (SNI)。
SNI 擴充功能會指定 SNI 資訊為 DNS 網域 (而不是 IP 位址):
「主機名稱」包含伺服器的完整 DNS 主機名稱 。主機名稱以位元組字串表示 使用 ASCII 編碼,而不再以點結尾。如此一來 國際化的網域名稱,方法是使用 RFC5890。DNS 主機名稱不區分大小寫。要比較的演算法 主機名稱請參閱 RFC5890 的 2.3.2.4 節。
「HostName」中不得使用常值 IPv4 和 IPv6 位址。
無法滿足 DoH 或 DoT 應用程式的需求 享有傳輸層安全標準 (TLS) 1.3 的安全性改善項目。Google 公用 DNS 目前 接受未提供 SNI 的 TLS 1.3 連線,但我們可能需要變更連線 這會造成未來的營運或安全性原因
以下是我們針對 SNI 所推薦的 DoT 或 DoH 應用程式:
- 傳送 dns.google 主機名稱做為 SNI 與 Google 公開伺服器的任何連線 DNS DoT 或 DoH 服務。
- 如果沒有主機名稱 (例如,在 這種情況下,最好在 SNI 中傳送 IP 位址,而不是 不要將這個欄位留空
- IPv6 位址應以
[2001:db8:1234::5678]
的括號形式顯示,且Host
標頭,但在 SNI 中不含括號。
DNS 回應截斷
雖然 Google 公用 DNS 通常不會截斷對 DoT 和 DoH 的回應 有兩種情況執行:
如果 Google 公用 DNS 無法從 取得完整且未經截斷的回應 權威名稱伺服器,就會在回應中設定 TC 標記。
若是 DNS 回應 (採用二進位 DNS 訊息格式) 超過 TCP DNS 訊息的 64 KiB 限制,Google 公用 DNS 可能會將 TC (截斷) 標記。
不過在這類情況下,用戶端不需要使用純 TCP 或任何其他傳輸方式,因為結果都是一樣的