คำขอ DNS และการตอบกลับแบบดั้งเดิมจะส่งผ่าน UDP หรือ TCP โดยไม่มีการเข้ารหัส จึงขึ้นอยู่กับการสอดส่อง การปลอมแปลง และการกรองอินเทอร์เน็ตด้วย DNS การตอบกลับไคลเอ็นต์จากรีโซลเวอร์สาธารณะ เช่น Google Public DNS มีประโยชน์อย่างยิ่ง มีช่องโหว่ต่อเรื่องนี้ เนื่องจากข้อความอาจผ่านหลายเครือข่าย ขณะที่ข้อความ ระหว่างรีโซลเวอร์ซ้ำและเนมเซิร์ฟเวอร์ที่เชื่อถือได้มักจะรวม การป้องกันเพิ่มเติม
เพื่อแก้ไขปัญหาเหล่านี้ ในปี 2016 เราได้เปิดตัว DNS-over-HTTPS (ปัจจุบันเรียกว่า DoH) เสนอการแปลง DNS ในการตรวจสอบ DNSSEC ที่เข้ารหัสผ่าน HTTPS และ QUIC และในปี 2019 เราได้เพิ่มการรองรับสำหรับมาตรฐาน DNS ผ่าน TLS (DoT) ที่ คุณลักษณะ DNS ส่วนตัวของ Android
DoH และ DoT ปรับปรุงความเป็นส่วนตัวและความปลอดภัยระหว่างไคลเอ็นต์และรีโซลเวอร์ การเสริมการตรวจสอบ DNS สาธารณะของ Google สำหรับ DNSSEC เพื่อให้บริการแบบครบวงจร DNS ที่ผ่านการตรวจสอบสิทธิ์สำหรับโดเมนที่ลงนาม DNSSEC DNS สาธารณะของ Google มุ่งมั่นที่จะให้บริการแก้ปัญหา DNS ที่รวดเร็ว เป็นส่วนตัว และมีความปลอดภัยสำหรับทั้ง DoH และ ไคลเอ็นต์ DoT
เวอร์ชัน TLS และชุดการเข้ารหัสที่รองรับ
DNS สาธารณะของ Google รองรับ TLS 1.2 และ TLS 1.3 สำหรับทั้ง DoH และ DoT ไม่ใช่ก่อนหน้านี้ สนับสนุนเวอร์ชันของ TLS หรือ SSL เฉพาะชุดการเข้ารหัสที่มีการรักษาความปลอดภัยส่งต่อเท่านั้น และการเข้ารหัสที่ตรวจสอบสิทธิ์ด้วยข้อมูลเพิ่มเติม (AEAD) แล้ว Qualys SSL Labs จะแสดงชุดการเข้ารหัสปัจจุบันที่รองรับ
ปลายทาง
DNS สาธารณะของ Google ใช้ปลายทางต่อไปนี้สำหรับ 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 คือเพย์โหลด UDP DNS แบบไบนารีที่มีประเภทเนื้อหา application/dns-message. - คำขอนี้คือ
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
- Intra (แอป Android) – DoH
เว็บไซต์ dnsprivacy.org มีรายชื่อไคลเอ็นต์อื่นๆ อีกหลายรายสำหรับ DoT และ DoH แต่ ซึ่งมักจะต้องมีการกำหนดค่าทางเทคนิคพอสมควร
ตัวอย่างบรรทัดคำสั่ง
ตัวอย่างบรรทัดคำสั่งต่อไปนี้ไม่ได้มีไว้สำหรับใช้ในไคลเอ็นต์จริง และเป็นเพียงภาพประกอบโดยใช้เครื่องมือวินิจฉัยที่หาได้ทั่วไป
DoT
คำสั่งต่อไปนี้ต้องใช้ Knot DNS kdig
2.3.0 ขึ้นไป ที่มีรุ่น 2.7.4 หรือ
ในภายหลัง ให้ยกเลิกการเลือกช่องทำเครื่องหมาย +tls‑sni
เพื่อส่ง SNI ตามที่ TLS 1.3 กำหนด
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
สตริงที่เข้ารหัส Base64Url ในคำสั่งนี้คือข้อความ DNS ที่ส่งโดย
dig +noedns example.test A
พร้อมตั้งค่าช่องรหัส DNS เป็น 0 ตามที่แนะนำ
โดย RFC 8484 ส่วน 4.1 คำสั่ง Shell จะส่งคำขอ 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
สตริงที่เข้ารหัส Base64Url ในคำสั่งนี้คือข้อความ DNS ที่ส่งโดย
dig +noedns example.com A
พร้อมตั้งค่าช่องรหัส DNS เป็น 0 ในกรณีนี้
มีการส่งผ่านอย่างชัดเจนใน 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
การดำเนินการนี้ใช้ JSON API สำหรับ DoH
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":[]}
TLS 1.3 และ SNI สำหรับ URL ที่อยู่ IP
TLS 1.3 กำหนดให้ไคลเอ็นต์ ระบุ Server Name identifier หรือ SNI)
ส่วนขยาย SNI จะระบุว่าข้อมูล SNI เป็นโดเมน DNS (ไม่ใช่ที่อยู่ IP) ดังนี้
"HostName" มีชื่อโฮสต์ DNS แบบเต็มของเซิร์ฟเวอร์ ที่ลูกค้าเข้าใจ ชื่อโฮสต์แสดงเป็นสตริงไบต์ โดยใช้การเข้ารหัส ASCII โดยไม่มีจุดต่อท้าย วิธีนี้ทำให้สามารถรองรับ ชื่อโดเมนสากลโดยใช้ป้ายกำกับ A ที่กำหนดไว้ใน RFC5890 ชื่อโฮสต์ DNS ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ อัลกอริทึมสําหรับเปรียบเทียบ ชื่อโฮสต์มีอธิบายไว้ใน RFC5890, ส่วนที่ 2.3.2.4
ไม่อนุญาตให้ใช้ที่อยู่ IPv4 และ IPv6 ใน "HostName"
คุณอาจปฏิบัติตามข้อกำหนดเหล่านี้ได้ยากสำหรับแอปพลิเคชัน DoH หรือ DoT ที่ต้องการ ใช้ประโยชน์จากการปรับปรุงด้านความปลอดภัยใน TLS 1.3 DNS สาธารณะของ Google ในขณะนี้ ยอมรับการเชื่อมต่อ TLS 1.3 ที่ไม่มี SNI แต่เราอาจต้องเปลี่ยน ด้วยเหตุผลด้านการดำเนินงานหรือความปลอดภัยในอนาคต
คำแนะนำสำหรับแอปพลิเคชัน DoT หรือ DoH เกี่ยวกับ SNI มีดังนี้
- ส่งชื่อโฮสต์ dns.google เป็น SNI สำหรับการเชื่อมต่อกับ Google Public บริการ DNS DoT หรือ DoH
- หากไม่มีชื่อโฮสต์ที่พร้อมใช้งาน (ตัวอย่างเช่น ในแอปพลิเคชันที่กำลัง ฉวยโอกาส) การส่งที่อยู่ IP ใน SNI จะดีกว่า มากกว่าการปล่อยให้ว่างไว้
- ที่อยู่ IPv6 ควรปรากฏในรูปแบบวงเล็บเหลี่ยม
[2001:db8:1234::5678]
ใน ส่วนหัวHost
โดยไม่มีวงเล็บใน SNI
การตัดการตอบกลับ DNS
แม้ว่าโดยทั่วไป Google Public DNS จะไม่ตัดการตอบสนองต่อ DoT และ DoH การค้นหามี 2 กรณี ได้แก่
หาก DNS สาธารณะของ Google ไม่ได้รับการตอบสนองที่สมบูรณ์และถูกยกเลิกการตัดจาก ที่เชื่อถือได้ จึงมีการตั้งค่าสถานะ TC ในการตอบสนอง
ในกรณีที่การตอบกลับ DNS (ในรูปแบบข้อความ DNS แบบไบนารี) จะ เกินขีดจำกัด 64 KiB สำหรับข้อความ DNS DNS ของ Google Public DNS แจ้ง TC (การตัดข้อความ) หากมาตรฐาน RFC กำหนดให้ดำเนินการ
อย่างไรก็ตาม ในกรณีเหล่านี้ ไคลเอ็นต์ไม่จำเป็นต้องลองอีกครั้งโดยใช้ TCP แบบธรรมดา หรือการส่งอื่นๆ เนื่องจากผลลัพธ์จะเหมือนกัน