今天了解到了一些关于代理环境下DNS解析知识,在此留下笔记。
背景与疑问:
我通过SSR代理浏览器可以快速访问Discord,但是Windows版的Discord缺无法连接,原因是一些软件并没有像浏览器一样走系统代理设置,流量无法通过SSR转发。于是我打算通过Proxifier代理Discord。
我的系统代理规则设置为PAC模式,discord.com域名在PAC文件中,因此会被SSR代理,SSR代理规则设为绕过局域网和大陆,discord.com是国外网站因此走代理。
为了方便解释,将SSR客户端所在的主机成称为代理服务器,将SSR服务端所在的主机称为远端服务器。
我通过网上的教程配置Proxifier,启动Discord,可以看到流量转发到了代理服务器。然而discord一直显示更新失败,完全无法启动。
我在GitHub的SSR项目下看到了下图,解释了SSR代理规则。
按照这张图,Proxifier属于“其他软件”,它代理的流量会经过SSR代理规则的判断,应当被SSR代理。然而Discord完全无法连接,不知道问题出在哪里。我随手将系统代理设置改为“全局模式”,结果意外发现Discord可以连接上了。这更让我疑惑了。接着发现在全局模式下,Discord没有出现在Proxifier的连接列表中。以前也遇到过这种情况,因为Minecraft Launcher下载游戏太慢,我把他添加到Proxifier代理,发现启动MC Launcher后Proxifier一点反应都没有。在网上找到了这篇文章解释了这个现象:Minecraft Launcher 无法通过代理连接至服务器的问题 - 黎明余光。
基础知识:
为了搞清楚这些问题,我先在百度上先后搜索了“程序通过域名还是IP访问服务端”,“域名解析是应用程序发起的吗”,“程序被代理后,由谁负责dns解析”,最终找到了这篇好文,解答了我许多疑问:https://blog.skk.moe/post/what-happend-to-dns-in-proxy/。
应用程序通过域名访问一个地址,在自身DNS缓存(如果有的话)中没有记录的话,会调用操作系统的 getaddrinfo 方法,向操作系统寻求结果。操作系统会查询自身缓存,或向配置的DNS服务器发起查询,最终返回结果给应用程序。也就是说,应用程序需要根据域名查询到精确的IP才能进行连接。
如果一个应用程序支持代理,那么应用程序就会直接将域名封装在 SOCKS5 流量之中发往代理客户端。如果代理客户端设为直连,则由代理客户端负责域名解析。如果设为代理,则将域名封装发送至远端服务器,由远端服务器负责域名解析。考虑到CDN优化,这样做很合理。
分析:
意外发现,在关闭代理软件的情况下,我仍然可以通过浏览器访问Discord网站。但是这个网站不是被墙了吗?我猜测虽然域名被墙,但IP解析结果不确定,所以IP没有被墙。况且DNS解析是由远端服务器完成的,不会受到国内DNS污染的影响。因为浏览器的DNS缓存,所以discord.com可以不经代理直接连接。
在启动SSR的情况下,通过查看日志,可以发现访问Discord的时候,进行了一次DNS查询:
因为设置了代理,所以浏览器不再需要从自己的 DNS 缓存中寻找 discord.com 对应的IP.
前面都在用Firefox测试,下面用Chrome测试。
无代理首次访问discord.com时无法连接,通过地代理连接一次,浏览器有了DNS缓存,可以在无代理的情况下继续访问discord.com。重置Chrome清除DNS缓存,Chrome在没有代理的情况下无法访问discord.com。
使用Proxifier代理Discord失败,猜测应该是Proxifier接管了DNS查询职责,却有没有查到结果,因此无法连接。修改Proxifier的DNS设置,由 Detect DNS settings automatically 改为 Resolve hostname through proxy,此时Discord可以正常通过Proxifier代理打开。
在只开启SSR的情况下,系统代理规则设为PAC模式,Discord无法启动,而设为全局模式就可以启动。如果说Discord像浏览器一样收到系统代理设置的影响,说明Discord访问了一个没有出现在PAC文件中但却无法直连的地址。Discord启动时会先进行更新,更新失败则无法启动。很可能是更新服务器无法连接。然而Proxifier中只能看到访问了discord.com:443。关闭代理后打开IP雷达,只能看到Discord访问了一个IP,而且每次启动这个IP都会变。
当我尝试用抓包工具Fiddler的时候,又发现一个奇怪的问题。SSR处于PAC模式下,若打开抓包工具,Discord可以打开;若关闭抓包工具,Discord像往常一样无法启动。
暂且研究到这里,剩下的以后再研究。



