V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xjx0524
V2EX  ›  宽带症候群

dns 分流,国内 ip 直连, fakeip 转发到 clash

  •  
  •   xjx0524 · 173 天前 · 3773 次点击
    这是一个创建于 173 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近开始用上了 RouterOS ,科学上网通过旁路由 openwrt ,具体方案参考了站内一些大佬 fakeip 的方案。

    具体方案如下:

    1. ROS 基础配置参考了这个文档 https://gitee.com/callmer/routeros_toss_notes
    2. 旁路由部署了 mosdns 和 openclash ( fakeip 模式),mosdns 国内域名查询阿里腾讯 dns 返回真实 ip ,国外域名请求 clash 的 dns 端口返回 fakeip 。
    3. 主路由 ROS 设置 dns 指向旁路由,增加 to_op 路由表默认网关为旁路由,通过 mangle mark-routing 将目的地址为 fakeip 和 telegram ip 的流量 指向 to_op 路由表

    有一些疑问希望大佬们能帮忙解答一下

    1. 对于一些国外 ip (非域名)的连接,如果不像 telegram 那样特别配置,是不是就没法走科学线路,不知道这种 ip 直连的情况多不多?
    2. 我的 clash 直接用的机场的配置,我是希望 clash 保留原有域名规则的情况下,不去进行 dns 查询。我现在手动把所有 ip 规则配上了 no-resolve ,不知道这样是否有用,或者有没有更好的解决办法?
    3. 现在的配置下,打开国外网站不够丝滑,以谷歌为例,具体表现为
      1. 浏览器首次打开谷歌或过了较长一段时间后再打开,会白屏约 1 秒,后续再打开正常。推测应该是 dns 问题,没有了缓存就会这样?
      2. 无论是否首次打开,显示出页面后,网页 tab 处仍然会转圈一段时间

    上面 3 的这个情况,在我将设备网关手动设置成旁路由的时候,基本不会出现,希望大佬能提供一些排查思路。

    目前网络知识还是半吊子水平,有些问题不好直接搜索到,希望大佬们能帮忙解答一下

    23 条回复    2023-12-23 12:56:50 +08:00
    LisaSue
        1
    LisaSue  
       173 天前   ❤️ 1
    https://github.com/vernesong/OpenClash/issues/2767
    第三点的话你 f12 看下是不是这个情况.我 openclash 已经放弃 fakeip 了
    xjx0524
        2
    xjx0524  
    OP
       173 天前
    @LisaSue 还真是,测试了几个国外网站,Initial connection 和 SSL 耗时 7 、8 秒,还有一部分 Waiting (TTFB) 耗时比较长。
    之前用 openwrt 做主路由,所有流量全过 openclash 都没有这问题
    lkjkkk
        3
    lkjkkk  
       172 天前 via iPhone   ❤️ 1
    fakeip 加混合模式试试
    imKiva
        4
    imKiva  
       172 天前 via iPhone   ❤️ 1
    都用策略路由了就不需要在分流机器上用 openclash/shellclash 了。直接在“旁路由”上跑 clash 核心开 tun 模式和 fake ip ,然后 ip route add 198.18.0.0/16 dev utun

    从目前你的描述来看,ROS 上也不需要用 mangle ,更不需要 “to_op 的默认网关为旁路由”。一种性能更好的方法是:直接往 main 表里加一条 198.18.0.0/16 下一跳为旁路由的地址。但是你需要注意不能让你的机场域名被解析成 fake ip ,否则流量会成环。不过也可以用另一张路由表,假设叫做 bypass ,然后所有 src ip 为旁路由的流量走 bypass 表,bypass 表里的默认网关为 pppoe-out1 之类,再加上几条局域网的地址网关为 bridge 口就行。命令大概类似这样:

    /routing/table add fib name=bypass

    /routing/rule add src-address=旁路由 IP table=bypass

    /ip/route add distance=1 gateway=pppoe-out1@main dst-address=0.0.0.0/0 routing-table=bypass
    /ip/route add distance=1 gateway=bridge@main dst-address=192.168.0.0/16 routing-table=bypass

    然后 main 表上把 fake ip 导向旁路由

    /ip/route add distance=110 gateway=旁路由 IP dst-address=198.18.0.0/16 routing-table=main

    手机上靠印象打的,可能不太对,你自己弄的时候善用 tab 补全就好了
    imKiva
        5
    imKiva  
       172 天前 via iPhone   ❤️ 1
    对于 Telegram 这类,用同样的方法

    /ip/route add distance=110 gateway=旁路由 IP dst-address=<TelegramIPCIDR> routing-table=main
    imKiva
        6
    imKiva  
       172 天前 via iPhone   ❤️ 1
    @imKiva 我目前就在用同类方案,没有发现除了 TG 以外的 IP 直连的主流应用
    imKiva
        7
    imKiva  
       172 天前 via iPhone   ❤️ 1
    不推荐在策略路由下用这种带有包装的 clash 例如 openclash/shellclash 是因为:它们的配置是给一个路由器透明代理的最傻瓜级解决方案。

    但是在你有正确的 DNS 分流和 fake ip 之后,很多 shellclash/openclash 中的配置(例如什么打标记,tproxy 转发,53 端口放行云云)就不再需要了,因为策略路由已经完成了同样的事情。那么此时再让这些包装工具带上这些规则,只会增加调试难度,并且可能在你意想不到的地方带来问题。
    carrionlee
        8
    carrionlee  
       172 天前 via iPhone   ❤️ 1
    1. 是的,ip 直连的手动添加静态路由或者 routing rules (二选一),不建议用 mangle 。这种情况多不多要看你的使用场景。
    2. 是的,所有 ip 规则加上 no-resolve 就行
    3. 应该是你的默认防火墙规则导致的。应该有一条"drop invalid"的规则,把里面的 In. Interface List 改为 !LAN ,不然的话,clash 过来的流量会标记为 invalid 而造成 TCP 流量握手缓慢
    xjx0524
        9
    xjx0524  
    OP
       172 天前
    @carrionlee 感谢大佬,3 的问题改完确实好了。但为什么 tcp 握手流量会被判断为 invalid 呢?
    xjx0524
        10
    xjx0524  
    OP
       172 天前
    @imKiva 1 、ros 直接设置路由表的方式也试过,是没问题的。只不过想到会国外 ip 直连的情况,会加很多路由规则。所以就想着路由表看着清爽点,mangle 表复杂点。不过直接用路由表性能更优的话,那我还是改回来吧

    2 、用 openclash 也是因为之前习惯了图形界面,那这次我也直接改成部署核心吧。这种情况下,除了 ip route add 198.18.0.0/16 dev utun ;对于 udp 流量,或者国外 ip 直连的情况,也需要单独配置转发吧?我先研究下 openclash 自动加了哪些防火墙规则
    carrionlee
        11
    carrionlee  
       172 天前 via iPhone   ❤️ 1
    @xjx0524 好像说是加密流量的关系,具体没深究。静态路由的确性能更好。也可以用策略路由的方式(因为我有 2 条 vlan 都要走 fakeip ,所以用策略路由比静态路由灵活一点),性能应该差不多。总之都比 mangle 好。
    用虚拟机单纯装 shellclash 或者有个叫 paopapgateway 的项目,相对来说规则清爽一点,不过归根结底还是看 clash 配置文件。
    XIU2
        12
    XIU2  
       172 天前
    一直没折腾过路由器,看了下你的描述,就想问下:

    路由器上搞代理时,单纯的国内外 IP 分流很简单,但是否可以实现只让国外的 HTTP 协议流量走代理,其他的那些游戏啊什么 IP 直连(比如 TG )、或其他特殊协议的依然直连?
    毕竟对我来说大部分情况下只让网页类型的流量走代理就够了。

    如果说只能手动排除 IP 段的话,岂不是很麻烦而且无穷无尽?。。。
    xjx0524
        13
    xjx0524  
    OP
       172 天前
    @XIU2 这种需求是不是浏览器装个插件,使用 http 或 socks 代理就行?在路由器上去识别 http 协议比较麻烦吧
    imKiva
        14
    imKiva  
       172 天前 via iPhone   ❤️ 1
    @xjx0524 1. 一般来说 mangle 表会让 fasttrack 失效,这是最主要的性能影响。在需求简单的情况下用 /routing/rules 更好,你可以把这个当成一个更弱的 mangle ,但需要注意如果两个一起用,mangle 表优先。

    2. udp 流量不需要单独配置,因为 ip route 这条命令加的路由表对所有 ip 包都生效。并且 premium 和 meta 核心的 tun 都可以处理 udp 入站流量。
    对于国外 IP 需要进代理的,用同样的方法加路由表就行。如果你嫌要同时在两台设备上维护相同的路由表很麻烦,可以考虑用一些路由协议,比如 ospf 或者 bgp

    3. 如果你有 IPv6 策略路由的需求,方法同 IPv4 ,但 premium 核心的 tun 不支持 IPv6 入站流量,需要用 meta 内核
    xjx0524
        15
    xjx0524  
    OP
       172 天前
    @imKiva 感谢大佬解答,之后准备再把 ipv6 配置一下,有问题再来请教~
    hsj1992
        16
    hsj1992  
       144 天前
    @imKiva 想请问一下大佬,我同样是 ROS 主路由,本地 DNS 服务器和 fakeip 旁路网关使用了 PaoPaoDNS 和 PaoPaoGateWay 。
    ROS 是在静态路由表里加一条 11.0.0.0/8 ,下一跳为旁路网关的地址。

    在 ROS 开启了 Endpoint-Independent NAT 后,地址是直连的 STUN 服务器,NAT 类型测试的映射/过滤行为都是 EndpointIndependent;
    但是不直连而是经过旁路网关的 STUN 服务器,NAT 类型测试的映射/过滤行为变成了 AddressDependent/EndpointIndependent;
    终端把 IPV4 网关地址 手动设置成旁路网关 IP 地址,NAT 类型测试映射/过滤行为就都是 EndpointIndependent 了,说明旁路网关的 Full Cone NAT 没问题。

    这个情况是设置因为静态路由导致的么?
    imKiva
        17
    imKiva  
       144 天前
    @hsj1992 这个问题我前两天刚好在调试,阅读了一下 NatTypeTester 的源码,正好可以解答。我不清楚 PaoPaoGateway 里用的 Clash 是 Premium 核心还是 Meta 核心。Premium 核心似乎是不支持 Endpoint-Independent NAT 的(存疑),但是 Meta 核心在 tun 小节的配置里有一条 `endpoint-independent-nat: true` 设置之后就可以做到 mapping/filtering 都变成 EndpointIndependent 。

    在上面的设置的基础上,从你的描述中 “终端把 IPV4 网关地址 手动设置成旁路网关 IP 地址....” 这一段可以看出,你用的核心应该已经给你做好了 EndpointIndependentNat (应该?),所以上面的内容可以忽略(打的时候没看到这一句,但是懒得删了,希望对后人有帮助)。这可能和 STUN 协议的原理有关,STUN 检测 filtering 行为的原理可以简单描述为:

    1. 你向 stun server (记为 A ) 说 “请返回我现在访问你用的 IP:Port”
    2. stun server 返回以下内容:
    1. 你当前访问 stun server 的 IP:Port ,记为 Self
    2. 给你发这条回复的 stun server 的 IP:Port ,即上面的 A
    3. 另一个 stun server 的 IP:Port ,记为 B
    3. 你向同一个 stun server A 发起一个请求,说 “请 改变 IP 和端口 向我发起一条请求”
    4. stun server B 会向你的 Self 发送一个 stun 包,如果你能接收到,那么说明 filtering 行为是 EndpointIndependent

    从这个过程中可以看出,Clash 会在第 4 步的时候用一个“之前你没有主动发起连接”的 IP 向你回包。但是我在测试的时候发现:tun 使用的 stack 不同( gvisor 或者 system ),会有不同的回包 IP 行为,其中使用 system stack 存在 bug 。所以如果你的 PaoPaoGateway 里的 tun 用的是 system stack ,考虑切换到 gvisor 并配合 Meta 核心的 `endpoint-independent-nat: true` 再做尝试。
    此外,还可以把 ROS 里的有一条 “drop invalids” 的规则里的 In. Interface. List 改成 !LAN ,我看前人的一些教程一上手就把这个规则改了,但我没测试过这个防火墙规则是否有影响,你也可以试一试。

    这个问题其实非常复杂,我自己调试的时候费了不少功夫,最后还修改了 Clash Meta 核心的代码才实现了 filtering/mapping 都是 EndpointIndependent 。如果你按照上述的方法不能得到预期的结果,可以加个联系方式,我有空的时候可以帮你看看,文字我觉得很难说清楚这个过程(主要是我没有用过 PaoPaoGateway 不知道里面的细节)。
    imKiva
        18
    imKiva  
       144 天前
    @hsj1992

    > 这个情况是设置因为静态路由导致的么?

    99% 不是。我也使用静态路由的方式,客户端的网关均指向 ROS ,但在我的配置中得不到 FullCone NAT 的原因有两个:
    1. 我的静态路由配置不完全:因为我的 DNS 对 stun server 始终返回真实 IP ,在上面的第 3 步的时候会变成直连从而测出未定义行为。
    2. Clash Meta 的 tun 入站对 `conn.LocalAddr()` 的赋值存在 bug ,在我修复这个问题后,成功测出 FullCone Nat
    hsj1992
        19
    hsj1992  
       143 天前
    @imKiva
    谢谢您的答复!
    PaoPaoGateWay 好像不是使用 tun ( ip addr 和 clash yacd 面板里没看到 tun 设备),是 TProxy 和 nftables 。

    作者博客的详细说明文章: https://blog.03k.org/post/paopaogateway.html
    Github 项目地址: https://github.com/kkkgo/PaoPaoGateWay
    相关的两条 nftables 脚本和 clash 的基础 yaml:
    https://github.com/kkkgo/PaoPaoGateWay/blob/main/FILES/usr/bin/nft.sh
    https://github.com/kkkgo/PaoPaoGateWay/blob/main/FILES/usr/bin/nft_tcp.sh
    https://github.com/kkkgo/PaoPaoGateWay/blob/main/FILES/etc/config/clash/base.yaml

    我当时的使用是有替换为 Clash meta 内核(好像还是 2023-10-13 时候自己编译的)。
    不知道编译新版内核去替换再试试会不会有区别。
    imKiva
        20
    imKiva  
       143 天前 via iPhone
    @hsj1992 tproxy 我就不清楚了,我自己没有使用 tproxy 的动机。你可以在客户端上开个 wireshark 抓包一下用 NatTypeTester 之类软件测试过程中的 stun 包。用经过 clash 和不经过 clash 的 stun server 的两种流量互相对比一下,看看哪里不一样。
    hsj1992
        21
    hsj1992  
       126 天前
    @imKiva 我切换了旁路网关,改为 tun 模式,经过旁路网关的 stun 服务器做 NAT 类型探测 ,mapping 仍然是 AddressDependent Mapping 。

    尝试使用局域网的一台 linux 设备进行测试(使用 stun-client),发现了问题:
    执行命令 stun stunserver.stunprotocol.org -v ,然后按常理,如果是 NAT1 的 EIM NAT 的话,显示的数个 mapped address 应该都会是同一个 proxy 的 ip 地址。但是其中的一个 mapped address 出现了 direct 的 ip 地址。
    我做了个尝试,在主路由 ros 里将该 stun 服务器的国外 ip 地址网段 3.132.0.0/16 和 3.132.0.0/16 静态路由指向旁路网关,对该国外 stun 服务器再次进行测试,就好了,mapping 和 filter 都是 endpoint-independent 了。

    所以应该是 fakeip DNS 分流的问题。就像在我的使用场景里,要使用 tg 还需要给它的 CIDR 网段写静态路由指向旁路网关一样,NAT 类型探测也会有设备直接指向 IP 而没经过 fakeip DNS 的场景?
    然后导致 mapped address 有不同,导致 mapped IP same = 0 ,从而显示 AddressDependent Mapping 。
    所以当我设备的网关地址直接设置为旁路网关时候是 EIM NAT ,因为此时设备没经过域名指向 IP 也是走的旁路网关。

    我后续可能结合使用 ROS 的 IP 分流。
    imKiva
        22
    imKiva  
       126 天前 via iPhone
    @hsj1992
    > 要使用 tg 还需要给它的 CIDR 网段写静态路由指向旁路网关一样,NAT 类型探测也会有设备直接指向 IP 而没经过 fakeip DNS 的场景?

    是的。我上面的最近一条回复里也提到了:是静态路由配置不全的问题
    imKiva
        23
    imKiva  
       126 天前 via iPhone
    @hsj1992 我后来找了一些常用 stun server 的服务器地址,把他们都加入静态路由,具体是下面几个

    # STUN server
    # stunserver.stunprotocol.org
    route 3.132.228.249/32 via "utun";
    route 3.135.212.85/32 via "utun"; # STUN OtherAddress
    # stun.hot-chilli.net
    route 49.12.125.53/32 via "utun";
    route 49.12.125.24/32 via "utun"; # STUN OtherAddress
    # stun.syncthing.net
    route 139.59.84.212/32 via "utun";
    route 139.59.49.16/32 via "utun"; # STUN OtherAddress
    route 198.211.120.59/32 via "utun";
    route 188.166.128.84/32 via "utun"; # STUN OtherAddress
    # stun.fitauto.ru
    route 195.208.107.138/32 via "utun";
    route 195.208.107.140/32 via "utun"; # STUN OtherAddress
    # stun.l.google.com
    route 108.177.125.127/32 via "utun";
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1471 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:03 · PVG 01:03 · LAX 10:03 · JFK 13:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.