在 HTTP 基础上实现 DNS
Velva34Z
8年前
<h2><strong>简介</strong></h2> <p>UDP或TCP所发送的传统的DNS查询和响应是没有加密的。这就很容易被窃听和受到欺骗(包括基于DNS的互联网过滤)。从递归解析器到客户端的响应是最易遭受意外或被恶意更改的,而递归解析器和权威名称服务器之间的通信通常需要包含额外的保护。</p> <p>目前,基于网络的应用程序必须使用浏览器扩展才能利用那些高级的DNS功能,比如 DANE , DNS-SD service discovery , ,甚至可以查看IP地址以外的任何东西。依赖DNSSEC的功能扩展必须要自我验证,因为浏览器和操作系统可能不会(能)验证DNSSEC。</p> <p>为了解决这些问题,谷歌的公共DNS提供了一种通过 加密的HTTPS进行连接的 DNSSEC验证方法,这种方法使用的是一种Web友好的API,它不需要对浏览器或操作系统进行什么配置或安装什么扩展。在 HTTPS基础上实现的 DNS大大提高了客户和递归解析器之间的隐私和安全,并且 DNSSEC 还提供了一种端到端的认证DNS查找。</p> <p>谷歌公共DNS提供的API可以在 <a href="/misc/goto?guid=4959720607974868024" rel="nofollow,noindex">https://dns.google.com/resolve?</a> 找到,同时 还提供了一种用户友好的Web界面 <a href="/misc/goto?guid=4959720608068765447" rel="nofollow,noindex">https://dns.google.com/query?</a> 。虽然后者在浏览器中可以显示结果,但相应的API并未实现;要注意不要混淆这两个网址。</p> <h2><strong>API规范</strong></h2> <p>注意:API还是beta版本,还会有变化。要报告一个错误或请求一个新的功能。</p> <p>所有的API调用都是HTTP GET请求。参数名称是不区分大小写的。在有重复参数的情况下,将使用第一个值。使用http: URLs进行API调用是被禁止的(403 Forbidden)。</p> <h3><strong>支持的参数</strong></h3> <h3><strong>name</strong></h3> <p>字符串, 需要</p> <p>唯一需要的参数。它的长度必须在1和 <a href="/misc/goto?guid=4959720608155155349" rel="nofollow,noindex">253</a> 之间 (忽略一个可选的跟踪点,如果存在的话)。所有标签(由点分隔的名称部分)必须是1到63个字节长。API不支持 escape字符或非 ASCII字符,但它们并没有被明确地拒绝。国际化域名必须使用 punycode格式(例如, "xn--qxam"而不是"ελ" )。</p> <p><strong>类型</strong></p> <p>字符串,默认:1</p> <p>RR 类型可以被从1到65535的数字或者是一组规范的字符串(不敏感的字符,比如A或者aaaa)所代替。你可以使用255来进行‘ANY’的查询,但是你要知道这并不是使用A或者AAAA或者MX记录代替它去发送查询( 报文 )。主域名服务器不需要返回像这样的查询( 报文 )所有的记录;一些甚至不做出回应,其他的(像 cloudflare.com )仅仅只返回HINFO。</p> <p>检查禁用</p> <p>布尔型,默认:false</p> <p>检查禁用位。使用cd,cd=1,或者cd=true来使DNSSEC验证失效;使用cd=0,cd=false,或者不使用cd参数来使DNSSEC验证进行有效的验证。</p> <p><strong>edns_client_subnet</strong></p> <p>字符串, 默认值: 空</p> <p>表示edns0-client-subnet 选项.格式是带子网掩码的IP地址。例如: 1.2.3.4/24,2001:700:300::/48.</p> <p>如果你出于隐私考虑使用基于HTTPS的DNS,而且不想要你的IP地址的任何一部分为了位置精度而发送到授权域名服务器,就让 edns_client_subnet=0.0.0.0/0。谷歌公用DNS通常会发送粗略的网络信息(通常将你IPv4地址的最后一部分归零) 。</p> <p><strong>random_padding</strong></p> <p>字符串, 忽略</p> <p>这项参数的值被忽略,例如: XmkMw~o_mgP2pf.gpw-Oi5dK.</p> <p>API 客户端关注可能的利用HTTPS的报文大小的旁信道隐私攻击。GET请求可以利用这一点通过填充随机数据来让所有请求变成同样大小。要防止URL的误解析,需要将填充字符限制到未限制的URL字符:大写或小写字母,数字,连字符,句号,下划线和波浪号 。</p> <h3><strong>JSON格式的DNS响应</strong></h3> <p>下面是一个成功的响应 (这里添加的注释在实际的响应中不会出现):</p> <pre> { "Status": 0, // 没有错误(NOERROR) - 标准的DNS响应代码(32位整数). "TC": false, // 响应是否有删减 "RD": true, // 对于Google公共DNS来说,总为真 "RA": true, // 对于Google公共DNS来说,总为真 "AD": false, // 是否需要用DNSSEC验证所有的响应数据 "CD": false, // 是否要求客户端禁止使用DNSSEC "Question": [ { "name": "apple.com.", // 结尾带有一个点的完全限定域名(FQDN) "type": 1 // A - 标准的DNS RR类型 } ], "Answer": [ { "name": "apple.com.", // 总是和Question部分中的name相同 "type": 1, // A - 标准的DNS RR类型 "TTL": 3599, // 记录的生命周期秒数 "data": "17.178.96.59" // A的数据 - IP地址 }, { "name": "apple.com.", "type": 1, "TTL": 3599, "data": "17.172.224.47" }, { "name": "apple.com.", "type": 1, "TTL": 3599, "data": "17.142.160.59" } ], "Additional": [ ], "edns_client_subnet": "12.34.56.78/0" // IP地址 / 掩码长度 }</pre> <p>参见EDNS客户子网 <a href="/misc/goto?guid=4959720608235203437" rel="nofollow,noindex">RFC draft</a> 以了解更多有关“掩码长度”的细节以及它对缓存有何影响。</p> <p>下面是提供了诊断信息的失败响应:</p> <pre> { "Status": 2, // 服务失败(SERVFAIL) - 标准的DNS响应代码(32位整数). "TC": false, // 响应是否有删减 "RD": true, // 对于Google公共DNS来说,总为真 "RA": true, // 对于Google公共DNS来说,总为真 "AD": false, // 是否需要DNSSEC验证所有的响应数据 "CD": false, // 是否要求客户端禁止使用DNSSEC "Question": [ { "name": "dnssec-failed.org.", // 结尾带有一个点的完全限定域名(FQDN) "type": 1 // A - 标准的DNS RR类型 } ], "Comment": "DNSSEC validation failure. Please check http://dnsviz.net/d/dnssec-failed.org/dnssec/." }</pre> <p>内部引用SPF和TXT记录的域名服务器属性如下:</p> <pre> { "Status": 0, // 无错误 - 标准DNS响应码(32位整数) "TC": false, // 响应是否有删减 "RD": true, // 对于Google公共DNS来说,总为真 "RA": true, // 对于Google公共DNS来说,总为真 "AD": false, // 是否需要DNSSEC验证所有的响应数据 "CD": false, // 是否要求客户端禁止使用DNSSEC "Question": [ { "name": "*.dns-example.info.", // 结尾带有一个完全限定域名(FQDN) "type": 99 // SPF - 标准 DNS RR 类型 } ], "Answer": [ { "name": "*.dns-example.info.", //总是Question的机器名 "type": 99, // SPF - 标准 DNS RR 类型 "TTL": 21599, // 记录的生命周期秒数 "data": "\"v=spf1 -all\"" // SPF的具体数据 - 引用的字符串 } ], "Comment": "Response from 216.239.38.110" //由认证域名服务器返回的无缓存响应 } { "Status": 0, // 无错误 - 标准DNS响应码(32位整数) "TC": false, // 响应是否有删减 "RD": true, //对于Google公共DNS来说,总为真 "RA": true, // 对于Google公共DNS来说,总为真 "AD": false, // 是否需要DNSSEC验证所有的响应数据 "CD": false, // 是否要求客户端禁止使用DNSSEC "Question": [ { "name": "s1024._domainkey.yahoo.com.", // 结尾带有一个完全限定域名(FQDN) "type": 16 // TXT - 标准 DNS RR 类型 } ], "Answer": [ { "name": "s1024._domainkey.yahoo.com.", // 总是Question的机器名 "type": 16, // TXT - 标准 DNS RR 类型 "data": "\"k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfm\"\"JiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB; n=A 1024 bit key;\"" //TXT的具体数据 - 多行引用字符串 } ], }</pre> <p>"Master file" 中对RRs(TXT和SPF)类型格式要求双引号,并且需要避开JSON的双引号字符串。</p> <p>单个字符串限制是255字节,而类似yahoo.com DKIM 的长TXT类型的记录包含多个字符串的情况需要每个字符串分开处理.</p> <p>许多使用长TXT类型记录,例如RFC 4408 (SPF) 或 RFC 4871 (DKIM)格式要求将多个串联字符串按照一个TXT或者SPF记录对待,但是通常不会需要进行这个处理。</p> <p>注意:尽管HTTP不截断,我们也可能得到一个从认证域名服务器返回的被截断的响应。所以我们需要在 响应中包含TC标志位。</p> <p>注意:考虑到HTTP消息没有大小限制,我们通常不需要EDNS机制</p> <p>唯一有意义的ENDS选项(即edns-client-subnet)是一个请求参数和JSON响应中的顶级属性。</p> <p> </p> <p>来自:https://www.oschina.net/translate/dns-over-https</p> <p> </p>