Clash为什么放弃了Redir-host?
这篇文章主要是填之前留下的坑,本篇将深入探究redir-host的缺陷以及Clash放弃此模式的原因。要注意,这里要说的不是今天的Clash.meta/mihomo,而是已经删库的原版Clash内核。
DNS增强模式的意义
ClashDNS中有一个增强模式,其主要是为了透明代理而存在的,而redir-host是增强模式的一种,它与另外的Fake-ip模式最明显的区别就是redir-host模式为客户端返回真正的网站IP,而Fake-ip会伪造一个IP让客户端连接,等到客户端真正需要真实IP的时候才去解析。
在网络中发送的数据包头部中有IP、有端口、有协议,可以利用这些信息进行分流,可惜数据包的头部中并没有写域名,Clash是一个能根据配置分流流量的代理客户端,如果不能使用域名进行分流那么其使用效果将会大大受限,要完成域名分流就必须设法得知这些IP的目的域名。而另一方面,获取目标域名也有助于优化访问速度(让代理服务器解析域名会)
我们知道在如今要想访问互联网就难逃域名解析,大多数情况下要先进行域名解析,在得知网站的IP后访问网站。
flowchart LR
a("客户端")
a--->|1: 域名解析|b("DNS服务器")
a--->|2: 访问|c("目标网站")
对于Clash来说,客户端的这两个步骤几乎是独立的,而这也是麻烦所在,那就是:如何将两个不相关的步骤关联起来?
通过DNS解析得知目标网站是一个可行的办法:客户端访问teapotium.com
前通过域名解析得到了一个地址A,那么这个客户端只要访问了地址A那基本上就是在访问teapotium.com
。
至于怎么把目标地址A的流量发给地址B或者是一个域名?这不是我们需要担心的事,你只要知道在技术上可以实现而且不会影响客户端访问。这种把流量发送到其他目的地的方法被称为redir-host
(翻译过来就是重定向主机)。
fake-ip
模式同样需要将流量发往其他目的地,所以它其实是基于redir-host
实现的。只是在ClashDNS的增强模式中以redir-host
代表经典的DNS模式,而fake-ip
则是因为其独特的假ip响应作为独立的模式名称。
redir-host模式的缺陷
redir-host的弱点仍是无法将域名解析和实际访问准确关联。
假设某一个ip上托管了多个不同域名的网站,那么这些网站的域名解析就会是相同的ip地址,如果客户端同时访问了其中两个网站,在Clash中就会有一个有趣的状况:
- 域名A的IP是1.1.1.1
- 域名B的IP也是1.1.1.1
- 客户端访问了1.1.1.1,此时Clash不知道目标是域名A还是B。如果随意按一个域名处理那么最终一定会影响客户端的访问。
那现实中有没有这种一个ip上有多个域名的情况呢?有,还很多。CDN就是一个例子,其每个节点上都托管了无数的网站,又恰好DNS是就近解析的,在你访问同CDN的网站时大概率会得到差不多的解析结果。除此之外Nginx此类web服务器均有同时运行多个网站的能力,即使没有使用CDN也有出现上述问题的可能。
Clash发现这个问题后在1.8.0版本开始就禁用redir-host的远端解析功能了,后来干脆直接移除了这个模式。
在当时的Clash文档中还提到了可以通过在fake-ip-filter
添加一条匹配所有域名的规则+.*
让Clash强制变为redir-host模式。
还有另一种情况:
- 你的域名A有两个IP:1.1.1.1,2.2.2.2
- 你访问了域名A,同时Clash记下了这个域名和IP
- 你忽然想起2.2.2.2这个服务器上有些设置忘记调整了
- 你使用SSH工具连接到2.2.2.2
- SSH连接被Clash捕获
- Clash根据你的目标IP发现你其实要访问域名A,并将SSH连接重定向到域名A
- 最后你发现SSH连接失败了
就是说,即使你访问的是纯IP,只要你访问过这个IP相关的域名,那么Clash就会将你的请求重定向到这个域名。
为什么Fake-ip没有这种缺陷?
首先,Fake-ip会通过污染DNS解析的方式提供假ip,它根据不同的域名会提供不同的假ip,可以正常处理以上问题:
- 域名A的IP是198.18.0.2(假ip)
- 域名B的IP是198.18.0.3(假ip,因为域名A和B是不相同的,Clash没有为其分配相同的假ip)
- 客户端访问198.18.0.2可得知是域名A,访问198.18.0.3可得知是域名B
Fake-ip几乎完美解决了上述问题,又因为直接返回假ip所以不需要每一次都需要等待域名解析完成(可以省下一次解析)还可以在一定程度上缓解DNS污染/故障,这个模式可以说是相当完美了。
Clash.meta/mihomo中仍然存在redir-host?
虽然redir-host有上述的缺陷,但好在这个问题并不是很常见,而且Fake-ip仍然有一些无法处理的情况,所以meta内核选择恢复了redir-host模式,并且依靠域名嗅探功能尽可能弥补缺陷,在今天的meta内核下redir-host已经十分稳定可靠了
官方原版Clash于v1.80版本后,为了防止单IP对应多域名情况下mapping失败,停止了Redir Host模式下向远端VPS传递域名的行为(这样无法通过VPS进行远端DNS解析,导致跨国多CDN网站无法就近解析/机场的Netflix的DNS解锁失效等问题);
Meta回滚了Redir Host部分代码,仍然保留官方v1.70以前的Redir Host模式的域名传递行为,配合Meta独有的 Sniffer域名嗅探器 ,可完美解决上文所述问题。
—— Clash meta文档
原版的Clash开发者维护了两个版本:开源版(或者叫FOSS版)和Premium版(闭源,与开源版相比拥有一些特色功能如TUN,Script模式等)。
meta内核则是基于开源版开发的,它实现了很多原版没有的新功能,甚至是一些Premium版的特色功能。