Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于DNS 模块里匹配优先级的可能bug #638

Open
5page opened this issue Jul 7, 2021 · 8 comments
Open

关于DNS 模块里匹配优先级的可能bug #638

5page opened this issue Jul 7, 2021 · 8 comments
Labels
bug Something isn't working documentation Improvements or additions to documentation

Comments

@5page
Copy link

5page commented Jul 7, 2021

按照xray文档描述,xray的dns模块请求优先级如下述:

1.查询的域名与某个 DNS 服务器指定的域名列表匹配时,Xray 会优先使用这个 DNS 服务器进行查询。
2.无匹配时, 按从上往下的顺序进行查询,并且会跳过 1 步骤中使用的最后一个服务器。

按照这个规则,如果有dns分流规则里有两条规则都匹配了某一个域名请求,那么xray会使用第一个匹配的dns进行查询。但我测量实际并非如此。

复现方法:

  • gstaticadssl.l.google.com 这个地址,"geosite:cn""geosite:geolocation-!cn" 都匹配。"geosite:cn" 里包含这个 google 域名因为这个域名在 beijing 有服务器,有些人为了加速 google 相关 app 响应会希望链接国内服务器。“geosite:geolocation-!cn” 也包括这个域名,因为有些人希望所有连接谷歌的服务都走 proxy 以避免 google 记录行为而把远端服务器 ip 拉到 cn 库。

  • 想实现后者,也就是所有 google 有关请求都走proxy, 又同时保证 "geosite:cn" 白名单里的其他域名可以直联,则需要利用 dns 规则,可以首先匹配 "geosite:geolocation-!cn" 规则走 proxy 的 dns ,之后匹配 "geosite:cn" 的规则,把其余的 cn site 导向国内 dns 比如 "114.114.114.114"

  • 如果模块工作符合预期,以上目的可通过以下 dns 配置得到。为了控制变量和方便在 log 里查看到底这条 gstaticadssl.l.google.com 请求走了哪个匹配,我用了3个不同的 dns 服务器 1.1.1.1 8.8.8.8114.114.114.114

    "dns": {
            "hosts": {
                "snapchat.com": "127.0.0.2"
            },
            "servers": [
                "1.1.1.1",
                {
                    "address": "8.8.8.8",
                    "port": 53,
                    "domains": [
                        "geosite:geolocation-!cn"
                    ]
                },
                {
                    "address": "114.114.114.114",
                    "domains": [
                        "geosite:cn"
                    ],
                    "expectIPs": [
                        "geoip:cn"
                    ]
                },
                {
                    "address": "1.1.1.1",
                    "port": 53,
                    "domains": [
                        "geosite:speedtest"
                    ]
                }
            ]
        },
  • 按照此配置,dig gstaticadssl.l.google.com @127.0.0.1 这条命令应从 "8.8.8.8" (第一个匹配的规则)得到 dns 解析结果。但 log 如下:

    2021/07/08 03:02:54 127.0.0.1:34606 accepted udp:1.1.1.1:53 [dns-in -> dns-out]
    2021/07/08 03:02:54 DNS accepted udp:114.114.114.114:53 [xray.system.3df764af-bd05-4a8a-890a-6f91592737d9 -> direct]
    2021/07/08 03:02:54 UDP:114.114.114.114:53 got answer: gstaticadssl.l.google.com -> [203.208.43.98, 203.208.43.98] 55.667373ms
    

    很明显 gstaticadssl.l.google.com 被匹配到了 "geosite:cn" 这条规则里。

  • 你可能会疑问,那么 "geosite:geolocation-!cn" 里真的包括 gstaticadssl.l.google.com 这个域名吗?请查看 https://github.com/Loyalsoldier/v2ray-rules-dathttps://github.com/felixonmars/dnsmasq-china-list/blob/master/google.china.conf。 或者也可以把匹配 "geosite:cn" 对应的规则(第三条)注释掉。结果 log 里会返回:

    2021/07/08 03:13:24 127.0.0.1:40002 accepted udp:1.1.1.1:53 [dns-in -> dns-out]
    2021/07/08 03:13:24 DNS accepted udp:8.8.8.8:53 [xray.system.7bb52998-3961-4dfd-9701-ac4bfce71b3f -> proxy]
    2021/07/08 03:13:27 UDP:8.8.8.8:53 got answer: gstaticadssl.l.google.com -> [142.251.2.94] 2.514721509s
    
  • 那么证明了两个规则都匹配有结果,那么返回 114.114.114.114 的 dns 查询结果显然不符合预期 “无匹配时, 按从上往下的顺序进行查询” 这一行为。

  • 如果把第二条与第三条交换呢?情况并没有改变仍然是走 114.114.114.114

  • 那么到这问题就已经描述完了,如果想要自己复现,完整配置可见:https://pastebin.ubuntu.com/p/J5QssdyRKc/

这个功能是实现 xray dns 分流的关键功能,很多时候只利用 xray 强大的分流就可以达到很好的效果不需要什么第三方 dns 或者 clash的。 个人一直只是 xray stand-alone 使用,体验很好。相信很多人也依赖 *ray 的强大的 dns 模块实现各种功能。如果真的是 bug ,希望可以得到修复。(大猫猫贴贴!)

PS: 复现使用了 Loyalsoldier 的 geosite 库: https://github.com/Loyalsoldier/v2ray-rules-dat

@hmol233 hmol233 added bug Something isn't working documentation Improvements or additions to documentation labels Jul 8, 2021
@hmol233
Copy link
Contributor

hmol233 commented Jul 8, 2021

  • gstaticadssl.l.google.comgeosite:geolocation-!cn 中以 DomainMatcher 的形式出现 (full:gstaticadssl.l.google.com)
  • gstaticadssl.l.google.comgeosite:cn 中以 FullMatcher 的形式出现 (可能是 domain:google.com)
  • 在排序时,FullMatcher 的优先级高于 DomainMatcher
  • 🎉

@5page
Copy link
Author

5page commented Jul 8, 2021

* 在排序时,`FullMatcher` 的优先级高于 `DomainMatcher`

这样的话,现有的规则设置是不是无法实现 "geosite:geolocation-!cn"“geosite:cn” 优先匹配?

@galaxyskyknight
Copy link

galaxyskyknight commented Jul 11, 2021

这也是我很挠头的一个问题,别看有些谷歌服务在北京广州有服务器,还是很坑的,你不知道哪些谷歌域名或者ip被墙,哪些服务名称给解析到国内ip哪些又给解析到国外,楼上搞得规则也是我一直想折腾的,搞了半天没整明白,放弃了,geosite/geoip/geolocation还要配合domainstrategy, 头晕.....反正对我这种还不算小白都难以想明白的人,估计能想明白的也不多,另外吐下槽,这块不管是v2ray也好还是xray也好,用Json写的规则,太偏开发逻辑,在易用性和用户友好性方面反正我个人的观点是做的有点差了,太复杂了,底下逻辑可以这样实现,但json规则在配置层面搞得太复杂了,给用户就能不能用说人话的简洁明了的构建配置。个人观点,手下留情。

回到这个问题,我的实践就是吧谷歌所有的域名和ip通桶都通过doh/doT配置的dns解析到梯子所在国最快的国外ip,然后通过梯子代理服务访问,而不要走什么国内的太监版,走到国内的服务,又有一部分要跑国外,可能又访问不通,非常尴尬,我知道的至少有几个场景有问题,比如谷歌的搜索图片、谷歌的chrome账号登陆和同步,谷歌账号修改个人资料,这几个在用国内服务的时候配置不当(不知道是上面的bug还是配置问题)就会碰到点了没反应的情况,但我统统解析到国外ip用proxy访问,就没问题。多用点梯子的流量而已。而且用梯子访问,不会反向访问回回国内谷歌服务器,不会有对称流量被墙识别的风险。

@hmol233
Copy link
Contributor

hmol233 commented Jul 11, 2021

@5page

对于这类特殊的域名,单独写一个 FullMatcher 可以暂时解决。

例如:

"dns": {
        "hosts": {
            "snapchat.com": "127.0.0.2"
        },
        "servers": [
            "1.1.1.1",
            {
                "address": "8.8.8.8",
                "port": 53,
                "domains": [
                    "geosite:geolocation-!cn",
                    "full:gstaticadssl.l.google.com"
                ]
            },
            {
                "address": "114.114.114.114",
                "domains": [
                    "geosite:cn",
                    "full:gstaticadssl.l.google.com"
                ],
                "expectIPs": [
                    "geoip:cn"
                ]
            },
            {
                "address": "1.1.1.1",
                "port": 53,
                "domains": [
                    "geosite:speedtest"
                ]
            }
        ]
    },

@5page
Copy link
Author

5page commented Jul 11, 2021

* 在排序时,`FullMatcher` 的优先级高于 `DomainMatcher`

有点好奇如果 core 匹配时就干脆不不考虑 FullMatcherDomainMatcher 之间的优先级区别。是不就可以彻底解决这类问题?可能我不太了解这个设定的具体意义,但 FullMatcherDomainMatcher 有优先级区别有很重要的用处吗? 既然都是 matcher 那么 match 上了就可以了,优先级可以完全由先后顺序决定( 把决定权交给 config ),这样是不是会更简化了?感觉不管是 dns 还是 routing 模块都可以这样。

当然如果这个 FullMatcherDomainMatcher 的优先级区别如果有重要用途的话就没法这样做了。

hmol233 added a commit that referenced this issue Jul 11, 2021
@hmol233
Copy link
Contributor

hmol233 commented Jul 11, 2021

已在 1ced798 中修复此问题。
app/dns: domain gstaticadssl.l.google.com matches following rules: [geosite:geolocation-!cn(DNS idx:1) geosite:cn(DNS idx:2)]

@GeorgeRudd
Copy link

#1119 不知道是不是同样的问题。。

@yuhan6665
Copy link
Member

这个有机会还是要再看一下 还有 #1127

@yuhan6665 yuhan6665 reopened this Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

6 participants