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

ECH: Support TLS Encrypted Client Hello #3813

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

ECH: Support TLS Encrypted Client Hello #3813

wants to merge 8 commits into from

Conversation

Fangliding
Copy link
Member

@Fangliding Fangliding commented Sep 15, 2024

仅客户端
才发现go1.23官方已经支持了 之前写过的那堆复杂替换也不需要了 就正常写入就行了 ws和splithttp预计都能使用cloudflare的ECH
目前是写死的 稍后可以考虑从DNS中获取 已经测试可以和singbox与cloudflare建立ECH连接
写法

{
    "protocol": "trojan",
    "settings": {
        "servers": [
            {
                "address": "xxx",
                "port": 8080,
                "password": "password"
            }
        ]
    },
    "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
            "serverName": "xxx",
            "echConfig": "AFj+DQBUAAAgACAJSBrX4ZNnpgYFsaF+sUabAbsO+y2Bs61D6nmHEw7dRgAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAAV4LmNvbQAA",
            "echDohServer": "https://1.1.1.1/dns-query",
            "alpn": [
                "h2",
                "http/1.1"
            ]
        }
    },
    "tag": "proxy"
}

@Fangliding
Copy link
Member Author

有一个最大的问题是utls是go121的似乎 现在还不支持 遥遥落后了

@RPRX
Copy link
Member

RPRX commented Sep 15, 2024

有一个最大的问题是utls是go121的似乎 现在还不支持 遥遥落后了

Win7 编译也需要 go121,所以等 2025 再加这个吧,至少得 utls 支持,而且感觉无法通过本地 dns 拿到 echConfig 的话有点鸡肋

最大的问题还是 GFW 又会严控 DNS 了

@Fangliding
Copy link
Member Author

有一个最大的问题是utls是go121的似乎 现在还不支持 遥遥落后了

Win7 编译也需要 go121,所以等 2025 再加这个吧,至少得 utls 支持,而且感觉无法通过本地 dns 拿到 echConfig 的话有点鸡肋

这点我考虑过了 稍后可以加build tag绕过低版本go 就像隔壁一样

至于utls 等它支持了 核心改两行代码就能跟上了 目前这个实验性功能应该没有什么坏处

最大的问题还是 GFW 又会严控 DNS 了

在配置里加一个可选的doh服务器用于获取解析? 或者尝试写死 观察一段时间 不知道CF这个ECH config是不是轮动的 如果不是的话写死也能接受

@RPRX
Copy link
Member

RPRX commented Sep 15, 2024

先写一下通过 dns 获取 echConfig,然后等 utls 支持了再合这个 pr 吧,其实仅用 utls 的话可能 Win7 也能用?

@Fangliding
Copy link
Member Author

先写一下通过 dns 获取 echConfig,然后等 utls 支持了再合这个 pr 吧,其实仅用 utls 的话可能 Win7 也能用?

有一个小问题是内置DNS服务器只能处理A和AAAA 这个要再加就得外置
utls更新不知道猴年马月了 他们撮了个李鬼ech 这估计还得修改一部分才能兼容 而且开发好像没那么活跃 上次commit两个月前 这边合着测试一下大概问题不大?

@Fangliding
Copy link
Member Author

好了 现在支持 "echDohServer": "https://1.1.1.1/dns-query" 这样的方法代替echConfig了 设置了600秒TTL缓存 要求设置 serverName(不然去查谁呢)

@Fangliding
Copy link
Member Author

好了已经通过测试 websocket可以设置doh sever然后通过ECH连接到cloudflare
splithttp和grpc大概也是可以的

@yuhan6665
Copy link
Member

看了一下非常棒!建议及早合并

@yuhan6665 yuhan6665 changed the title 尝试支持 TLS Encrypted Client Hello ECH: client support TLS Encrypted Client Hello Sep 16, 2024
@dyhkwong
Copy link
Contributor

dyhkwong commented Sep 26, 2024

既然这个在 v2fly 和这里都开了并且不是 draft、没有进一步行动,那么:

  • mutex 用错
  • ServerName 用错,为什么不用 *tls.Config 的?(e.g. sni 不填,服务器地址是域名)
  • proto 里的 ech_config 类型可以为 bytes
  • 根据 RFC,DoH 的 message id “应该”为 0
  • 能用正常方法读取的为什么要用正则表达式去读取?
for _, answer := range msg.Answer {
	if https, ok := answer.(*dns.HTTPS); ok && https.Hdr.Name == dns.Fqdn(domain) {
		for _, v := range https.Value {
			if echConfig, ok := v.(*dns.SVCBECHConfig); ok {
				return echConfig.ECH, answer.Header().Ttl, nil
			}
		}
	}
}
  • 完全没有 context 管理

建议重写或转 draft

@Fangliding
Copy link
Member Author

@dyhkwong 感谢指正 有的问题我也知道不过没打算合我也没动了 等会改一下

不过有必要ctx吗 log里用Background的原因是GetTLSConfig这个函数就没有ctx 至于内部管理 我想这么简单大概没有必要?

@RPRX
Copy link
Member

RPRX commented Oct 2, 2024

隔壁咋已经合了,就是说现在没 uTLS 支持不会觉得很鸡肋吗,等待 uTLS 更新

@Fangliding
Copy link
Member Author

Fangliding commented Feb 8, 2025

稍微更新了一下 以便可能有人需要

区别 rebase到最新的commit 理论上可以支持XHTTP(3)

删除win7不支持的警告 由于使用魔改go而不是旧版本所以可以正常使用

proto文件让位到20 避免跟目前在开发的mitm功能撞车 顺便mitm功能可以扩展到接管所有被墙的CF网站(通过ECH)

@Fangliding
Copy link
Member Author

Fangliding commented Feb 8, 2025

稍微挂个简单点的测试
curl http://crypto.cloudflare.com:443/cdn-cgi/trace --resolv crypto.cloudflare.com:443:127.0.0.1 可以看到 sni=encrypted

{
    "log": {
        "loglevel": "debug"
    },
    "inbounds": [
        {
            "port": 443,
            "listen": "127.0.0.1",
            "tag": "in",
            "protocol": "dokodemo-door",
            "settings": {
                "address": "crypto.cloudflare.com",
                "port": 443,
                "network": "tcp"
            }
        }
    ],
    "outbounds": [
        {
            "tag": "tls-repack",
            "protocol": "freedom",
            "streamSettings": {
                "security": "tls",
                "tlsSettings": {
                    "serverName": "crypto.cloudflare.com",
                    "fingerprint": "unsafe",
                    "echDohServer": "fimtale.com+https://1.1.1.1/dns-query",
                    "alpn": [
                        "http/1.1"
                    ]
                }
            }
        }
    ]
}

@RPRX
Copy link
Member

RPRX commented Feb 9, 2025

utls 指纹差不多就是模板 但是kyber毕竟涉及到握手流程 这个不能发假的得真实现 有点难 至于基于gotls的模板的模板。。支持这样搞吗 得修改tls库吧

等 Chrome 默认发 X25519MLKEM768 了就能搞

不是基于 gotls,是基于 REALITY 仓库

@Fangliding
Copy link
Member Author

等 Chrome 默认发 X25519MLKEM768 了就能搞

早就是了

不是基于 gotls,是基于 REALITY 仓库

那得看了

@yuhan6665
Copy link
Member

BTW we have the new research fellow taking over UTLS (thank god Trump cannot/haven't layoff this project)
You two knows quite a lot about fingerprint, we can make suggestions to Mingye Chen if you see fit.

@Fangliding
Copy link
Member Author

能复更是最好的 能把新版chrome做一下再支持一下ech就行了(

@RPRX
Copy link
Member

RPRX commented Feb 25, 2025

等待 refraction-networking/utls#322

@Fangliding
Copy link
Member Author

和这个没关系 要等也是等它的chrome支持ech 现在只有 hellogolang的

@RPRX
Copy link
Member

RPRX commented Feb 25, 2025

意思就是等 uTLS 更新 Chrome 指纹并更新 ECH 功能

@RPRX
Copy link
Member

RPRX commented Feb 25, 2025

话说等 uTLS 更新带抗量子的指纹后 REALITY 也要更新了,现在 CF 服务端默认提供抗量子的密钥交换算法吗

@Fangliding
Copy link
Member Author

1.24新加了服务端支持 到时候可以考虑一下

@Fangliding
Copy link
Member Author

新增了服务端支持 服务端key和sb是一个格式 因为两边变量名命名不是很负责任 中间踩了一些坑 最后分开去看实现才弄明白 xray这个ech key生成某种意义上是错的 就改掉了 也许当初就不该在支持ECH前提前加这玩意 走了些弯路

@Fangliding Fangliding changed the title ECH: client support TLS Encrypted Client Hello ECH: Support TLS Encrypted Client Hello Mar 1, 2025
@RPRX
Copy link
Member

RPRX commented Mar 2, 2025

uTLS 最新 commit 更新到 Go 1.24 了,不过不确定它的 Chrome 指纹是否带真正的 ECH 功能了,你研究下?

@RPRX
Copy link
Member

RPRX commented Mar 2, 2025

要不你给 Chrome 指纹弄个真正的 ECH,PR 给 uTLS 吧,应该没啥难度

@Fangliding
Copy link
Member Author

挺麻烦的说实话 有一些问题 而且我试过强行打开但是被reject了 估计还涉及到client hello的构建

@RPRX
Copy link
Member

RPRX commented Mar 2, 2025

ECH 不就是把真正的 CH 给加密了放扩展,然后外面的是假的吗,照这个流程来就行

我现在挺想合了 ECH,但是没 uTLS 支持的话就很鸡肋,而且我感觉那边一时半会儿也加不上,可能在等人 PR

@RPRX
Copy link
Member

RPRX commented Mar 2, 2025

换句话说就是可能没人 PR 的话一直都不会有

它那 hellogolang 有 ECH 的话参考一下就行,主要在于两个 CH,且后续握手流程用被加密的那个 CH

@Fangliding
Copy link
Member Author

Fangliding commented Mar 2, 2025

比这麻烦 自己impl还算说得轻巧的 但是utls首先config和构建出的hello msg是分开的 然后还得根据 outer hello 构建 inner hello 还得分开处理服务端和outer/inner握手的情况 标准库实现utls的一些操作又和utls本身的做法是冲突 就很 嗯。。 我遇到的这个问题大概是它模仿出来的client hello在加密成 inner hello 的时候不符合啥构建标准了
总的来说这本身就是一个不太好实现的侵入性比较大的扩展(它现在还卡在draft而不是RFC) 又和侵入性比较大的utls碰一起就强强对决了

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.

4 participants