DNS 劫持是一种网络攻击手段,攻击者通过篡改域名系统(DNS)解析过程,将用户请求的域名重定向到恶意网站或其他不正确的地址。这种攻击可以用于多种目的,例如窃取用户数据、传播恶意软件或进行钓鱼攻击。
举个例子
假设你想访问一个银行的官方网站,输入了银行的域名(例如 www.bank.com
)并按下回车键。正常情况下,DNS 服务器会将这个域名解析为银行服务器的 IP 地址,然后你的浏览器就会连接到正确的银行网站。
然而,在 DNS 劫持的情况下,攻击者可能会在 DNS 解析过程中做手脚:
-
篡改 DNS 服务器:攻击者可能入侵并控制一个 DNS 服务器,将
www.bank.com
的解析记录改为他们控制的恶意服务器的 IP 地址。 -
中间人攻击:在用户和 DNS 服务器之间的通信过程中,攻击者拦截并修改 DNS 响应,将域名解析到错误的地址。
-
家庭路由器劫持:攻击者可能通过恶意软件或漏洞攻击用户的家庭路由器,修改其 DNS 设置,使所有连接到该路由器的设备都被重定向。
结果
当你在这种情况下试图访问银行网站时,你可能会被引导到一个看似合法但实际上是由攻击者控制的钓鱼网站。该网站可能会试图窃取你的登录凭证或其他敏感信息。
HTTPDNS 是一种通过 HTTP 协议进行域名解析的技术,与传统的基于 UDP 的 DNS 查询方式不同。它的主要目的是绕过传统 DNS 的一些限制和问题,如 DNS 劫持和缓存污染。
HTTPDNS 的工作原理
-
HTTP 协议:HTTPDNS 使用 HTTP 协议向一个专门的 HTTPDNS 服务器发送域名解析请求,而不是通过传统 DNS 协议的 UDP 或 TCP 发送请求。
-
解析过程:客户端向 HTTPDNS 服务器发送一个 HTTP 请求,服务器返回解析后的 IP 地址。这一过程通常通过 HTTPS 进行,以确保传输的安全性。
-
绕过本地 DNS:由于是通过 HTTP 进行解析,HTTPDNS 可以绕过本地 ISP 的 DNS 服务器,避免本地 DNS 劫持和缓存污染。
HTTPDNS 的优点
- 防止 DNS 劫持:由于请求是通过 HTTP/HTTPS 发送的,可以有效避免本地 DNS 劫持。
- 准确性:可以提供更准确的解析结果,因为解析请求直接发送到权威 DNS 服务器或专门的 HTTPDNS 服务。
- 防止缓存污染:由于直接从权威服务器获取解析结果,减少了缓存污染的风险。
HTTPDNS 的缺点
- 延迟:由于使用 HTTP 协议,可能会增加一定的网络延迟,尤其是在使用 HTTPS 时。
- 依赖性:需要依赖一个可靠的 HTTPDNS 服务提供商,增加了对第三方服务的依赖。
- 复杂性:实现和管理比传统 DNS 更复杂,尤其是在大规模应用中。
-
域名验证问题:在 HTTPS 连接中,客户端会验证服务器的证书,以确保其与请求的域名匹配。这是通过检查证书中的域名(通常是 CN 或 SAN 字段)是否与用户请求的域名一致来实现的。如果使用 HTTPDNS 返回的 IP 地址进行连接,而不是原始域名,可能导致域名与证书不匹配,从而导致 SSL/TLS 握手失败。
假设你有一个移动应用程序,需要访问一个 HTTPS 网站,比如 https://example.com
。为了避免 DNS 污染,你决定使用 HTTPDNS 来解析域名。
场景描述:
-
HTTPDNS 请求:应用程序向 HTTPDNS 服务发送请求,解析
example.com
,得到一个 IP 地址,比如203.0.113.10
。 -
直接使用 IP 地址的问题:如果你直接使用这个 IP 地址来建立 HTTPS 连接,浏览器或应用程序会尝试验证证书。由于证书是为
example.com
签发的,而不是203.0.113.10
,这会导致证书验证失败,进而导致 SSL/TLS 握手失败。
解决方案:
-
使用 SNI:
在建立 TLS 连接时,通过 SNI 机制向服务器发送原始的域名example.com
。这可以帮助服务器返回正确的证书。例如,在使用某些编程语言的 HTTP 客户端库时,可以设置 SNI 选项(大多数现代库默认支持 SNI)。 -
保持域名:
在应用层次上,继续使用原始域名example.com
进行请求,而不是直接使用 IP 地址。这意味着在 HTTP 请求的 Host 头中仍然设置为example.com
,以确保服务器能够正确识别请求的目标。
在直播场景中,为了解决传统localDNS调度不精确,容易被劫持等缺点,近年业界起兴起了另一种方案httpDNS。其原理是APP通过HTTP协议直接调用CDN提供的httpsDNS API,获取一组合适的边缘节点IP。这两种方案互有优劣:
- 1.localDNS的优势在于运营商的DNS Server数量较少,对CDN GSLB来说,定位运营商的DNS Server的信息比较容易,虽然粒度比较粗,但大致区域运营商判断还是准确的。
- 2.传统的localDNS解析方式依赖于系统的DNS解析机制,系统一般都有内部缓存导致解析时间不可控,httpDNS方案直接绕开系统DNS解析机制,可以在用户观看直播前就提前解析好节点ip,在真正开播的时候能完全省掉DNS解析时间。当然,localDNS也可以通过自己调用底层解析接口的方式实现域名预解析。
- 3. httpDNS的方案是由APP直接调用CDN的API,请求没有经过运营商中转,可以绕过DNS劫持设备,因此能够有效的防止运营商劫持域名。
- 4. APP直接调用CDN的httpDNS API还有一个好处是CDN能直接获取到APP的出口ip,节点的分配可以做到更加准确合理。问题是在多出口小运营商的情况下,去CDN httpDNS服务器的出口很可能是从电信联通租用的线路,容易误判,而localDNS由于是运营商地区粒度的,反而更容易判断出用户所属运营商。
为什么HTTPDNS能避免DNS劫持?
- 避开本地DNS服务器
- 传统DNS请求(53端口,UDP/TCP)容易被运营商或网络设备拦截/篡改。
- HTTPDNS是通过HTTP/HTTPS(80/443端口)发往远程权威服务器,普通网络设备不会动HTTP/HTTPS流量,且运营商通常不会劫持80/443端口的HTTP/HTTPS数据包。
- HTTPS加密可防中间人篡改
- 若用HTTPS协议(即加密HTTPDNS),中间人无法篡改和伪造响应,更加安全可靠。
- 全程走应用层API
- HTTPDNS请求可以直接到达第三方云服务,有效绕过本地网络的DNS污染和劫持风险。
总结:HTTPDNS能避免DNS劫持,是因为它绕过了本地DNS服务器,直接用HTTP/HTTPS从权威服务器获取解析结果,且HTTPS加密可以防止中间人篡改。
补充:
传统的DNS解析(业界统称localDNS方案)的过程很简单。整个过程如下图,APP向所在网络运营商的DNS Server发起域名解析的请求,而运营商DNS Server会向CDN的GSLB系统发起递归查询,GSLB通过运营DNS Server所属IP地址判断查询来自于哪个运营商和地理位置,然后返回若干合适的CDN边缘节点IP给它。
这个过程中,APP和CDN之间隔了运营商DNS Server这一层,CDN在分配节点的时候其实没有办法获取任何APP的信息。为了解决传统localDNS调度不精确,容易被劫持等缺点,近年业界起兴起了另一种方案httpDNS。其原理是APP通过HTTP协议直接调用CDN提供的httpsDNS API,获取一组合适的边缘节点IP。
假设你有一个移动应用程序,需要访问一个 HTTPS 网站,比如 https://example.com。为了避免 DNS 污染,你决定使用 HTTPDNS 来解析域名。
场景描述:
HTTPDNS 请求:应用程序向 HTTPDNS 服务发送请求,解析 example.com,得到一个 IP 地址,比如 203.0.113.10。直接使用 IP 地址的问题:如果你直接使用这个 IP 地址来建立 HTTPS 连接,浏览器或应用程序会尝试验证证书。由于证书是为 example.com 签发的,而不是 203.0.113.10,这会导致证书验证失败,进而导致 SSL/TLS 握手失败。 如果使用localdns,不也是用dns解析得到的ip建联吗?为什么使用localdns就不会有httpdns的这个问题了
这个问题的关键在于“SNI”和“Host”字段的使用方式,以及客户端发起 HTTPS 请求时的“目标地址”和“目标主机名”的区别”。
1. local DNS 的正常流程
- 当你用 local DNS 解析 `example.com` 时,得到 IP 比如 `203.0.113.10`。
- 浏览器或 App 在建立连接时,依然是**以“域名”方式发起 HTTPS 请求**:
- 例如:`https://example.com`
- 在和服务器握手时,客户端会在 TLS 握手阶段通过SNI(Server Name Indication)扩展,告诉服务器“我需要访问 example.com”。
- 同时,客户端会校验证书上写的域名和你请求的域名是否一致(这里都是 `example.com`)。
- 总结:虽然底层 TCP 连接是用 IP 建立的,但上层 TLS 和 HTTP 请求依然以“域名”为主,证书校验和 SNI 都是用的域名。
2. HTTPDNS 场景下直接用 IP 发起连接的问题
- 你用 HTTPDNS 解析出 IP,比如 `203.0.113.10`。
- 如果你的应用直接用 IP 建立连接(如 `https://203.0.113.10`),
- **SNI 字段会变成 `203.0.113.10`**(除非你手动设置)。
- 证书校验也会用 IP 来校验——但服务器的证书是为 `example.com` 签发的,不是为 IP。
- 结果:证书校验失败,TLS 握手失败。
3. **区别的本质
- local DNS 模式:
- 用户/应用始终请求 `https://example.com`
- DNS 只是把域名解析成 IP,连接建立后,SNI、证书校验都是以域名为准
- 所以不会有证书校验问题
- HTTPDNS “错误”用法:
- 如果你把 `https://example.com` 换成 `https://203.0.113.10`,浏览器/应用会以 IP 为“主机名”发起连接
- SNI、Host 头、证书校验都用 IP,当然和服务器证书不匹配
4. 如何正确用 HTTPDNS?
- 正确做法:
- 用 HTTPDNS 拿到 IP
- 用 IP 建立 TCP 连接
- 但Host 头和 SNI 依然设置为 `example.com`
- 这样服务器会返回 example.com 的证书,证书校验就能通过
5. 举例说明
- local DNS 场景:
用户请求:https://example.com
DNS 解析:203.0.113.10
TCP 连接:203.0.113.10:443
SNI/Host/证书校验:example.com
- HTTPDNS 错误用法:
用户请求:https://203.0.113.10
SNI/Host/证书校验:203.0.113.10
服务器证书:example.com -> 校验失败
- HTTPDNS 正确用法(需要特殊设置):
TCP 连接 IP:203.0.113.10:443
SNI/Host/证书校验:example.com
总结
- local DNS:你虽然用 IP 建立连接,但上层始终用域名,证书校验不会出错。
- HTTPDNS:如果直接用 IP 发起 HTTPS,SNI/Host/证书校验都会用 IP,会失败。
- 正确姿势:用 IP 连接,但 SNI/Host 依然指向域名(需要代码或客户端支持)。
建议通过httpdns获取到ip后,不论是发起http请求还是https请求,都将host(https的话还需要设置sni)设为对应的域名。