在 HTTP 基础上实现 DNS 已翻译 100%

oschina 投递于 2016/09/30 15:59 (共 7 段, 翻译完成于 10-12)
阅读 5798
收藏 44
DNS
2
加载中

简介

UDP或TCP所发送的传统的DNS查询和响应是没有加密的。这就很容易被窃听和受到欺骗(包括基于DNS的互联网过滤)。从递归解析器到客户端的响应是最易遭受意外或被恶意更改的,而递归解析器和权威名称服务器之间的通信通常需要包含额外的保护。

目前,基于网络的应用程序必须使用浏览器扩展才能利用那些高级的DNS功能,比如DANEDNS-SD service discovery,,甚至可以查看IP地址以外的任何东西。依赖DNSSEC的功能扩展必须要自我验证,因为浏览器和操作系统可能不会(能)验证DNSSEC。

昌伟兄
翻译于 2016/09/30 23:59
1

为了解决这些问题,谷歌的公共DNS提供了一种通过加密的HTTPS进行连接的DNSSEC验证方法,这种方法使用的是一种Web友好的API,它不需要对浏览器或操作系统进行什么配置或安装什么扩展。在HTTPS基础上实现的DNS大大提高了客户和递归解析器之间的隐私和安全,并且DNSSEC还提供了一种端到端的认证DNS查找。
谷歌公共DNS提供的API可以在https://dns.google.com/resolve? 找到,同时还提供了一种用户友好的Web界面https://dns.google.com/query?。虽然后者在浏览器中可以显示结果,但相应的API并未实现;要注意不要混淆这两个网址。

昌伟兄
翻译于 2016/10/01 00:09
0

API规范

注意: API还是beta版本,还会有变化。要报告一个错误或请求一个新的功能,请访问submit an issue

所有的API调用都是HTTP GET请求。参数名称是不区分大小写的。在有重复参数的情况下,将使用第一个值。使用http: URLs进行API调用是被禁止的(403 Forbidden)。

支持的参数

name

字符串, 需要

唯一需要的参数。它的长度必须在1和 253之间(忽略一个可选的跟踪点,如果存在的话)。所有标签(由点分隔的名称部分)必须是1到63个字节长。API不支持escape字符或非ASCII字符,但它们并没有被明确地拒绝。国际化域名必须使用punycode格式(例如,"xn--qxam"而不是"ελ")。


昌伟兄
翻译于 2016/10/01 00:34
0

类型

字符串,默认:1

RR 类型可以被从1到65535的数字或者是一组规范的字符串(不敏感的字符,比如A或者aaaa)所代替。你可以使用255来进行‘ANY’的查询,但是你要知道这并不是使用A或者AAAA或者MX记录代替它去发送查询(报文)。主域名服务器不需要返回像这样的查询(报文)所有的记录;一些甚至不做出回应,其他的(像cloudflare.com)仅仅只返回HINFO。

检查禁用

布尔型,默认:false

检查禁用位。使用cd,cd=1,或者cd=true来使DNSSEC验证失效;使用cd=0,cd=false,或者不使用cd参数来使DNSSEC验证进行有效的验证。

火星撞地球的魔术师
翻译于 2016/10/04 17:01
0

edns_client_subnet

字符串, 默认值: 空

表示edns0-client-subnet 选项.格式是带子网掩码的IP地址。例如:1.2.3.4/24,2001:700:300::/48.

如果你出于隐私考虑使用基于HTTPS的DNS,而且不想要你的IP地址的任何一部分为了位置精度而发送到授权域名服务器,就让edns_client_subnet=0.0.0.0/0。谷歌公用DNS通常会发送粗略的网络信息(通常将你IPv4地址的最后一部分归零)

random_padding

字符串, 忽略

这项参数的值被忽略,例如: XmkMw~o_mgP2pf.gpw-Oi5dK.

API 客户端关注可能的利用HTTPS的报文大小的旁信道隐私攻击。GET请求可以利用这一点通过填充随机数据来让所有请求变成同样大小。要防止URL的误解析,需要将填充字符限制到未限制的URL字符:大写或小写字母,数字,连字符,句号,下划线和波浪号

T
翻译于 2016/10/05 19:35
0

JSON格式的DNS响应

下面是一个成功的响应 (这里添加的注释在实际的响应中不会出现):

{
  "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地址 / 掩码长度 
}

参见EDNS客户子网RFC draft 以了解更多有关“掩码长度”的细节以及它对缓存有何影响。

下面是提供了诊断信息的失败响应:

{
  "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/."
}
昌伟兄
翻译于 2016/10/07 00:30
1

内部引用SPF和TXT记录的域名服务器属性如下:

{
  "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的具体数据 - 多行引用字符串 
    }
  ],
}

"Master file" 中对RRs(TXT和SPF)类型格式要求双引号,并且需要避开JSON的双引号字符串。
单个字符串限制是255字节,而类似yahoo.com DKIM 的长TXT类型的记录包含多个字符串的情况需要每个字符串分开处理.
许多使用长TXT类型记录,例如RFC 4408 (SPF) 或 RFC 4871 (DKIM)格式要求将多个串联字符串按照一个TXT或者SPF记录对待,但是通常不会需要进行这个处理。

注意:尽管HTTP不截断,我们也可能得到一个从认证域名服务器返回的被截断的响应。所以我们需要在 响应中包含TC标志位。

注意:考虑到HTTP消息没有大小限制,我们通常不需要EDNS机制
唯一有意义的ENDS选项(即edns-client-subnet)是一个请求参数和JSON响应中的顶级属性。

温安适
翻译于 2016/10/12 10:13
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(21)

西安鲲之鹏
西安鲲之鹏

引用来自“西安鲲之鹏”的评论

还没想到有什么能应用的场景

引用来自“双城记”的评论

运营商拦截重定向之类的行为

引用来自“西安鲲之鹏”的评论

现在底层的库(例如 urllib2)都是基于传统UDP协议的DNS解析,要想使用这个(DNS-over-HTTPS)底层都需要修改。况且在墙内考虑都不用考虑。

引用来自“双城记”的评论

可以不需要从底层去考虑这个使用。 比如一个应用需要调用许多http://www.example.com域下的资源,为了防止www.example.com udp解析出问题,那我就先调用另外一个dns 解析的http api. http://123.123.123.123/resolveDNS?domain=www.example.com ,然后根据请求的实际情况返回可用的ip地址,客户端拿到域名与ip的映射以后,自己去做相关的处理(类似修改host)。

引用来自“西安鲲之鹏”的评论

底层不支持的话,这个就有点鸡肋了。 例如,如果是一个Web客户端应用(e.g. 爬虫),即便得知真实的域名真实的ip,也不能使用ip正常访问大部分网站(考虑主机域名绑定)。这跟修改hosts不同。 不过可以利用这个服务做一个防DNS污染的HOSTS修改器。

引用来自“灵魂架构师”的评论

你Socket连接解析的IP,在发送Http是把header里的HOST字段设置成域名即可,代理服务器都是这么做的。。。。我自己也用脚本实现简单的类似CDN的反代。
嗯,只能从socket级别完成http封包和交互了。没法直接用上层的http客户端(例如 urllib2)。
灵魂架构师
灵魂架构师

引用来自“西安鲲之鹏”的评论

还没想到有什么能应用的场景

引用来自“双城记”的评论

运营商拦截重定向之类的行为

引用来自“西安鲲之鹏”的评论

现在底层的库(例如 urllib2)都是基于传统UDP协议的DNS解析,要想使用这个(DNS-over-HTTPS)底层都需要修改。况且在墙内考虑都不用考虑。

引用来自“双城记”的评论

可以不需要从底层去考虑这个使用。 比如一个应用需要调用许多http://www.example.com域下的资源,为了防止www.example.com udp解析出问题,那我就先调用另外一个dns 解析的http api. http://123.123.123.123/resolveDNS?domain=www.example.com ,然后根据请求的实际情况返回可用的ip地址,客户端拿到域名与ip的映射以后,自己去做相关的处理(类似修改host)。

引用来自“西安鲲之鹏”的评论

底层不支持的话,这个就有点鸡肋了。 例如,如果是一个Web客户端应用(e.g. 爬虫),即便得知真实的域名真实的ip,也不能使用ip正常访问大部分网站(考虑主机域名绑定)。这跟修改hosts不同。 不过可以利用这个服务做一个防DNS污染的HOSTS修改器。
你Socket连接解析的IP,在发送Http是把header里的HOST字段设置成域名即可,代理服务器都是这么做的。。。。我自己也用脚本实现简单的类似CDN的反代。
554330833a
554330833a

引用来自“DuLerWeil”的评论

国内几家公共解析服务早先也已经提供这样的服务了

引用来自“554330833a”的评论

运营商是怎么update dns的记录的?,我们个人也可以修改吗?

引用来自“DuLerWeil”的评论

首先你得是某个域名的拥有者,然后到注册这个域名的服务商系统中,修改这域名的DNS为第三方的服务地址(比如阿里云、DNSPOD之类的。也可以不修改, 域名服务商一般有自己的DNS)。最后去第三方DNS系统中修改这个域名及其子域名的解析记录(A,CNAME、MX)等

引用来自“DuLerWeil”的评论

接下来等待全网DNS递归刷新,几秒钟到几天都有可能。
谢谢大神,我查了下应该是买了域名就有一个公网ip了是吧?然后通过配置dns解析到空间上的web文件,是这样的吗?
DuLerWeil
DuLerWeil

引用来自“DuLerWeil”的评论

国内几家公共解析服务早先也已经提供这样的服务了

引用来自“554330833a”的评论

运营商是怎么update dns的记录的?,我们个人也可以修改吗?

引用来自“DuLerWeil”的评论

首先你得是某个域名的拥有者,然后到注册这个域名的服务商系统中,修改这域名的DNS为第三方的服务地址(比如阿里云、DNSPOD之类的。也可以不修改, 域名服务商一般有自己的DNS)。最后去第三方DNS系统中修改这个域名及其子域名的解析记录(A,CNAME、MX)等
接下来等待全网DNS递归刷新,几秒钟到几天都有可能。
DuLerWeil
DuLerWeil

引用来自“DuLerWeil”的评论

国内几家公共解析服务早先也已经提供这样的服务了

引用来自“554330833a”的评论

运营商是怎么update dns的记录的?,我们个人也可以修改吗?
首先你得是某个域名的拥有者,然后到注册这个域名的服务商系统中,修改这域名的DNS为第三方的服务地址(比如阿里云、DNSPOD之类的。也可以不修改, 域名服务商一般有自己的DNS)。最后去第三方DNS系统中修改这个域名及其子域名的解析记录(A,CNAME、MX)等
IdleMan
IdleMan
都有DNSCrypt为什么还要基于http协议的dns
晒太阳的小猪
晒太阳的小猪

引用来自“ak_birdofprey”的评论

为什么会有人劫持域名!!!???

引用来自“西安鲲之鹏”的评论

e.g. 中间人攻击、防火墙(GFW拦截)
造反起家最怕别人造反。所以收缴各种武器。大宋皇帝就是这个样子的!!!
晒太阳的小猪
晒太阳的小猪

引用来自“ak_birdofprey”的评论

为什么会有人劫持域名!!!???

引用来自“西安鲲之鹏”的评论

e.g. 中间人攻击、防火墙(GFW拦截)
造反起家最怕别人造反。所以收缴各种武器。大宋皇帝就是这个样子的!!!
西安鲲之鹏
西安鲲之鹏

引用来自“西安鲲之鹏”的评论

还没想到有什么能应用的场景

引用来自“双城记”的评论

运营商拦截重定向之类的行为

引用来自“西安鲲之鹏”的评论

现在底层的库(例如 urllib2)都是基于传统UDP协议的DNS解析,要想使用这个(DNS-over-HTTPS)底层都需要修改。况且在墙内考虑都不用考虑。

引用来自“双城记”的评论

可以不需要从底层去考虑这个使用。 比如一个应用需要调用许多http://www.example.com域下的资源,为了防止www.example.com udp解析出问题,那我就先调用另外一个dns 解析的http api. http://123.123.123.123/resolveDNS?domain=www.example.com ,然后根据请求的实际情况返回可用的ip地址,客户端拿到域名与ip的映射以后,自己去做相关的处理(类似修改host)。
底层不支持的话,这个就有点鸡肋了。 例如,如果是一个Web客户端应用(e.g. 爬虫),即便得知真实的域名真实的ip,也不能使用ip正常访问大部分网站(考虑主机域名绑定)。这跟修改hosts不同。 不过可以利用这个服务做一个防DNS污染的HOSTS修改器。
西安鲲之鹏
西安鲲之鹏

引用来自“ak_birdofprey”的评论

为什么会有人劫持域名!!!???
e.g. 中间人攻击、防火墙(GFW拦截)
返回顶部
顶部