tun2proxy DNS
tun2proxy 代码库 DNS 解析说明
tun2proxy通过在
src/args.rs文件中定义的
ArgDns 枚举来提供三种不同的DNS处理策略:
Virtual,
OverTcp, 和
Direct。核心的处理逻辑位于
src/lib.rs` 文件的主循环中,它会根据用户选择的策略来处理发往53端口(DNS端口)的UDP数据包。
以下是三种策略的详细代码逻辑分析:
1. Direct DNS (--dns direct
) - 直接转发
这是最简单直接的策略,也是默认策略。
-
工作原理:
当tun2proxy
捕获到一个目标为DNS服务器(端口53)的UDP数据包时,它不会解析或修改DNS查询内容本身。它的核心操作是:如果数据包的目标IP是一个私有或保留地址,它会将其目标IP地址修改为您在参数中指定的公共DNS服务器地址(--dns-addr
,默认为8.8.8.8
)。然后,这个数据包会像其他普通数据包一样,被路由到TUN虚拟网卡,并通过代理服务器转发出去。 -
代码逻辑:
在src/lib.rs
的主循环中,如果DNS策略是Direct
,代码会执行info.dst.set_ip(dns_addr);
这行指令,将数据包的目标地址设置为配置的DNS服务器地址,然后就进入标准的UDP代理处理流程。 -
适用场景:
- 当你信任你的代理服务器能够正确、高效地处理UDP数据包时。
- 当你的系统或应用需要直接与特定的DNS服务器通信时。
- 这是最接近“透明代理”的模式,对DNS查询的干预最少。
2. DNS over TCP (--dns over-tcp
) - TCP封装
此策略旨在解决代理服务器对UDP支持不佳或网络环境对UDP不友好的问题。
-
工作原理:
当tun2proxy
捕获到一个UDP DNS查询时,它并不会直接转发这个UDP包。相反,它会:- 将这个会话的协议标记从UDP更改为TCP (
info.protocol = IpProtocol::Tcp
)。 - 与代理服务器建立一个TCP连接。
- 在原始的DNS查询数据包前,加上一个2字节的长度字段(符合RFC 7766规范),然后通过这个TCP连接发送给代理。
- 代理服务器将通过TCP将查询转发给DNS服务器,收到TCP响应后,再原路返回给
tun2proxy
。 tun2proxy
接收到TCP形式的DNS响应,去掉长度字段,将其还原为原始的UDP数据包格式,再发送给发起请求的应用程序。
- 将这个会话的协议标记从UDP更改为TCP (
-
代码逻辑:
相关逻辑主要在src/lib.rs
的handle_dns_over_tcp_session
函数中实现。它会建立一个TCP流,并在发送和接收数据时处理2字节的长度前缀,确保DNS报文的正确封装和解封装。 -
适用场景:
- 代理服务器不支持UDP转发(UDP Associate)。
- 网络环境(如移动网络)对UDP不友好,丢包严重,但TCP连接稳定。
- 需要更可靠的DNS查询传输。
3. Virtual DNS (--dns virtual
) - 虚拟IP映射
这是功能最强大也是最复杂的策略,通常被称为 "Fake IP" 模式,能有效防止DNS泄露。
-
工作原理:
- 拦截查询:
tun2proxy
捕获到DNS查询后,并不向任何外部DNS服务器转发。 - 分配虚拟IP:它在内部维护一个IP池(默认为
198.18.0.0/15
)。src/virtual_dns.rs
中的VirtualDns
模块会为查询的域名(例如www.google.com
)从这个池中分配一个虚拟IP(例如198.18.0.10
),并记录下www.google.com -> 198.18.0.10
这个映射关系。 - 伪造响应:
tun2proxy
会伪造一个DNS响应包,发回给应用程序,告诉它www.google.com
的IP地址是198.18.0.10
。 - IP连接捕获:应用程序收到响应后,会尝试与
198.18.0.10
这个虚拟IP建立TCP或UDP连接。 - 域名反向解析与代理:
tun2proxy
捕获到这个发往虚拟IP的连接请求。它会查询内部的映射表,将目标IP198.18.0.10
反向解析回原始域名www.google.com
。然后,它向SOCKS5/SOCKS4a/HTTP代理服务器发起请求,要求连接到域名www.google.com
,而不是那个虚拟IP。 - 远程解析:最终的DNS解析由远端的代理服务器完成。
- 拦截查询:
-
代码逻辑:
src/virtual_dns.rs
: 实现了VirtualDns
结构体,包括LRU缓存来管理IP和域名的映射,以及分配和回收虚拟IP的逻辑。src/lib.rs
:handle_virtual_dns_session
函数调用VirtualDns
来生成伪造的DNS响应。在处理TCP和UDP会话时,会检查目标IP是否在虚拟池中,如果是,则解析出域名,并将域名传递给代理处理器(例如SocksProxyImpl
)。
-
优势与适用场景:
- 防DNS泄露:真正的DNS解析发生在代理服务器端,本地不会有任何真实的DNS流量产生。
- 强制远程解析:完美支持SOCKS5h、SOCKS4a这类需要代理服务器进行域名解析的协议。
- 兼容性强:即使代理不支持UDP,也能通过此方式处理需要域名解析的UDP应用,因为解析过程被
tun2proxy
内部接管了。 - 推荐默认选择:在绝大多数需要强隐私保护和高度兼容性的场景下,这是最佳选择。
总结
策略 | 工作原理 | 优点 | 缺点 |
---|---|---|---|
Direct | 直接将DNS UDP包转发给指定DNS服务器。 | 简单高效,对DNS干预最少。 | 依赖代理的UDP转发能力,可能存在DNS泄露风险。 |
Over-TCP | 将DNS UDP查询封装成TCP流发送。 | 可靠性高,适用于UDP不稳定的环境或代理。 | 性能开销略高,增加了握手延迟。 |
Virtual | 内部维护虚拟IP池,将域名映射到虚拟IP,由代理服务器执行最终解析。 | 彻底防止DNS泄露,兼容性极强,支持远程域名解析。 | 实现最复杂,可能会与某些依赖特定IP行为的软件有冲突。 |
透明代理说明
在网络代理的领域中,“透明”这个词指的是代理服务器对用户和应用程序的“隐形”程度。一个完全“透明的代理”意味着,无论是用户还是正在运行的应用程序,都不知道自己正在通过一个代理服务器来访问网络。
具体来说,"透明"体现在以下几个方面:
-
无需配置:
- 非透明代理:你需要在操作系统或特定软件(如浏览器)的设置中,手动输入代理服务器的IP地址和端口号。应用程序知道它必须先把网络请求发送给代理服务器。
- 透明代理:用户和应用程序完全不需要进行任何代理设置。网络流量被网络设备(如路由器或像
tun2proxy
这样的软件)在底层自动拦截,并强制重定向到代理服务器。
-
应用程序无感知:
- 应用程序像平常一样发起网络连接,它认为自己是直接连接到目标服务器(例如
www.google.com
)。 - 它不知道中间有一个“人”在拦截、检查和转发它的所有数据。所有这一切都在它不知情的情况下发生。
- 应用程序像平常一样发起网络连接,它认为自己是直接连接到目标服务器(例如
-
流量的自动重定向:
- 透明代理的核心技术在于流量的重定向。在
tun2proxy
的场景中,它通过创建一个虚拟网络接口(TUN设备)并修改系统的路由表来实现这一点。 - 当你的电脑发送任何网络数据包时,操作系统根据新的路由规则,不会把它们发送到默认的物理网关,而是发送到这个TUN虚拟接口。
tun2proxy
程序就在这个接口的另一端监听,捕获所有流经的数据包,然后再将这些数据包通过你配置的SOCKS5或HTTP代理发送出去。
- 透明代理的核心技术在于流量的重定向。在
tun2proxy
如何实现“透明代理”?
tun2proxy
正是一个典型的透明代理工具。当你使用 --setup
参数时,它会自动完成以下操作,让代理过程对你完全“透明”:
- 创建虚拟网卡:创建一个
tun
设备,这是一个软件层面的虚拟网卡。 - 修改路由:修改你电脑的路由表,将大部分网络流量都指向这个虚拟网卡,而不是你的物理路由器。
- 修改DNS:它可能会修改你系统的DNS设置(例如,指向它自己的虚拟DNS服务器
198.18.0.1
),以确保DNS查询也被它捕获,从而防止DNS泄露。
当你运行一个程序(比如浏览器)时,浏览器向 www.example.com
发出请求。这个请求的数据包被系统路由到tun
设备,tun2proxy
接收到后,再通过远端的代理服务器去访问 www.example.com
。整个过程中,浏览器本身并不知道这一切的发生,它就像直接连接到了互联网一样。
所以,简单来说,“透明代理”的“透明”指的是代理过程的“隐形性”和“无感知性”。它让网络流量在用户和应用程序毫不知情的情况下,被自动地、强制地通过代理服务器进行转发。