DNS 在代理中的解析行为

不使用代理情况下的 DNS 解析流程

浏览器和操作系统都有DNS缓存机制

  1. 浏览器从自身的 DNS 缓存机制寻找解析成果
  2. 解析失败,则通过系统的 getaddrinfo 方法向操作系统寻找解析成果
  3. 系统解析失败,则会根据系统设置的 DNS 地址向DNS服务器请求解析结果

设置代理并直连

场景:浏览器设置了 SOCKS5 代理,但没有远端服务器存在,此时浏览器不再需要从自己的 DNS 缓存中寻找 IP

  1. 浏览器直接将域名封装在 SOCKS5 协议中发往代理客户端
  2. 代理客户端从 SOCKS 流量中抽出域名,并设法解析。此时,代理客户端即可以使用系统的 getaddrinfo 方法,也可以使用自己实现的DNS解析方法

设置代理并将流量转发到远端服务器

场景:在上一步的基础上,代理会使用某种协议与远端服务器通信

  1. 浏览器直接将域名封装在 SOCKS5 协议中发往代理客户端
  2. 代理客户端从 SOCKS 流量中抽出域名
  3. 代理客户端使用某种协议将浏览器的 SOCKS 流量重组并发往远端服务器
  4. 远端服务器使用相同的某种协议解析并获得域名
  5. 远端服务器发起 DNS 解析请求解析域名(一般情况下使用系统的 DNS 解析方法)

该场景下,浏览器和代理客户端都没有进行 DNS 解析,而是由远端服务器进行解析。

设置代理并使用 IP 规则进行分流

  1. 浏览器将带有域名的 HTTPS 请求封装在 SOCKS5 流量之中发往代理客户端
  2. 代理客户端从 SOCKS 流量中抽出域名并进行 DNS 解析
  3. 代理客户端根据域名解析结果和 IP 规则,决定解析的 IP 是否需要走代理
  4. 如果不许要走代理,则执行 设置代理并直连 的剩余操作
  5. 如果需要走代理,则进行 设置代理并将流量转发到远端服务器 的剩余操作

使⽤ IP 规则分流,前提⾸先你得有⼀个 IP 拿来⽐较,所以代理客户端必须先进⾏⼀次 DNS 解析

只有在直连时,代理客户端才基本会复用这个 IP ;如果将流量交给远端服务器,那么远端服务器拿到的还是域名而不是 IP ,还需要再进行一次 DNS 解析。即 远端服务器连接的 IP 与代理客户端解析得到的 IP 毫⽆关系

设置代理并使用域名规则进行分流

  1. 浏览器将带有域名的 HTTPS 请求封装在 SOCKS5 流量之中发往代理客户端
  2. 代理客户端从 SOCKS 流量中抽出域名
  3. 代理客户端将域名与规则列表开始比较,决定是否需要走代理
  4. 如果不需要走代理,则执行 设置代理并直连 的剩余操作
  5. 如果需要走代理,则进行 设置代理并将流量转发到远端服务器 的剩余操作

除非域名命中直连规则,否则代理客户端无需进行 DNS 解析

使用 redir/tun2socks 实现全局流量经过代理

场景:对于不⽀持设置 SOCKS/HTTP(S) 代理的软件,Surge/Clash 等软件⼀般选择通过 TUN/TAP 或转发 redir 透明⽹关接管⽹络请求,从⽽拿到原始的 TCP/IP 连接。⽤户不再主动为每个应⽤程序设置代理。此时应⽤程序是不会感知到代理客户端的存在,它们会正常的发起 TCP 连接。由于 TCP/IP 协议,在拿到 DNS 解析结果之前,连接是不能建⽴的

  • redir : 一个简单的 TCP 端口重定向工具。它可以将网络流量从一个端口重定向到另一个端口或 IP 地址

  • tun2socks :可以将 TUN 接口上的 IP 流量转发到 SOCKS5 代理服务器上

  • TUN (网络隧道)接口:模拟一个三层(网络层)设备,即一个网络接口卡(NIC),它处理的是 IP 数据包。它的工作方式类似于一个虚拟的点对点设备,通常用于创建虚拟点对点连接

  • TAP (网络 tap)接口:模拟一个二层(数据链路层)设备,即一个以太网设备,它处理的是以太网帧。TAP 接口工作方式类似于一个虚拟交换机端口,用于创建虚拟局域网

  1. 浏览器从自身的 DNS 缓存机制寻找解析成果
  2. 解析失败,则通过系统的 getaddrinfo 方法向操作系统寻找解析成果。在系统的⽹络设置之中有设置上游 DNS 地址。代理客户端可能会修改系统设置中的 DNS 到 127.0.0.1 或者别的 IP ,也可能保留⽤户之前的设置。但不论如何,这个设置最终会使操作系统向代理客户端发起 DNS 请求
  3. 操作系统发出的 DNS 解析请求经过代理客户端并最终被截获
  4. 代理客户端可以将这个DNS解析请求原样发出去者使用⾃⼰实现的DNS解析方法,最终得到一个解析结果
  5. 代理客户端返回解析结果,操作系统将这个解析结果返回给浏览器
  6. 浏览器对这个解析结果的 IP 建⽴⼀个 TCP 连接并发送
  7. 这个 TCP 连接被代理客户端截获。由于之前代理客户端进⾏的 DNS 解析请求这⼀动作,代理客户端可以找到这个 IP 的 原来的⽬标域名
  8. 如果是⽀持 redir 的代理客户端,那么代理客户端就会直接将域名和 TCP 连接中的其它数
    据封装成某种协议发给远端服务器;或者封装成 SOCKS5 后交给⽀持 SOCKS5 的代理
    客户端

在设置透明代理的情况下,浏览器无需将流量封装成SOCKS5,而是正常地发起 TCP 连接

浏览器设置 SOCKS5 代理的话,可以不在代理客户端发起 DNS 解析请求就能将流量发送给远端服务器;⽽在透明代理模式下,不论是否需要 IP 规则分流都需要先进⾏⼀次 DNS 解析才能建⽴连接

TUN/TAP 接管DNS解析带来的问题

  • DNS 污染:由于特殊的⽹络环境,通过你本机直接进⾏ DNS 解析得到的结果可能不可靠
  • CDN 优化:如果要访问的⽬标⽹站使⽤了CDN,但却在本机进行DNS解析,则得到的IP可能并不是距离你的远端服务器最近的CDN节点
  • 如果软件决定将域名转发给远端代理服务器,那么本机解析的IP地址没有任何作用,造成了额外的一次解析时间

在 redir/tun2socks 中使用 Fake IP

使用 Fake IP,代理客户端可以省掉一次DNS解析。其原理是代理客户端先不执行查询动作,而是丢一个 Fake IP 给浏览器,让其可以立刻建立连接

  1. 浏览器从自身的 DNS 缓存机制寻找解析成果
  2. 解析失败,则通过系统的 getaddrinfo 方法向操作系统寻找解析成果
  3. 在系统的⽹络设置之中有设置上游 DNS 地址。代理客户端可能会修改系统设置中的 DNS 到 127.0.0.1 或者别的 IP ,也可能保留⽤户之前的设置。不论如何,这个设置最终会使操作系统向代理客户端发起 DNS 请求
  4. 操作系统发出的 DNS 解析请求会经过代理客户端并最终被截获
  5. 代理客户端从解析请求中获得域名,从 Fake IP 池中选取⼀个 IP 建⽴映射
  6. 代理客户端返回 Fake IP ,操作系统拿到了这个 Fake IP 并返回给浏览器
  7. 浏览器以 Fake IP 为⽬标发起⽹络请求
  8. 该 TCP 连接被代理客户端截获。代理客户端抽取出 Fake IP 并反查出这个 TCP 连接中对应的域名
  9. 有了 TCP 连接和域名,代理客户端可以轻易地将其使⽤ SOSCKS5 或者 某种协议 进⾏封装

使用 Fake IP 后本机仍会进行DNS解析的情形

  • 遇到了按照 IP 进⾏分流的规则时,代理客户端才需要进⾏⼀次解析拿到⼀个 IP ⽤于匹配分流
  • 目标域名命中直连策略,此时代理客户端需要得到真实的目标IP

参考

[1]. 浅谈在代理环境中的 DNS 解析行为

[2]. 简析代理客户端导致的远端服务器流媒体 DNS 解锁失效的可能原因

[3]. 我有特别的DNS配置和使用技巧