关于 Clash 科学上网的最佳实践
<h1>关于 Clash 科学上网的最佳实践</h1><p>回国出趟差,迫于 ChatGPT 在公司内网访问不了,又要开始研究翻墙技术。这次回国发现墙又增高了不少,不过也没之前朋友传言的那么恐怖,传言说几小时封一个节点,得用 IPv6 不断换 IP。我的节点有国外家庭宽带也有 VPS,实际体验下来没那么恐怖,节点一直都连得上,只是墙在 DNS 方面又加高了一些。</p>
<p>经过几天的搜寻资料,阅读文档,尝试各种组合,我可以负责任的说,在现在这个时间节点,没有人比我更懂软件里这些配置项。</p>
<h2>DNS – 上网的根基</h2>
<p>目前所有公共 DNS 都污染了谷歌 / ChatGPT 这些域名。普通 DNS 请求走的是 UDP 明文连接,少部分情况走 TCP 但是也是明文,污染一部分来自于墙的抢答,墙现在是随机返回一个 IP,没什么规律可言,所以没有好的检测应对策略。另一部分来自于 DNS 本身的污染,污染源我就无从得知了。具体表现如下,从国内 223.5.5.5 查询 chat.openai.com,返回的结果是被污染过的:</p>
<p>dig chat.openai.com @223.5.5.5</p>
<p>;; ANSWER SECTION:</p>
<p>chat.openai.com. 1 IN A 128.242.245.93</p>
<p>;; Query time: 8 msec</p>
<p>;; SERVER: 223.5.5.5#53(223.5.5.5) (UDP)</p>
<p>但是从境外请求 223.5.5.5 就是正确的</p>
<p>dig chat.openai.com @223.5.5.5</p>
<p>;; ANSWER SECTION:</p>
<p>chat.openai.com. 146 IN CNAME chat.openai.com.cdn.cloudflare.net.</p>
<p>chat.openai.com.cdn.cloudflare.net. 146 IN A 104.18.37.228</p>
<p>chat.openai.com.cdn.cloudflare.net. 146 IN A 172.64.150.28</p>
<p>;; Query time: 28 msec</p>
<p>;; SERVER: 223.5.5.5#53(223.5.5.5) (UDP)</p>
<p>有人可能会觉得墙在抢答,DNS 本身还是干净的,那我们再来一组实验,从<strong><em>境内</em></strong>分别使用国内的 DoH 和国外的 DoH:</p>
<p># 从境内请求境内的 DoH</p>
<p>dog --time chat.openai.com --https @https://dns.alidns.com/dns-query</p>
<p>A chat.openai.com. 1m45s 108.160.162.102</p>
<p>Ran in 118ms</p>
<p># 从境内访问境外的 DoH</p>
<p>dog --time chat.openai.com --https @https://1.1.1.1/dns-query</p>
<p>CNAME chat.openai.com. 1m53s "chat.openai.com.cdn.cloudflare.net."</p>
<p>A chat.openai.com.cdn.cloudflare.net. 1m53s 172.64.150.28</p>
<p>A chat.openai.com.cdn.cloudflare.net. 1m53s 104.18.37.228</p>
<p>Ran in 1631ms</p>
<p>结果不言而喻了,国内的 DNS 环境,除了墙会抢答之外,DNS 本身也会污染一些结果。不过我相信阿里 DNS 解析大多数域名还是干净的,只是污染了某几个特殊照顾的域名。这点也是下面某些配置的前提。</p>
<h2>关键词说明</h2>
<p>为避免歧义,先对几个关键词作出说明</p>
<ol>
<li>终端:指运行师夷长技工具的设备,例如电脑/手机等等</li>
<li>代理工具:即上面说的师夷长技工具,例如 Clash / Surge 等等</li>
<li>远端:指<strong><strong>代理工具</strong></strong>使用的节点</li>
<li>本地:泛指<strong><strong>终端</strong></strong>和<strong><strong>代理工具</strong></strong></li>
<li>兜底策略:没有匹配任何规则的策略,例如 DIRECT / Proxy 等等</li>
</ol>
<h2>关于 tun 模式和 fake IP</h2>
<p>在普通的模式下,即设置系统 socks5 / http 代理的情况下,当<strong><strong>终端</strong></strong>发起一个连接的时候是直接全部封装网络包发出去,发之前不做域名解析。在这种情况下,如果触发了<strong><strong>代理工具</strong></strong>的分流规则,自动就会走<strong><strong>远端</strong></strong>解析,反之如果没触发,走直连并且使用前面配置的 nameserver (223.5.5.5) 解析。</p>
<p>而在 tun 模式下,由于在网卡层接管流量,代理是透明的,<strong><strong>终端</strong></strong>则和正常请求一样,需要先拿到一个 IP 才可以发起连接,普遍来讲<strong><strong>代理工具</strong></strong>都会劫持所有 53 端口的请求,也就是说 IP 普遍来讲都是<strong><strong>代理工具</strong></strong>提供的,可以是真实解析再提供,也可以是提供一个假的 IP 骗<strong><strong>终端</strong></strong>先发起连接。</p>
<p>真实解析固然是好,但是速度从几十毫秒到几千毫秒不等,而且这个 IP 还不一定用得上,例如发起的连接触发了分流规则,走<strong><strong>远端</strong></strong>解析,或是 IP 被污染导致网站打开失败。这个时候就可以引入一个概念 fake IP。fake IP 这个概念出自 <a href="https://www.rfc-editor.org/rfc/rfc3089" \t "/Users/mac/Documents\\x/_blank">RFC3089</a>,早在 2001 年就被提出来了,下文的讨论假设 fake IP 被设置为 28.0.0.1/8 网段.</p>
<p>在 tun 模式下,<strong><strong>代理工具</strong></strong>是可以劫持所有网络包的,假设用户请求 chat.openai.com,<strong><strong>代理工具</strong></strong>先返回一个假的 IP 比如 28.0.0.2,同时记住这个映射关系:"chat.openai.com": "28.0.0.2",当<strong><strong>终端</strong></strong>对 28.0.0.2 发起连接的时候,<strong><strong>代理工具</strong></strong>就知道要访问的域名是 chat.openai.com,就开始判断规则,看是否整个走<strong><strong>远端</strong></strong>解析,或是走直连并且使用 223.5.5.5 解析。在这里不由得佩服<strong><strong>代理工具</strong></strong>开发人员的智慧。</p>
<p>简单讲:</p>
<ul>
<li>使用普通的系统代理可以让<strong><strong>终端</strong></strong>第一时间发起连接,进入分流阶段,缺点是部分应用不遵守系统代理,优点是除了前面一个缺点全都是优点</li>
<li>tun 模式是为了让<strong><strong>终端</strong></strong>实现全局代理的能力,但是 tun 模式下,<strong><strong>终端</strong></strong>拿到 IP 之后才会发起连接</li>
<li>fake IP 是为了让<strong><strong>终端</strong></strong>第一时间发起连接,进入分流阶段,后续和系统代理相同</li>
</ul>
<p>用 fake IP 接管 DNS 会造成一些意想不到的问题,这里需要和普通系统代理做个取舍。</p>
<h2>配置误区之 fallback dns</h2>
<p>fallback dns 是 redir-host 时代的产物,是为了解决 DNS 污染问题。</p>
<p>redir-host 模式也是 tun 模式的一种(还有一种叫 fake IP),tun 模式工作在第三层网络层,拿不到请求的域名,只能拿到连接的 IP 地址。那他如何根据域名规则分流呢?答案是先拦截 53 端口的 DNS 请求,自己建立一个映射表,在<strong><strong>终端</strong></strong>发起请求的时候来匹配访问的域名,从而进行后续分流等操作。</p>
<p>但是如果多个网站部署在同一个 IP 下,或者 DNS 被污染到同一个 IP,redir-host 就不准了(除非加上嗅探功能)。配置 fallback dns 之后,如果获取到的 IP 被判定为被污染(需要回滚),就使用 fallback dns 解析出来的结果。为了确保拿到的结果完全正确,fallback dns 要设置为境外的加密 DNS 服务器,因为无加密或者境内的 DNS 都会被污染。</p>
<p>但正如前文论述,使用境外加密 DNS 毫无体验可言,而且这个<strong><strong>本地</strong></strong>解析出来的 IP,绝大多数场景下是用不到的,最终还是会走<strong><strong>远端</strong></strong>解析。<strong><strong>终端</strong></strong>只是需要一个 IP 建立连接,<strong><strong>代理工具</strong></strong>只是需要一个 IP 来维护映射表而已。费时费力 fallback 出来的一个真实 DNS 结果,最终还用不上。fallback DNS 的核心功能只是一定程度上解决 DNS 污染问题,降低了映射表出错的概率。</p>
<p>所以随着发展,redir-host 已经被官方扫进了垃圾堆,毕竟硬伤太多了。在继任者 fake IP 模式下,<strong><strong>代理工具</strong></strong>拦截 53 端口的查询,立刻返回一个假的 IP,让<strong><strong>终端</strong></strong>立刻发起连接。由于假的 IP 是自己生成的,可以确保每个域名 IP 都不同,彻底杜绝了上述映射表出错的可能性,并且分流结果可以拿去给<strong><strong>远端</strong></strong>解析。</p>
<p>所以,在弃用 redir-host 并且改用 fake IP 模式的情况下,fallback 极大概率是不需要配置的,把黑名单规则写全,全部走<strong><strong>远端</strong></strong>解析,剩下的没被污染的域名走国内 223.5.5.5 岂不是更快。</p>
<p>如果一定要用 fallback DNS 的话,确保填入境外的加密 DNS 即可,因为 fallback DNS 的最终目的是正确解析被污染的域名。不过这样体验极差,境外加密 DNS 至少需要 1.5 秒拿到结果。</p>
<h2>Clash / Surge 配置注意事项</h2>
<p>很多年前大家都熟练掌握分流配置,自动测速配置,规则集这些,就不再赘述,主要分享下有关 DNS 污染的应对策略。</p>
<h3>协议选择</h3>
<p>首先,原厂 ShadowSocks 仍然是最稳的协议之一,V2Ray 插件我测试下来测速会慢个 1 秒左右,原因未知,其他协议例如 VLESS VMess 也都不错,性能表现都大同小异,没有发现哪一种协议被墙盯上的</p>
<h3>nameserver 配置</h3>
<p>nameserver 使用普通的无加密 UDP 协议就好,例如 223.5.5.5 和 119.29.29.29,前提是大厂 DNS 只重点关照特定几个域名,以及墙只抢答 53 端口的这些域名。如果将来有一天大面积抢答国外域名,需要再想对策,例如使用境内 DoH。</p>
<p>为什么不建议折腾 DoH DoT 呢,用境内的 DoH 解析 chat.openai.com,该污染照样污染,第一章节已经论证过了。也别想着用境外的 DoH DoT,DoT 853 公网端口不定时抽风,稳定性很差。境外的 DoH 普遍查询一次都在 2 秒左右,毫无体验可言,第一章节也已经论证过了。</p>
<p>gfwlist 域名直接走<strong><strong>远端</strong></strong>解析就好,<strong><strong>本地</strong></strong>只解析直连的网站,而这些没命中规则的域名大概率是没被污染的,走 DoH 解析没有意义,除非你特别介意明文传输的 DNS 数据包。</p>
<h3>fallback dns 配置</h3>
<p>在上个章节已经论述过,fake IP 模式下不需要配置 fallback dns。我自己还遇到过一些麻烦,贴出来仅供参考:</p>
<ol>
<li>Clash Premium 内核下,如果规则里写了 IP-CIDR,1.1.1.1/32,Proxy,no-resolve,<strong><strong>终端</strong></strong>进行 dig xxx.com @1.1.1.1 的时候是真的会走代理</li>
<li>Clash Meta 内核不支持这个特性,我没做太密集的测试,初步测试是不行</li>
<li>会有大量网站打不开,原因不明</li>
<li>即使我使用例如 https://1.1.1.1/dns-query 不需要解析 DoH 域名的,也会有网站打不开的情况,原因不明</li>
</ol>
<p>况且 fallback 支持的能力太弱了,只支持 geosite 匹配和 geoip 匹配,很容易误伤,即要么很多漏网之鱼,要么一杆子全打死,导致体验极差。本来好好的交给<strong><strong>远端</strong></strong>解析就好,多此一举还惹一身麻烦,总之只要你的 gfwlist 规则够用,就不太可能需要 fallback DNS。</p>
<h3>分流配置注意事项</h3>
<p>分流配置方面,尽可能移除不带 no-resolve 的 IP 规则(例如谷歌云亚马逊云的 IP 段),TG 之类的 IP 规则要保留但是必须加上 no-resolve,这样可以避免多一次解析 DNS。举个例子:</p>
<ol>
<li>假设现在有一个规则列表,里面有域名匹配,有 IP 匹配。当<strong><strong>终端</strong></strong>发起一个连接的时候,如果没有命中域名匹配,或者域名规则比较靠后,则<strong><strong>终端</strong></strong>上运行的<strong><strong>代理工具</strong></strong>会发起一次 DNS 请求,用来判断是否在 IP 匹配规则里,这里就会有潜在的 DNS 污染 /泄露 问题</li>
<li>带上 no-resolve 之后,则不会进行 DNS 解析,除非应用是对 IP 发起连接才会匹配到这条 IP 规则</li>
</ol>
<h3>其他配置</h3>
<p>节点测速必须用完整的时间,不要使用 unified-delay,因为某些协议的握手时间很离谱。例如我的节点上同时有原厂 ShadowSocks 和 V2Ray 插件 websocket 混淆的 ShadowSocks,V2Ray 插件的完整时间比原厂慢 1 秒,应该就是握手速度太慢,但是如果开启 unified-delay,插件版反而快 100ms。</p>
<p>如果你的<strong><strong>兜底策略</strong></strong>是直连,那么前面只写需要 Proxy 的规则就好了,不命中就会直连,没必要增加配置的复杂度,反之亦然。</p>
<p>我个人更喜欢<strong><strong>兜底策略</strong></strong>用直连了,因为现在各 vps 的 IP 地址被黑产污染的很厉害,兜底配置走代理很容易触发风控,例如 Cloudflare 的人机验证,谷歌的人机验证。我个人的想法是,只要 gfwlist 域名匹配规则够详细,就很难遇到 DNS 污染问题,对于非 gfwlist 的域名,走直连也没什么不好,遇到哪个网站直连慢的自己添加一条代理规则就好。</p>
<h3>tun 模式的缺陷</h3>
<p>tun 模式有两个问题,第一个问题下一个章节有解决方案,第二个就要自己取舍了</p>
<ol>
<li>配合去广告 DNS 使用的时候,由于<strong><strong>终端</strong></strong>拿到的假 IP 不为空,有些没节操的软件会引发雪崩,即不断循环发请求,导致设备发热以及额外的流量消耗</li>
<li>ping 命令拿不到真实的延迟</li>
</ol>
<h2>DNS 进阶配置</h2>
<p>部分用户是有去广告的需求的,会在规则列表引进来几万条拦截广告配置,但是<strong><strong>终端</strong></strong>毕竟处理能力有限,不如把这件事交给服务器来做,即搭建一个 AdGuard Home 服务。</p>
<p>众所周知中国境内想要搭建 53 端口的 DNS 服务器是违法的,不过搭建在非 53 端口目前还没人管。恰巧 Clash 这类软件支持自定义端口号的 DNS 服务器,自建的好处是重复请求的域名处理时间基本上是 0 毫秒,请求的速度只取决于网络延迟,比公共 DNS 还是要快很多。</p>
<p>由于中国很大,很多网站的 CDN 都细化到省份甚至城市,自建 DNS 的风险之一就是会把 CDN 解析到距离服务器最近的位置。通常来讲横跨半个中国网速也不会太慢,但是这样毕竟不环保,解决方案是打开 AdGuard Home 的 EDNS Client Subnet 功能,上游 DNS 服务器就会根据 ECS 的信息返回正确的 IP。</p>
<p>请注意并不是所有上游 DNS 服务器都支持 ECS 功能,测试方法如下</p>
<p># 新加坡</p>
<p>dig +subnet=111.65.50.0/24 api.bilibili.com @223.5.5.5</p>
<p>;; ANSWER SECTION:</p>
<p>api.bilibili.com. 1 IN CNAME a.w.bilicdn1.com.</p>
<p>a.w.bilicdn1.com. 1 IN CNAME i.w.bilicdn1.com.</p>
<p>i.w.bilicdn1.com. 1 IN A 164.52.39.43</p>
<p>/* 164.52.39.43 归属地是新加坡 CDS Global Cloud CO., LTD */</p>
<p># 广东深圳电信</p>
<p>dig +subnet=218.17.109.0/24 api.bilibili.com @223.5.5.5</p>
<p>;; ANSWER SECTION:</p>
<p>api.bilibili.com. 1 IN CNAME a.w.bilicdn1.com.</p>
<p>a.w.bilicdn1.com. 1 IN A 59.36.228.17</p>
<p>/* 59.36.228.17 归属地是佛山 中国电信 */</p>
<p># 北京移动</p>
<p>dig +subnet=223.104.3.0/24 api.bilibili.com @223.5.5.5</p>
<p>;; ANSWER SECTION:</p>
<p>api.bilibili.com. 90 IN CNAME a.w.bilicdn1.com.</p>
<p>a.w.bilicdn1.com. 90 IN A 111.31.33.21</p>
<p>/* 111.31.33.21 归属地是天津 中国移动 */</p>
<p>根据我的测试,国内只有 223.5.5.5 和 119.29.29.29 支持 EDNS 解析,国外只有 8.8.8.8 和 223.5.5.5 支持 EDNS。这些公共 DNS 服务器对应的 IPv6 地址也支持 EDNS。</p>
<p>将上述支持 EDNS 的服务器配置到 AdGuard Home上游 DNS 列表,即可较为完美的实现去广告+CDN 加速。附加好处是自建服务器到<strong><strong>终端</strong></strong>这段路径的 DNS 响应不会被 GFW 抢答,因为现阶段 GFW 只抢答 53 端口。PS: 如果上游配置的是 53 端口无加密 DNS,自建服务器到上游仍然会被抢答。</p>
<p>另外需要注意,开启 EDNS 功能会在一定程度上影响 DNS 缓存,如果你只在服务器物理位置附近活动,建议不要开启此功能,如果你全国各地到处跑,开启 EDNS 会更好一些。</p>
<p>配置完之后即可实现去广告了,不过恭喜你喜提机身发热,请求日志雪崩的问题,日志列表可以看到大量涌入的类似于 dial DIRECT error: dial tcp4 0.0.0.0:443: connect: connection refused 的错误,原因是 fake IP 模式下广告软件收到一个假的但是有效的 IP,而自建 DNS 给<strong><strong>代理工具</strong></strong>返回的是一个空 IP(0.0.0.0)。有些没节操的软件这时候就会疯狂重试,点名批评一下微软和英伟达的日志上报代码。解决方案是搜集日志列表雪崩的域名,或者 AdguardHome 拦截排行榜前几名的域名,写成 Clash 规则并且 REJECT 即可,REJECT 仍然还有少部分会不断重试但是总体情况已经好很多了。</p>
页:
[1]