DNS 透明代理(转载)

最近在研究 V2Ray 在各个端的使用,在配置 json 文件中的 DNS 部分时,想搞清楚具体的实现细节,便找到了这篇文章:

漫谈各种黑科技式 DNS 技术在代理环境中的应用

看完后觉得写得很好,但是还是需要整理正自己的比较,所以做个简单的记录。

1. DNS 解析过程

  1. 浏览器输入域名 www.aaaa.com
  2. 浏览器查找本地的 hosts 文件,如果找到则使用对应的 ip 进行通信,DNS 解析结束。
  3. hosts文件没有,那么浏览器向系统配置的 114.114.114.114(当前配置) 发起请求。
  4. 114.114.114.114 收到 DNS 解析的 UDP 请求,解析出域名。
  5. 114.114.114.114 查找自己的缓存,如果没找到就向其他的 DNS 服务器发起请求拿到结果后返回。
  6. 浏览器接收到 114.114.114.114 返回的结果 IP
  7. 浏览器跟结果 IP 创建 tcp 连接,发送数据。

2. SOCKS 代理 DNS 解析

  1. 必须要是 SOCKS5, SOCKS4 不支持远程 DNS 解析,Windows 用户主要注意。
  2. 设置代理后,浏览器不再进行 DNS 解析,而是把域名放进 SOCKS 请求中,直接将 SOCKS 数据转发给代理服务器。
  3. 代理服务器从 SOCKS 请求中获取到域名,由代理服务器来决定是否采用系统 DNS 服务器解析域名。
  4. 此时,解析 DNS 的请求发起方是代理服务器。

3. DNS 请求

1
2
3
4
5
6
7
F1

+------+-------+--------------------------+
| IP 头| UDP 头 | DNS 头 及 其 请 求 内 容 |
+------+-------+--------------------------+

重点:一般这种 DNS 请求都是纯文本(我们也只讨论这种 DNS),它们所流经的各种设备,各种程序都可以看到,可以修改里面的内容,发出的请求可以修改,返回的结果也可以修改,甚至修改过后毫无痕迹,就是说,对于发出的请求,DNS 服务器没办法知道它是否在中间链路被修改过,对于返回的结果,应用程序也没办法知道它是否在中间链路被修改过

这是一个 IP 包,从某种角度来看可以说它是一个承载了 UDP 流量的 IP 包,其中 IP 头中包含了源地址(本机 IP)和目的地址(114.114.114.114),UDP 头中包含了源端口(随机)和目的端口(53),DNS 头及其请求内容中包含了请求要解析的域名(www.bilibili.com),要解析的 DNS 类型(A/AAAA)。

3.1. udp over tcp 和 udp in tcp

两者是同一个东西,都是把 DNS 的 UDP 包封装到 TCP 包中,接收方收到 TCP 包,然后恢复出来 UDP 包。

4. 内置 DNS

4.1. Hosts

因为域名解析是交给了代理服务器来做,那么 代理服务器可以实现自己的 Hosts

4.2. DNS 分流

实现内置的 DNS,因为 CDN 的问题,需要对 DNS 请求分流,否则会出现返回了一个离自己很远,或者国外的 CDN IP 地址。

4.3. 正确的配置内置 DNS 的注意事项

  1. 正确配置 servers 列表及域名分流(用域名信息来选 DNS 服务器)
  2. 正确为发出的 DNS 请求配置路由规则(用 DNS 服务器的地址信息以及流量的协议信息:IP,端口, TCP/UDP )

5. V2Ray DNS Outbound

5.1. 作用

对进来的 DNS 流量进行拦截、解析,以及对 A, AAAA 类型的 DNS 查询做重新转发。

5.2. 原理

因为 DNS 的请求 UDP 包是明文的,所以,可以获取,修改,修改返回的响应,或者生成一个假的响应(DNS “劫持”)

5.3. 把 DNS 流量导入 Outbound

5.3.1. 手动设置代理

手动配置 SOCKS(HTTP/HTTPS) 代理(SOCKS5 支持远程 DNS 解析)。

5.3.1.1. HTTP(S) 代理和 SOCKS 代理区别

  1. HTTP(S) 属于应用层协议,SOCKS 是会话层协议,位于表示层和传输层之间。
  2. HTTP(S) 需要代理服务器支持 HTTP(S) 协议,而 SOCKS 需要代理服务器支持 SOCKS 协议。
  3. SOCKS 只关心数据包,并不关心数据包中是 HTTP(S)还是 FTP。
  4. SOCKS代理还可以转发UDP流量和反向代理,而HTTP代理不能

5.3.2. 本地搭建 DNS server

  1. 监听 127.0.0.1:53 端口
  2. 本机的 DNS server 修改为 127.0.0.1

5.3.2.1. 移动端 – tun2socks(lwip 协议的实现)

参考:socks代理转化为VPN的工具

对于 iOS,Android 而言,SOCKS5 代理在非越狱和 root 的情况下不被支持,不过能得到 ip 数据包,所以要想办法把 ip 数据包转成 TCP/UDP 的包,这样才能分析出 TCP/UDP 中的内容进行转发。

这里引入一个开源的 TCP/IP 协议栈:lwip,它简单占用内存小,所以能运行在移动设备上,我们要的是让它接收系统的 ip 数据包,分析出 TCP/UDP 数据内容。但是对于标准的 TCP/IP 协议栈,由于系统的 ip 数据包发送的目的地与这个协议栈运行的地址不同,所以正常情况下它是不会被解析出来的,不过由于这个协议栈相对来说简单,所以我们可以进行改造,让它不管是去哪里的 IP 数据包,都像本来就是发送给他的一样;这样它能 accept 发给其它地址的 tcp 的连接,可以直接读取 tcp 连接之后的发送的内容;这也就是为什么叫 tun2socks 了(改造的过程其实很简单,只是把在 tcp 段组成 tcp 时的 ip 和 port 限制去掉就行了),并且由于它能让我们得到 tcp 发送的数据包,这样就不用另一个socks代理了。

tun2socks 是一个进程,这个进程可以做到左手连接一个 tun 设备,右手连接一个 sock5 代理,然后在两者之间做数据对拷。所以使用了 tun2socks 之后,shadowsocks 自身的客户端提供的就是sock5 的代理接口.

tun2socks,能够把所有本机应用程序发出的流量都交给 V2Ray/SOCKS/Shadowsocks,从而达到全局 TCP/UDP (DNS) 代理(对,只是 TCP/UDP ,ICMP(lwip协议是支持的) 等等是不支持的,全局性还是不比真正的 VPN)。

go-tun2socks 是一个命令行工具,要使用的话还要自己创建 TUN 接口,配置路由表等,比较繁琐,这里还有另一个应用叫 Mellow ,对 go-tun2socks 进行了包装,可以自动完成这些繁琐的步骤,实际使用起来的效果就相当于 Privoxy、SSTap、Surge for Mac 等软件,可以把所有流量都代理了:

6. Fake DNS

不管是发到 freedom outbound 直连还是发到 VMess outbound 代理,这些 DNS 请求终究是要以实际的流量形式从本地发送到互联网上。可以在利用 tun2socks 获取所有 TCP/UDP 流量的同时,又可以像 HTTP/S 和 SOCKS5 代理那样,本地完全不发出 DNS 请求流量,只把域名交给代理服务器,让代理服务器自己去解析,这个就是 Fake DNS。

7. DNS Fallback

DNS fallback(这个名字可能不太对),在代理服务器不支持 UDP 的时候,单纯的全局 TCP/UDP 流量代理 就会出问题了,因为要解析 DNS 就需要 UDP,服务器不支持 UDP 就没办法处理 DNS ,也就没办法处理所有域名请求了,DNS fallback 是一种可以强制让应用程序把 DNS 请求以 TCP 流量发送出去的技术。

众所周知一般的 DNS 请求都是用 UDP 发的,但 DNS 的 UDP 报文的大小会被限制在大概 512 字节,如果某个 DNS 答复很长,超过了这个限制,就不能通过 UDP 来传输了,为此 DNS 规范中提出,对于这种超过限制大小的 DNS 请求,DNS 服务器可以在答复中设置一个 flag(truncated),来告诉客户端这个答复太长,你不能用 UDP 来做这个 DNS 请求,请用 TCP,于是客户端就会用 TCP 来重新请求 DNS。
DNS fallback 正是利用了这一点,在 tun2socks 给过来的 UDP 流量中识别出 DNS 请求,然后伪造一个设置了 truncated flag 的答复返回给客户端,客户端就会转用 TCP 来做 DNS 请求了。

Just for my love !!