-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Proposal for amending domain matching logic #92
Comments
先阐述一下当前Domain Matcher的匹配过程:
其中:
|
参考 v2fly/domain-list-community#91 (comment) 中的配置:
现在可以解释Issue中现象出现的原因了:
以上十分需要注意的是,
因此若在
|
修正方法提案综合以上描述,可以总结出当前的域名匹配的两个重要特征: 因此修正方案有以下两个方向: 返回最先匹配的记录,保留最先插入的记录这个方案直接解决了 v2fly/domain-list-community#91 (comment) 中的问题,同时改动极小(大约三行),也即当新记录插入时,若结点上已有记录,则抛弃新记录。 返回所有匹配的记录,保留所有插入的记录这个方案改变 这个方案的优点:
这个方案的缺点:
两种方案都会引入对DNS匹配规则的breaking change(虽然大概很少会有人利用后插入的优先匹配这个feature/bug)。 |
在本机上,原版实现与修改实现(返回所有记录)的Benchmark
原版实现
修改后实现
|
@Vigilans 哆啦 A 梦 😄 🎉 |
首先,路由应该设定是顺序匹配。 |
I think you should file a PR. |
@Loyalsoldier I've created a PR adopting the second choice: preserving and returning array of all matches. Yesterday I purposely kept back my PR in order not to incline towards any of the two choices in this issue. |
@Vigilans Excellent job! 🎉 |
Domain Matcher还存在另外一个问题。在添加结点的代码中: v2ray-core/common/strmatcher/domain_matcher.go Lines 28 to 31 in 8b4ba03
不太清最初的设计目的是什么,这段代码使得域名级数最少的优先匹配,而其他级数多的甚至不会加入进Trie树中。也即尝试往DomainMatcher中添加以下三条规则时:
只有 实际使用中,一般是对于一级域名使用一种通用规则,再对某些特定的二级及以上的域名设置更细致的规则。按这种模式一种修正方法是:
|
"dns": {
"servers": [
{
"address": "https+local://dns.alidns.com/dns-query",
"domains": [
"regex:apis\\.us$",
"keyword:apis",
"domain:googleapis.com",
"domain:com",
"full:www.baidu.com"
]
},
{
"address": "https://1.1.1.1/dns-query",
"domains": [
"keyword:apis",
"domain:googleapis.com",
"full:fonts.googleapis.com",
"full:www.baidu.com",
"domain:example.com"
]
}
]
} 做完以上修改后,DNS 匹配逻辑是不是下面这样? 总体优先级由上到下,且 使用上面的 DNS JSON 配置,
|
@Loyalsoldier 命中的 DNS 在所有命中结果全部查询失败后,则再从最上面的 DNS 重新开始查起。 我按你的配置写了测试代码,打印了一下匹配的中间过程,结果如下(Matcher 的标号与参考的 DNS JSON 配置一一对应,可以参照查阅标号对应的原 Matcher 的内容):
可以看到 DNS 的优先级匹配行为与你的描述一致。 一个值得注意的现象是,由于两个 DNS 各自都设置了匹配范围相互覆盖的 Matcher,因此在 Matched DNS 中常常出现一个 DNS 被反复匹配的现象。这可能会导致该 DNS 在 Priority Matching 过程中被反复查询(如果前面的查询失败的话)。 个人认为这个行为可以保留,不需要修正,原因是:
|
想问一下,在 debug 级别的 log 中打印上面这个匹配流程,是否容易实现?这样的话,就不需要用户猜了。如果需要大改的话,就算了。 |
@Loyalsoldier 只打印标号的话,打印后两个总匹配结果很容易,前几个分Matcher的不太好打印,一方面是Match函数没有接收Context,另一方面是潜在的性能问题。 后两个在打印标号的基础上,要再打印名字等信息的话,打印最后一个DNS信息改动很小,打印Matcher信息稍微要加点东西。 |
那只打印 Matcher result 和 Matched DNS 的话,应该可以同时打印具体匹配到的规则的文本吧?如果只打印标号的话,意义不是很大。 |
@Loyalsoldier 应该可以。在上面的测试结果里面发现了另一个小BUG(新PR里面少删了一行……),修正后把上面的测试结果更新了一下,并且手动添加了标号与原规则内容的映射,你可以看一下。 关于debug log里面的文本格式,你觉得该如何设置?我大概想了两种方案:
|
line 1: line 2: line 3: |
@Loyalsoldier 我试着实现了一下,line 2没有什么问题,line 1有一些问题:
总体来看,目前有三个选择:
Edit: 有个方案或许可以少一些Trivial改动,我试着写出来发个Draft PR看看 |
line 1已经存在
如果日志中要打印DNS规则匹配流程,是否也应该打印路由规则匹配流程? |
@Robot-DaneelOlivaw 在 #98 里实现了Log,line 2还是保留了下来,因为知道匹配了哪些规则和知道将用哪些DNS查询应该算是不同的需求,大多数人可能也比较关心后者。不过line 2的idx没有打印,因为line 1和line 2数组元素是一一对应的,确实没必要重复标识。
对于这个,我看了下原日志的打印代码,这种
路由和DNS虽然都有域名匹配,也都用了DomainMatcher,不过使用方式并不一样。支持打印DNS的匹配日志都花费了一些功夫,还有其他模块的路由可能会让事情更复杂一些。不过把DNS这边的Contribution清完后,个人再下一个计划看的就是路由了…… |
当前V2Ray版本
4.27.0
使用场景
域名匹配(路由、DNS)
看到的不正常的现象是什么?
这个Issue由 v2fly/domain-list-community#91 (comment) 中的现象引出:
The text was updated successfully, but these errors were encountered: