MetaCubeX / mihomo

A simple Python Pydantic model for Honkai: Star Rail parsed data from the Mihomo API.
https://wiki.metacubex.one
MIT License
16.01k stars 2.6k forks source link

[Feature] 可否考虑在DNS部分中加入redir-host与fake-ip混合模式 #916

Open lyz05 opened 10 months ago

lyz05 commented 10 months ago

Verify steps

Description

如题目所述,我希望mihomo在域名解析的过程中,先遍历一遍规则,发现规则匹配的是DIRECT,则返回真实IP(类似redir-host行为),若不是DIRECT,则返回fake-ip。

这样做有什么好处呢?

  1. 让mihomo专注处理需要走代理的流量,而不需要处理直连流量。
  2. 减少mihomo对设备本身物理网络的影响。

应用场景(本机)

当我启用TUN模式,并开启自定义路由,设置为fake-ip网段。(即:目的IP为fake-ip网段的流量被mihomo捕获,其余流量走默认物理网卡) 这样做以后,所有直连的流量都不会经过mihomo处理,这样我就能灵活开启关闭mihomo,而不会出现连接中断。

应用场景(局域网中所有设备)

此外,这种方法还可以扩展到局域网中的其他设备。 我仅需在主路由上设置两个参数,就能实现全局域网设备的科学上网。

  1. 配置fake-ip网段静态路由到运行着mihomo TUN模式的设备上。
  2. 配置主路由DNS上游为mihomo的DNS。 带来的另外的好处就是局域网中的设备直连上网,不会被运行着mihomo的设备捕获,也不会受到mihomo设备性能的影响。 局域网中其他设备,按照域名解析需要被代理的流量,会被路由表正确路由到TUN网卡中。 一个小遗憾就是,对于IP直连的应用无法走代理。但是可以通过添加静态路由解决。

下面给出配置:

dns:
  enable: true
  enhanced-mode: fake-ip-mixed # 上文定义的混合模式策略
  listen: :1053
  fake-ip-range: 198.18.0.1/16 #设置fake-ip范围
  nameserver:
    - 223.5.5.5
  fake-ip-filter:
    - +.stun.*.*
    - +.stun.*.*.*
    - +.stun.*.*.*.*
    - +.stun.*.*.*.*.*
    - "*.n.n.srv.nintendo.net"
    - +.stun.playstation.net
    - xbox.*.*.microsoft.com
    - "*.*.xboxlive.com"
    - "*.msftncsi.com"
    - "*.msftconnecttest.com"
    - WORKGROUP
tun:
  enable: true
  stack: system
  dns-hijack:
    - any:53
  auto-detect-interface: true
  auto-route: true
  inet4-route-address:
    - 198.18.0.0/16 #fake-ip段
# 下面为Telegram IP段
    - 91.108.56.0/22
    - 91.108.4.0/22
    - 91.108.8.0/22
    - 91.108.16.0/22
    - 91.108.12.0/22
    - 149.154.160.0/20
    - 91.105.192.0/23
    - 91.108.20.0/22
    - 185.76.151.0/24

目前所用方案

目前我是在主路由上运行了mosdns,来做dns分流。 针对解析IP段为国外的,会选mihomo的fake-ip dns解析结果。 解析IP为国内的,直接返回解析结果。 这样做能让局域网中其他设备直连国内网站不受任何影响。

Possible Solution

No response

benyfu911 commented 10 months ago

You could try #913

Paulgudring commented 10 months ago

现在的情况是,如果你需要混用,fakeip-filter里的就是redir-host;如果你需要大规模混用,比如rule-set geosite,见pinned issue #515 ,这项功能没有必要实现,做透明网关建议直接redir-host,有sniff配置好了还是很完备的

lyz05 commented 10 months ago

现在的情况是,如果你需要混用,fakeip-filter里的就是redir-host;如果你需要大规模混用,比如rule-set geosite,见pinned issue #515 ,这项功能没有必要实现,做透明网关建议直接redir-host,有sniff配置好了还是很完备的

我的需求比较小众。做透明网关用redir-host是可行的,但我得在主路由上运行clash,主路由的性能/容量不足以让我运行clash。因此,我想用一台24h运行性能好的(旁路由)设备来运行clash。在不修改局域网其余设备网关的情况下,我得在主路由上配置指向旁路由的静态路由。如果采用redir-host,那我得导入相当多的路由条目。如果采用fake-ip,只需添加一条路由条目并配置分流的DNS即可。

xishang0128 commented 10 months ago

@lyz05 这边建议使用dae https://github.com/daeuniverse/dae

lyz05 commented 10 months ago

我有从境外连回家中网络的需求,redir-host模式下添加大量的境外路由,会导致境外访问家中设备的回程路由无法直连,而走的是clash网关。

sleepm commented 10 months ago

规则里 DIRECT 的应该设置 fake-ip-filter 确实不好实现

sleepm commented 10 months ago

可以设置为 normal

wcyws commented 10 months ago

真的居然和我的想法一模一样,比我早很多,同样的情况,家里的主路由是TPLINK,因为用了TP的AP,所以不方便更换主路由,而且旁路由不稳定,家里人也不喜欢随时断网,这时候所有设备指向主路由就很关键了,旁路由只负责DNS,就算挂了,DNS缓存也能支持一段时间。

我的想法有一点点不同,不是必须 "在fake-ip-filter里面塞一整个列表" ,其实还有个办法就是"预代理",基本就是CLASH的代理过程,过程如下所示,本人基本是个小白,如果有不正确的地方请指出:

  1. 7874端口获取dns请求之后,直接先进行域名规则匹配(黑名单,IP规则先no-resolve),这部分规则其实就是用户设置的clash规则集&脚本,黑名单命中直接返回fake-ip
  2. 如果1未命中,再匹配域名白名单,如果域名白名单命中,clash使用本地DNS服务直接进行最快的进行resolve,返回真实IP
  3. 如果2未命中,但是用户设置了IP规则,则clash使用本地DNS服务直接进行最快的resolve,结果再进行IP规则匹配,IP匹配命中无需代理则直接返回resolve结果,需要代理则返回fake-ip
  4. 最后最终返回结果是fake-ip,clash直接把连接请求发到远端服务器即可

我觉得这样操作应该不会带来额外开销,无论是返回真实IP还是fakeip,只是相当于多加了一个开关,不至于对性能延迟造成太大影响 -- 即在规则匹配的过程中去做判断返回真实IP还是fakeip,而不是重新做另一套DNS的判断。 也就是需要代理才返回fake-ip,无需代理返回真实IP。用户如果需要国内DNS分流,直接把geoip:cn规则放到自己的规则集中即可,如果不喜欢,可以关掉开关,或者全程不设置IP规则,依然和以前一样,使用fake-ip

我有把这个QA发送到了OPENCLASH,可能和这边的描述存在一点点出入,具体的链接如下: https://github.com/vernesong/OpenClash/issues/3693

skill7899 commented 10 months ago

说白了就是想国内IP或者域名直接走网卡,不经内核。经了内核有些nat的类型就不对了,特别是跑pcdn的。现在的实现都是在前分再做一次分流,用mosdns把域名解析命中国内IP的都写到ip_set,再写一条iptables,不在ip_set内的走tun。要是直接是IP访问的就GG了,只能自已再写一个获取国内IP的脚本,定时写另一个ip_set,如果这个功能实现了,那就不需要再做一次分流方案了。

deuteros-gex commented 9 months ago

真的居然和我的想法一模一样,比我早很多,同样的情况,家里的主路由是TPLINK,因为用了TP的AP,所以不方便更换主路由,而且旁路由不稳定,家里人也不喜欢随时断网,这时候所有设备指向主路由就很关键了,旁路由只负责DNS,就算挂了,DNS缓存也能支持一段时间。

我的想法有一点点不同,不是必须 "在fake-ip-filter里面塞一整个列表" ,其实还有个办法就是"预代理",基本就是CLASH的代理过程,过程如下所示,本人基本是个小白,如果有不正确的地方请指出:

  1. 7874端口获取dns请求之后,直接先进行域名规则匹配(黑名单,IP规则先no-resolve),这部分规则其实就是用户设置的clash规则集&脚本,黑名单命中直接返回fake-ip
  2. 如果1未命中,再匹配域名白名单,如果域名白名单命中,clash使用本地DNS服务直接进行最快的进行resolve,返回真实IP
  3. 如果2未命中,但是用户设置了IP规则,则clash使用本地DNS服务直接进行最快的resolve,结果再进行IP规则匹配,IP匹配命中无需代理则直接返回resolve结果,需要代理则返回fake-ip
  4. 最后最终返回结果是fake-ip,clash直接把连接请求发到远端服务器即可

我觉得这样操作应该不会带来额外开销,无论是返回真实IP还是fakeip,只是相当于多加了一个开关,不至于对性能延迟造成太大影响 -- 即在规则匹配的过程中去做判断返回真实IP还是fakeip,而不是重新做另一套DNS的判断。 也就是需要代理才返回fake-ip,无需代理返回真实IP。用户如果需要国内DNS分流,直接把geoip:cn规则放到自己的规则集中即可,如果不喜欢,可以关掉开关,或者全程不设置IP规则,依然和以前一样,使用fake-ip

我有把这个QA发送到了OPENCLASH,可能和这边的描述存在一点点出入,具体的链接如下: vernesong/OpenClash#3693

打了这么多字还反复修改过,说明不是来恶搞的,只是缺乏常识。你可能觉得:

dns分流时直接复用rules部分的功能就行,为什么要另做一套?这样后续rules说不定都不用再匹配了 这个逻辑非常顺滑,应该连代码都不用改太多,用户的配置文件也不需要大改

但这并不行。 哪怕采用了@benyfu911给出的commit,rules还是得写两套,dns分流和网络分流还是得分开做。 想不到什么特别言简意赅的方式给你解释,只能建议找点网络、dns相关的科班教程看看。

wcyws commented 9 months ago

打了这么多字还反复修改过,说明不是来恶搞的,只是缺乏常识。你可能觉得:

dns分流时直接复用rules部分的功能就行,为什么要另做一套?这样后续rules说不定都不用再匹配了 这个逻辑非常顺滑,应该连代码都不用改太多,用户的配置文件也不需要大改

但这并不行。 哪怕采用了@benyfu911给出的commit,rules还是得写两套,dns分流和网络分流还是得分开做。 想不到什么特别言简意赅的方式给你解释,只能建议找点网络、dns相关的科班教程看看。

感谢指正,这一思路的源头在passwall2的远程DNS配置中,上面写了一句话,类似的意思是“fakedns:在需要经过代理的时候使用”,于是想着能不能融合使用。我后面去看了V2ray-core和Xray-core的doc,发现他们的fakedns好像也是在配置文件中单独指定分流规则的....并没有融合一说..他们的配置如下 { "servers": [ { "address": "fakedns", "domains": [ // 与下方分流所用的内容一致 "geosite:cn", "domain:example.com" ] }, { "address": "1.2.3.4", "domains": ["geosite:cn"], "expectIPs": ["geoip:cn"] }, { "address": "1.1.1.1", "domains": ["domain:example.com"] }, "8.8.8.8" ] }

911 这个case如果能实现的话,当然也是极好的,fakeip-rule会非常好用 -- 虽然我不太清楚这里面的工作量...

yyysuo commented 9 months ago

这就是泡泡网关的思路啊,可以用2个vm来解决比较方便。

wcyws commented 9 months ago

忘了补充一下我自己的bypass方式了

    我这用的是cleardns,其实它的功能足以满足日常需求,而且配置起来也较为简单,相当于Adguard的域名分流规则以及fakeip-filter的域名规则,主要是多了工具自己写了脚本去抓chinaip,chinaDomain和Gfw规则,做了一个防污染的fallback,不用用户自己写脚本处理,相对来说较为方便

然后逻辑实现方式是 dns请求->53端口的adguardhome->cleardns->{114upstream , openclash upstream}

yyysuo commented 9 months ago

我用了2个月了,非常稳定 image

wcyws commented 9 months ago

我用了2个月了,非常稳定 image

是的,主要思路感觉非常近似,用路由表+IP来分流,只有工具使用选择上有区别

deuteros-gex commented 9 months ago

打了这么多字还反复修改过,说明不是来恶搞的,只是缺乏常识。你可能觉得:

dns分流时直接复用rules部分的功能就行,为什么要另做一套?这样后续rules说不定都不用再匹配了 这个逻辑非常顺滑,应该连代码都不用改太多,用户的配置文件也不需要大改

但这并不行。 哪怕采用了@benyfu911给出的commit,rules还是得写两套,dns分流和网络分流还是得分开做。 想不到什么特别言简意赅的方式给你解释,只能建议找点网络、dns相关的科班教程看看。

感谢指正,这一思路的源头在passwall2的远程DNS配置中,上面写了一句话,类似的意思是“fakedns:在需要经过代理的时候使用”,于是想着能不能融合使用。我后面去看了V2ray-core和Xray-core的doc,发现他们的fakedns好像也是在配置文件中单独指定分流规则的....并没有融合一说..他们的配置如下 { "servers": [ { "address": "fakedns", "domains": [ // 与下方分流所用的内容一致 "geosite:cn", "domain:example.com" ] }, { "address": "1.2.3.4", "domains": ["geosite:cn"], "expectIPs": ["geoip:cn"] }, { "address": "1.1.1.1", "domains": ["domain:example.com"] }, "8.8.8.8" ] } #911 这个case如果能实现的话,当然也是极好的,fakeip-rule会非常好用 -- 虽然我不太清楚这里面的工作量...

dns分流和网络分流总得分开做,那么即便这个issue的诉求被满足,也无非是原本在外面做的dns套娃被收进了clash本身。 问题的复杂度没变,只要思路错了,依然会有人像个别楼层里那样,去做一些比尔迈克式的套娃。 此时只能说开心就好了,毕竟机器性能都过剩,即便dns是负优化也没感觉。

而且既然读过v2ray和xray的doc,那看来也不介意上点难度,不妨跟着白话文教程自己搭透明代理试试(节点配置部分用转换器转换,只专注透明代理的实现即可),我个人觉得同样都是花时间折腾,那不如找对方向。现在有了AI辅助理解,门槛低太多了。

很多feature都要求你了解上述基本流程的,所以不太可能只靠读passwall界面里只言片语的描述,就理解它具体是在做什么。这一点openclash也一样,比如 Vernesong/openclash#3467 但凡把花在openclash上的一星期时间花在透明代理上,恐怕也问不出这种没人愿意回答的问题了。

13wenwen commented 9 months ago

建议用sing-box,这个能满足你的要求

CarterCL commented 9 months ago

还是建议DNS和代理分开,也就是你目前的方案,如果mihomo崩溃或者设备关机,不影响局域网其他设备的国内流量。 假设全都让mihomo干,一崩全崩

qwerr0 commented 9 months ago

我也有这样的需求,使用额外的工具比如 mosdns 来分流需要加载一个很长的代理列表和直连列表,会额外占用不少的内存,同时更新列表也是一件麻烦事,在我的硬路由器上是一个不小的负担。我仿照之前某个 pull request 改了改,去除了 fakeip-filter 的规则,遇到 geosite:cn 就直接返回真实 IP,这样能充分利用路由器的 NPU 加速,现在用着很好。

hsj1992 commented 9 months ago

@lyz05 我说一下我的网络构造,不知道能否给你一点参考: 旁路网关 LXC:192.168.31.55 架设了mihomo,启用fakeip模式; DNS LXC:192.168.31.4 架设了PaoPaoDNS,自动将网络的CN域名(以及force_cn_list.txt里的域名)解析为正常国内IP,国外域名则解析为fakeip; 主路由 ROS VM:192.168.31.1 ,静态路由增加了一条fakeip指向旁路网关(到这里为止是PaoPaoDNS和PaoPaoGateWay的fakeip旁路网关构造思路),运行ospf协议从协议机获取nchnroutes静态路由; ospf协议机 LXC:192.168.31.55 运行bird2,以及我给自己为nchnroutes额外写的一个python文件。它会将PaoPaoDNS的HTTP服务器里force_nocn_list.txt的完整域名解析出IP的CIDR,然后作为nchnroutes的exclude参数从静态路由中剔除。然后nchnroutes会生成国外IP指向旁路网关的静态路由,协议机通过bird2和ospf协议让主路由获取到静态路由。

这样就是一层DNS分流,一层IP分流。 多套一层IP分流的目的是为了tg和netflix这些有不由域名而是直接连IP的应用; 我写一个python文件再用nchnroutes的目的是因为一些国外的域名需要在使用nchnroutes的同时不由国外IP静态路由经过mihomo,比如stun.parsec.app这种stun服务器域名。我需要这么做才能在两层分流中让parsec正常使用。域名写在PaoPaoDNS的fore_nocn_list.txt里避免被解析为fakeip。

我现在的一个问题就是旁路网关无法DIRECT连接国外IP了,否则会因为主路由的静态路由设置再次指向旁路网关它自己而陷入回环。 不过旁路网关本身就是要代理DNS分流过来的国外流量,一般也是直接开GLOBAL,不会有国外IP需要DIRECT。

lyz05 commented 9 months ago

我也有这样的需求,使用额外的工具比如 mosdns 来分流需要加载一个很长的代理列表和直连列表,会额外占用不少的内存,同时更新列表也是一件麻烦事,在我的硬路由器上是一个不小的负担。我仿照之前某个 pull request 改了改,去除了 fakeip-filter 的规则,遇到 geosite:cn 就直接返回真实 IP,这样能充分利用路由器的 NPU 加速,现在用着很好。

相关代码开源吗?想参考参考

lyz05 commented 9 months ago

@lyz05 我说一下我的网络构造,不知道能否给你一点参考: 旁路网关 LXC:192.168.31.55 架设了mihomo,启用fakeip模式; DNS LXC:192.168.31.4 架设了PaoPaoDNS,自动将网络的CN域名(以及force_cn_list.txt里的域名)解析为正常国内IP,国外域名则解析为fakeip; 主路由 ROS VM:192.168.31.1 ,静态路由增加了一条fakeip指向旁路网关(到这里为止是PaoPaoDNS和PaoPaoGateWay的fakeip旁路网关构造思路),运行ospf协议从协议机获取nchnroutes静态路由; ospf协议机 LXC:192.168.31.55 运行bird2,以及我给自己为nchnroutes额外写的一个python文件。它会将PaoPaoDNS的HTTP服务器里force_nocn_list.txt的完整域名解析出IP的CIDR,然后作为nchnroutes的exclude参数从静态路由中剔除。然后nchnroutes会生成国外IP指向旁路网关的静态路由,协议机通过bird2和ospf协议让主路由获取到静态路由。

这样就是一层DNS分流,一层IP分流。 多套一层IP分流的目的是为了tg和netflix这些有不由域名而是直接连IP的应用; 我写一个python文件再用nchnroutes的目的是因为一些国外的域名需要在使用nchnroutes的同时不由国外IP静态路由经过mihomo,比如stun.parsec.app这种stun服务器域名。我需要这么做才能在两层分流中让parsec正常使用。域名写在PaoPaoDNS的fore_nocn_list.txt里避免被解析为fakeip。

我现在的一个问题就是旁路网关无法DIRECT连接国外IP了,否则会因为主路由的静态路由设置再次指向旁路网关它自己而陷入回环。 不过旁路网关本身就是要代理DNS分流过来的国外流量,一般也是直接开GLOBAL,不会有国外IP需要DIRECT。

为了加一层IP分流,设计的太复杂了。我还是倾向于主路由静态路由直接加某些不用域名解析的境外APP直连所用的IP段。因为这类IP,一定是在GFW的IP黑名单中的,本来就不可能直连,对本地网络不会有副作用。就能解决你遇到的想直连国外IP的问题。 相反,直接把所有的境外IP走代理,会影响到境外IP直连你本地公网IP。比如:BT下载,境外IP直连你本地公网IP。你本地机器回包的时候会绕道mihomo,境外IP会发现回来的报文跟发出去的报文IP不一致(发出去的是本地公网IP,回来的是梯子落地IP)。你举例中的各种stun应用