Skip to content

Conversation

Fangliding
Copy link
Member

rt

@patterniha
Copy link
Collaborator

patterniha commented Aug 3, 2025

@Fangliding

this is right:

GlobalECHConfigCacheKey := ECHCacheKey(server, domain, sockopt)

but this is wrong:

serverKey := ECHCacheKey(server, domain, sockopt)

we should use the same httpClient for all domains, otherwise we have a saperate connection for each domain.
(for example in MitM-use we have hundreds of connections !!!)
also, in ip-DOH we create one connection for all domains.

///

i add three mode echForceQuery and append to this PR.

@Fangliding
Copy link
Member Author

Fangliding commented Aug 3, 2025

我改位置的时候复制错了而已 domain是置空的 注释都写了

@patterniha
Copy link
Collaborator

for cache and when err happen:
in full mode, no cache
in none mode, cache all error for default ttl time.
in half mode, only cache emptyResponse.

this is only for cache, and not complicated anything, and has no effect on echForceQuery behavior.

so please change Update function to:

echConfig, ttl, err := dnsQuery(server, domain, sockopt)
	if err != nil {
		if forceQuery == "full" || (forceQuery == "half" && errors.Cause(err) != dns2.ErrEmptyResponse) {
			return nil, err
		}
	}
	if ttl == 0 {
		ttl = dns2.DefaultTTL
	} 
	configRecord = &echConfigRecord{
		config: echConfig,
		expire: time.Now().Add(time.Duration(ttl) * time.Second),
		err:    err,
	}
	c.configRecord.Store(configRecord)
	return configRecord.config, configRecord.err


@patterniha
Copy link
Collaborator

also, config.go line 454 should be change to:
if c.EchForceQuery == "full" || (c.EchForceQuery == "half" && errors.Cause(err) != dns.ErrEmptyResponse) {

@Fangliding
Copy link
Member Author

好好的控制流为了你这个用法改来改去 我真后悔当初说xray可以mitm

@patterniha
Copy link
Collaborator

@Fangliding

if forceQuery == "none" || forceQuery == "" {

this is wrong! (you use cache for full mode !!!)

please change Update function(I mentioned above)

also if ttl==0 -> ttl should be defaultTTL.

@patterniha
Copy link
Collaborator

what???

so what is different between none and half mode???

@Fangliding Fangliding force-pushed the ECH branch 2 times, most recently from 7d7ba23 to 537c0d3 Compare August 3, 2025 08:43
@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding Ready 了说一声

@patterniha
Copy link
Collaborator

@RPRX

We agreed on everything except cache.

the if c.EchForceQuery != "none"

should be change to:

if c.EchForceQuery == "full" || (c.EchForceQuery == "half" && errors.Cause(err) != dns.ErrEmptyResponse) {

this is only for cache, and the connection is made regardless of type of error

///

in half mode, and when DNS fail, we cache all error for 5 minutes, So the problem was not solved for MitM

@Fangliding
Copy link
Member Author

@Fangliding Ready 了说一声

这样应该差不多了 给绕晕了

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@patterniha 你看一下现在的代码

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 现在的代码,"none" 和 "half" 除了第一次,会等查到 ECH 吗(希望不会)

@patterniha
Copy link
Collaborator

patterniha commented Aug 3, 2025

#4973 (comment)

this is the correct code, and is not complicated anything, and this is only for cache, and in none and half mode connection is made regardless of type of error.

@Fangliding
Copy link
Member Author

@Fangliding 现在的代码,"none" 和 "half" 除了第一次,会等查到 ECH 吗(希望不会)

会等查 稍微改一下应该就行了

@patterniha
Copy link
Collaborator

patterniha commented Aug 3, 2025

@RPRX

none-mode: for connecting as much as possible
full-mode: for connecting only with ech-TLS.
half-mode: for using in MitM case

so in half-mode we should use cache for emptyResponse, otherwise we have query for each request for non-ech domains.

so all things ok except:

if forceQuery != "none"
should be change to
if c.EchForceQuery == "full" || (c.EchForceQuery == "half" && errors.Cause(err) != dns.ErrEmptyResponse) {

and if ttl=0 ttl should change to defaultTTL

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

会等查 稍微改一下应该就行了

那等你弄好

@patterniha 给你 write access 了,如果 @Fangliding 改完你还有要改的,你直接改一下,然后让 @Fangliding 看看

@Fangliding
Copy link
Member Author

这回总都开心了吧 emptyresponse也是成功响应 half下非阻塞重试

@Fangliding
Copy link
Member Author

改了一下 full 遇到空响应一样炸 因为回复可能被污染

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

Ready 了吗,"none" 和 "full" 是我们需要的版本,"half" 是 @patterniha 需要的版本,@patterniha 你看下代码还有没有问题

@patterniha
Copy link
Collaborator

finally, @Fangliding find the best solution, thx. it is OK.

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 可以合了吗

@Fangliding
Copy link
Member Author

Fangliding commented Aug 3, 2025

test过了应该就没问题
none 尝试一次 五分钟或者ttl后再更新
half 尝试一次 失败后尝试更新 遇到空响应也是成功
full 只许成功 而且不许空响应
更新都是不阻塞的

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

none 尝试一次 五分钟或者ttl后再尝试

"none" 和 "half" 需要把 emptyResponse 原本的 TTL 扔了,遇到它就等五分钟再查

@Fangliding
Copy link
Member Author

Fangliding commented Aug 3, 2025

none 尝试一次 五分钟或者ttl后再尝试

"none" 和 "half" 需要把 emptyResponse 原本的 TTL 扔了,遇到它就等五分钟再查

none的ttl是说获取成功之后的ttl emptyResponse 无论如何都是300

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

600 不是十分钟吗,改成五分钟,我的意思就是别管它原本的 TTL,都五分钟,"half" 也是

@patterniha
Copy link
Collaborator

defaultTTL is 5 minutes.

@Fangliding code is correct.

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

那没事了,"half" 的 emptyResponse TTL 也是 300 吧

@Fangliding
Copy link
Member Author

我这么说可能清楚点
如果拿到了包含正确ECH响应的结果 那就尊重ttl
其他任何情况都是300

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

那没问题,终于可以合了

@RPRX

This comment was marked as resolved.

@Fangliding
Copy link
Member Author

在apply config那里转了 因为怕来自其他地方(特别是test)的空输入 就没在infra控制

@RPRX RPRX changed the title 恢复先前的forcequery行为 TLS ECH client: echForceQuery "full" / "half" / "none" (default) Aug 3, 2025
@RPRX RPRX merged commit 7cbf5b0 into main Aug 3, 2025
78 checks passed
@RPRX RPRX deleted the ECH branch August 3, 2025 10:15
@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 更新一下 ECH 和 tunnel 的文档(直接把 dokodemo-door.html 重命名为 tunnel),完成 ECH 后我把 pre 改为 latest

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 分成两个 commit 吧,先更新 ECH 的

tunnel 入站侧边栏没改,就 tunnel.md 不用带 dokodemo,加一下 portMap 的配置

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

Tunnel(隧道),旧称 dokodemo-door(任意门)

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 查看 XTLS/Xray-docs-next@179851f ,有四处需要修改

根配置 version 也加一下吧

@Fangliding
Copy link
Member Author

侧边栏是跟标题的 我觉得侧边栏就这样吧 反正其他的也不是没有括号

@Fangliding
Copy link
Member Author

version 你们弄的时候我没看 我觉得最好挪到 outbound 去 因为share link定义的是单个outbound

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

version 你们弄的时候我没看 我觉得最好挪到 outbound 去 因为share link定义的是单个outbound

我想的是订阅不止 outbound,还有路由啥的,先加到 root

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

侧边栏是跟标题的 我觉得侧边栏就这样吧 反正其他的也不是没有括号

那我说错了,是那个页面显示的文字那里没改成 Tunnel,你再看一下


标题改为 Tunnel(dokodemo-door),注意汉字括号、大小写


Tunnel(隧道),旧称 dokodemo-door(任意门)可以监听一个本地端口,并把所有进入此端口的数据通过 outbound 发送至指定服务器的一个端口,从而达到端口映射的效果。

Tunnel(隧道),旧称 dokodemo-door(任意门),可以监听数个本地端口,并把所有收到的数据通过 outbound 发送至指定服务器的某个端口,从而达到端口映射的效果。


当 followRedirect(见下文)为 true 时,address 可为空。

这句可以删了

@RPRX
Copy link
Member

RPRX commented Aug 3, 2025

@Fangliding 对了,原先的 dokodemo.md 需要做一个 link,参考现在的 tcp.md

我指的是这里 https://xtls.github.io/config/inbounds/ 没更新,复制粘贴 Tunnel (dokodemo-door)这下中英文空格对齐了

@patterniha
Copy link
Collaborator

Well, in silence, I have been granted maintenance permission.

FUN:

Now, I can close @Fangliding open PRs to get revenge for the times he closed my PRs without reason :)

FACT:

If it weren't for @Fangliding harshness, I wouldn't be a member of Project X now and I owe a lot of my progress to him.

Although sometimes...

@Fangliding
Copy link
Member Author

Fangliding commented Aug 4, 2025

enjoy that, I won't waste my time on your things anymore

maoxikun pushed a commit to maoxikun/Xray-core that referenced this pull request Aug 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants