התשובות והשאילתות המסורתיות ב-DNS נשלחות באמצעות UDP או TCP ללא הצפנה, ולכן הן חשופות למעקב, לזיוף ולסינון אינטרנט המבוסס על DNS. תגובות ללקוחות ממקודדים ציבוריים, כמו Google Public DNS, פגיעות במיוחד: ההודעות עשויות לעבור ברשתות רבות, בעוד שהודעות בין מקודדים רקורסיביים לבין שרתי שמות מהימנים כוללות בדרך כלל הגנות נוספות.
כדי לפתור את הבעיות האלה, בשנת 2016 השקנו את DNS באמצעות HTTPS (שנקרא עכשיו DoH), עם רזולוציית DNS מוצפנת לאימות DNSSEC ב-HTTPS וב-QUIC. וב-2019 הוספנו תמיכה בתקן DNS over TLS (DoT) שמשמש את הפיצ'ר שרת DNS פרטי ב-Android.
ה-DoH ו-DoT משפרות את הפרטיות והאבטחה בין הלקוחות והמקודדים, וכך הן משלימים את אימות ה-DNSSEC של ה-DNS הציבורי של Google, וכך מספקות DNS מאומת מקצה לקצה לדומיינים שנחתמו באמצעות DNSSEC. עם Google Public DNS, אנחנו מחויבים לספק פענוח DNS מהיר, פרטי ומאובטח גם ללקוחות DoH וגם ללקוחות DoT.
גרסאות TLS נתמכות וחבילות קריפטו
ב-DNS הציבורי של Google יש תמיכה ב-TLS 1.2 וב-TLS 1.3 גם ל-DoH וגם ל-DoT, אין תמיכה בגרסאות קודמות של TLS (אבטחת שכבת התעבורה) או SSL. יש תמיכה רק בסט אלגוריתמים להצפנה (cipher suite) עם אבטחת העברה והצפנה מאומתת עם נתונים נוספים (AEAD). ב-Qualys SSL Labs מוצגת הקבוצה הנוכחית של חבילות הצפנה הנתמכות.
נקודות קצה
ב-Google Public DNS נעשה שימוש בנקודות הקצה הבאות עבור DoH ו-DoT:
DoT (יציאה 853) dns.google
תבניות URI של DoH (יציאה 443)
RFC 8484 –
https://dns.google/dns-query{?dns}
- כשמשתמשים ב-POST, כתובת ה-URL היא רק
https://dns.google/dns-query
והגוף של בקשת ה-HTTP הוא המטען הייעודי (payload) הבינארי של ה-UDP מסוג DNS עם סוג התוכן application/dns-message. - עבור GET, הערך הוא
https://dns.google/dns-query?dns=
BASE64URL_OF_QUERY.
- כשמשתמשים ב-POST, כתובת ה-URL היא רק
API מסוג JSON –
https://dns.google/resolve{?name}{&type,cd,do,…}
- בדף JSON API מתוארים פרמטרים נוספים של GET.
רק הפרמטר
name
נדרש.
- בדף JSON API מתוארים פרמטרים נוספים של GET.
רק הפרמטר
לקוחות
יש כמה אפליקציות לקוח שמשתמשות ב-DoT או ב-DoH
- תכונת הגלישה הפרטית ב-Android 9 (Pie) – נקודה
- 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 POST
המחרוזת המקודדת ב-Base64Url בפקודה הזו היא הודעת ה-DNS שנשלחה על ידי dig +noedns example.test A
, כאשר שדה מזהה ה-DNS מוגדר לאפס, לפי ההמלצה של 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 בפקודה הזו היא הודעת ה-DNS שנשלחה על ידי 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
נעשה שימוש ב-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, הלקוחות נדרשים לספק זיהוי של שם השרת (SNI).
סיומת SNI מציינת שפרטי SNI הם דומיין DNS (ולא כתובת IP):
'HostName' מכיל את שם המארח המלא של ה-DNS של השרת, כפי שהלקוח מבין. שם המארח מיוצג כמחרוזת בייטים באמצעות קידוד ASCII ללא נקודה בסוף. כך אפשר לתמוך בשמות דומיינים בינלאומיים באמצעות תוויות A שמוגדרות ב-RFC5890. שמות מארחים של DNS אינם תלויי-רישיות. האלגוריתם להשוואת שמות מארחים מתואר ב-RFC5890, סעיף 2.3.2.4.
לא ניתן להשתמש בכתובות IPv4 ו-IPv6 ליטרליות ב-"HostName".
קשה לעמוד בדרישות האלה לאפליקציות DoH או DoT שרוצות לנצל שיפורי אבטחה ב-TLS 1.3. כרגע, אפשר להשתמש ב-Google Public DNS באמצעות חיבורי TLS 1.3 שלא מספקים SNI, אבל יכול להיות שנצטרך לשנות את ההגדרה הזו בעתיד מטעמי תפעול או אבטחה.
אלו ההמלצות שלנו לגבי אפליקציות DoT או DoH שקשורות ל-SNI:
- צריך לשלוח את שם המארח של dns.google כ-SNI לכל החיבורים לשירותי Google Public DNS DoT או DoH.
- אם אין שם מארח זמין (לדוגמה, באפליקציה שמבצעת DoT יחסי), עדיף לשלוח את כתובת ה-IP ב-SNI ולא להשאיר אותה ריקה.
- כתובות IPv6 צריכות להופיע בצורת סוגריים מסוג
[2001:db8:1234::5678]
בכותרתHost
, אבל בלי סוגריים ב-SNI.
קיצור של תגובת DNS
על אף ש-Google Public DNS בדרך כלל לא מקצר את התשובות לשאילתות DoT ו-DoH, יש שתי נסיבות שבהן הוא כן:
אם ל-DNS הציבורי של Google אין אפשרות לקבל תגובות מלאות ולא קטועות משרתי שמות מוסמכים, הוא מגדיר את דגל השקיפות וההסכמה בתגובה.
במקרים שבהם תגובת ה-DNS (בטופס של הודעת DNS בינארית) תחרוג ממגבלת 64 KiB להודעות DNS מסוג TCP, ייתכן ש-Google Public DNS יגדיר את הסימון 'TC (חיתוך)' אם תקני RFC נדרשים לעשות זאת.
עם זאת, במקרים כאלה הלקוחות לא צריכים לנסות שוב להשתמש ב-TCP פשוט או בכל העברה אחרת, כי התוצאה תהיה זהה.