curl ECH 支持实战指南:基于 DoH 与 --ech 选项实现 Encrypted Client Hello
本文以 curl 仓库中的 docs/ECH.md 为主体,完整讲解如何在 curl 中构建并启用 ECH(Encrypted Client Hello)支持:涵盖 OpenSSL/BoringSSL/wolfSSL 三种 TLS 后端的编译方法、--ech 命令行选项的六种取值、ECHConfigList 的获取与注入方式、默认配置策略,以及结合 lib/vtls/openssl.c、lib/vdns/doh.c、lib/setopt.c 等源码的底层实现链路。读完本文,你可以复现 curl 的 ECH 实验性构建,理解其 “DoH 拉取 HTTPS RR → DNS 缓存 → TLS 握手喂入 OpenSSL” 的完整数据通路。
需要特别强调文档中的原始声明:此功能为 EXPERIMENTAL(实验性),切勿用于生产环境。它的定位是一个“足以引发 ECH 在 curl 中长期方案讨论的概念验证(proof-of-concept)”,可配合 AWS-LC、BoringSSL、OpenSSL、Rustls 或 wolfSSL 作为 TLS 提供方工作。
ECH 在 curl 中的两条配置路径
ECH 要加密 TLS ClientHello,前提是先拿到服务器的 ECHConfigList。curl 目前提供两条获取路径:
- 通过 DoH 自动获取:curl 本就支持用 DoH 做 A/AAAA 解析,因此顺带扩展了在同一 DoH 请求中拉取 HTTPS RR(SVCB/HTTPS 类型记录)中
ech=标签的能力。只要配置了 DoH URL,--ech true即可工作; - 命令行直接提供:用
--ech ecl:<b64value>把 base64 编码的 ECHConfigList 直接贴在命令行上,绕开 DNS。这条路径的价值在于:它可用于在 ECHConfigList 尚未发布到 DNS 之前的测试与部署验证阶段。
两条路径共同依赖一个约束:ECH 只在 TLS 1.3 上工作,且要求构建时开启 ECH 开关(USE_ECH)。
构建:autotools 与 CMake 两条路线
OpenSSL 后端 + autotools
文档给出的标准流程是:先构建 ECH-enabled 的 OpenSSL(4.0.0+),再基于它构建 curl:
# 1. 构建 ECH-enabled OpenSSL(浅克隆 openssl 源码后)
cd $HOME/code
git clone --depth 1 --branch openssl-4.0.0 <openssl 源码仓库>
cd openssl
./config --libdir=lib --prefix=$HOME/code/openssl-local-inst
make -j8
make install_sw
# 2. 构建启用 ECH 的 curl
cd $HOME/code
git clone --depth 1 <curl 源码仓库>
cd curl
autoreconf -fi
LDFLAGS="-Wl,-rpath,$HOME/code/openssl-local-inst/lib/" ./configure --with-ssl=$HOME/code/openssl-local-inst --enable-ech
make
验证要点:configure 输出结尾必须出现如下警告,否则说明 ECH 没有真正启用,需要回查步骤:
WARNING: ECH is enabled but marked EXPERIMENTAL...
如果需要调试 curl 本体,可在 configure 中追加 --enable-debug。
文档还记录了一个真实的构建坑:某次 2024-05-20 的构建中,configure 找不到 ECH-enabled 的 SSL 库,排查发现与 $HOME/code/openssl-local-inst/lib/pkgconfig 目录的存在有关,删除该目录后问题消失——这提示在自定义 --prefix 安装 OpenSSL 时,pkgconfig 残留可能干扰 curl 的能力探测。
对应到仓库源码,autotools 路径的开关逻辑在 configure.ac:--enable-ech 打开后,用 AC_CHECK_FUNCS(SSL_set1_ech_config_list, ...) 探测 TLS 库是否具备 ECH API,探测成功才定义 USE_ECH,否则报错 --enable-ech ignored: No ECH support found。
CMake 构建
CMake 路线更简洁,同样假设 ECH-enabled OpenSSL 已就绪:
cd $HOME/code
git clone --depth 1 <curl 源码仓库>
cd curl
mkdir build
cd build
cmake -DOPENSSL_ROOT_DIR=$HOME/code/openssl -DUSE_ECH=1 ..
make
# [100%] Built target curl
一个实用细节:CMake 构建出的二进制不需要任何 ECH 相关的 LD_LIBRARY_PATH 设置(autotools 路线则往往需要,见下文“默认设置”一节的陷阱)。
CMake 侧的实现在 CMakeLists.txt:USE_ECH 选项默认 OFF,开启后依次验证 TLS 后端(OpenSSL/wolfSSL/Rustls)、用 curl_openssl_check_exists("SSL_set1_ech_config_list" ...) 确认 API 存在,随后强制连带打开 USE_HTTPSRR,并打印 ECH enabled / HTTPSRR enabled 状态。
BoringSSL 后端
BoringSSL 同样支持 ECH,构建方式(省略外部仓库地址):
cd $HOME/code
git clone --depth 1 <boringssl 源码仓库>
cd boringssl
cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/code/boringssl/inst -DBUILD_SHARED_LIBS=1
make
make install
然后构建 curl:
cd $HOME/code
git clone --depth 1 <curl 源码仓库>
cd curl
autoreconf -fi
LDFLAGS="-Wl,-rpath,$HOME/code/boringssl/inst/lib" ./configure --with-ssl=$HOME/code/boringssl/inst --enable-ech
make
成功时同样应看到实验性警告(BoringSSL 下措辞略不同):
WARNING: ECH HTTPSRR enabled but marked EXPERIMENTAL. Use with caution.
由于 AWS-LC/BoringSSL 的 ECH API 与 ECH-enabled OpenSSL fork 非常接近,代码改动同样落在 lib/vtls/openssl.c 中,通过 #ifdef OPENSSL_IS_BORINGSSL 保护的分支实现,大多是 API 的等价替换。注意限制:AWS-LC/BoringSSL 目前不支持 --ech pn: 命令行变体。
wolfSSL 后端
cd $HOME/code
git clone --depth 1 <wolfssl 源码仓库>
cd wolfssl
./autogen.sh
./configure --prefix=$HOME/code/wolfssl/inst --enable-ech --enable-debug --enable-opensslextra
make
make install
其中安装前缀(inst)是必须的,否则 curl 的 configure 探测不顺利;而 --enable-opensslextra 经过反复尝试后确认是必需的,缺失会导致 curl 构建出问题。
接着构建 curl:
cd $HOME/code
git clone --depth 1 <curl 源码仓库>
cd curl
autoreconf -fi
./configure --with-wolfssl=$HOME/code/wolfssl/inst --enable-ech
make
wolfSSL 后端的 ECH 实现有已知问题(原文档列出的上游问题,此处不复述外部链接):
- HelloRetryRequest(HRR)处理不正确:导致客户端无法访问强制 HRR 的 ECH 测试站点(如
tls-ech.dev); - 中间盒兼容模式(middlebox compatibility mode)相关缺陷同样存在。
wolfSSL 与 OpenSSL 路线还有一些“怪异的差异”,来自实际踩坑记录:
.curlrc中的 DoH URL 在 OpenSSL 下可以直接写1.1.1.1,wolfSSL 下则必须写one.one.one.one(后者对两者都可用,所以统一用它);- CA 数据库差异:wolfSSL 版本不喜欢
defo.ie的证书,可用--insecure/-k绕过(真实部署则必须解决)。
wolfSSL 侧的源码改动包括:configure.ac 中新增 wolfSSL 是否具备 ECH 的探测;在 lib/vtls/wolfssl.c 中新增与 OpenSSL 版本镜像的 ECH 代码。功能差异上,wolfSSL 不支持 --ech false,也不支持 --ech pn:。不支持 --ech false 的根因在于 wolfSSL 的设计决策:只要以 ECH 方式构建,就总是至少发送 GREASE 扩展——即对 wolfSSL 来说 GREASE 是编译期选择,而对 OpenSSL / AWS-LC / BoringSSL 来说是运行期选择(两种设计都合理)。
--ech <config> 选项全解
--ech 选项自 curl 8.8.0 引入,属于 TLS 分类,仅对 HTTPS 协议生效(见 docs/cmdline-opts/ech.md)。完整取值如下:
| 取值 | 行为 | 失败语义 |
|---|---|---|
false |
不尝试 ECH(默认值) | — |
grease |
发送 GREASE 占位 ECH 扩展 | 永不失败 |
true |
尽量尝试 ECH | 尝试未果不失败;但一旦真正发起 ECH 而解密失败则连接失败 |
hard |
必须成功发起 ECH | 无法尝试(如 DNS 中找不到 ECHConfig)即硬失败 |
ecl:<b64value> |
使用给定的 base64 ECHConfigList 而非来自 DNS | 配合 ECH 尝试逻辑 |
pn:<name> |
覆盖 ECHConfigList 中的 public_name 字段(仅 OpenSSL 后端可用) |
— |
一个容易混淆的点(原文档专门强调):所谓“attempt ECH”指客户端发出带“真实” ECH 扩展的 TLS ClientHello,并不意味着服务器一定能成功解密——解密还可能因其它原因失败。
源码视角:选项如何落到内部状态
选项解析实现在 lib/setopt.c 的 setopt_ech()(受 #ifdef USE_ECH 保护,未启用 ECH 构建时整个函数退化为 CURLE_NOT_BUILT_IN):
static CURLcode setopt_ech(struct Curl_easy *data, const char *ptr)
{
...
if(!ptr || !strcmp(ptr, "false"))
s->tls_ech = CURLECH_DISABLE;
else {
...
if(!strcmp(ptr, "grease"))
s->tls_ech = CURLECH_GREASE;
else if(!strcmp(ptr, "true"))
s->tls_ech = CURLECH_ENABLE;
else if(!strcmp(ptr, "hard"))
s->tls_ech = CURLECH_HARD;
else if(plen > 4 && !strncmp(ptr, "ecl:", 4)) {
if(!s->tls_ech)
s->tls_ech = CURLECH_HARD; /* 给出 ecl: 但未显式指定模式时,默认 hard */
result = Curl_setstropt(data, STRING_ECH_CONFIG, ptr + 4);
}
else if(plen > 3 && !strncmp(ptr, "pn:", 3)) {
if(!s->tls_ech)
s->tls_ech = CURLECH_HARD;
result = Curl_setstropt(data, STRING_ECH_PUBLIC, ptr + 3);
}
else
result = CURLE_BAD_FUNCTION_ARGUMENT;
}
...
}
从源码结构看有三个值得注意的细节:
- 字符串被映射为
CURLECH_DISABLE/CURLECH_GREASE/CURLECH_ENABLE/CURLECH_HARD四态枚举,存储在data->set.tls_ech; - 单独使用
ecl:或pn:而未显式指定true/hard时,内部默认按CURLECH_HARD处理,即“给了配置列表就应当严格尝试”; ecl:后的 base64 串存入STRING_ECH_CONFIG,pn:后的名字存入STRING_ECH_PUBLIC,二者在 TLS 握手阶段才被消费。
错误语义方面,绝大多数 ECH 相关错误会映射为 CURLE_ECH_REQUIRED(错误码 101),这在后文的错误示例中可以看到。
ECH + DoH:完整工作流
curl 支持用 DoH 做 A/AAAA 查找,因此在其上拉取 HTTPS RR 相当自然。典型用法:
cd $HOME/code/curl
LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl --ech true \
--doh-url https://one.one.one.one/dns-query \
https://defo.ie/ech-check.php
一切正常时,响应 HTML 中会包含(这是 defo.ie 测试页回显的握手状态):
SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
原文档验证过以下测试站点(覆盖 4 种不同服务器技术、3 方实现,其中含一个强制 HRR 的 8414 端口场景):
https://defo.ie/ech-check.php
https://crypto.cloudflare.com/cdn-cgi/trace
https://tls-ech.dev/
非 443 端口的场景也受支持:按 SVCB/HTTPS 规范,目标端口不是 443 时,DoH 查询的 qname 会被相应改写,保证取到对应端口的 HTTPS RR。
命令行直接提供 ECHConfigList
不依赖 DoH 时,可以 dig 拿到 HTTPS RR 中的 ech= 值并粘贴回命令行:
dig +short https defo.ie
1 . ipv4hint=213.108.108.101 ech=AED+DQA8PAAgACD8WhlS7VwEt5bf3lekhHvXrQBGDrZh03n/LsNtAodbUAAEAAEAAQANY292ZXIuZGVmby5pZQAA
ipv6hint=2a00:c6c0:0:116:5::10
然后:
LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl --ech ecl:AED+DQA8PAAgACD8WhlS7VwEt5bf3lekhHvXrQBGDrZh03n/LsNtAodbUAAEAAEAAQANY292ZXIuZGVmby5pZQAA \
https://defo.ie/ech-check.php
# ...
# SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
配置列表过期与 retry_configs
注意 ECHConfigList 可能频繁轮换(defo.ie 的每小时变化)。粘贴了过期值时,-vvv 下会看到硬失败错误:
LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl -vvv --ech ecl:AED+DQA8yAAgACDRMQo+qYNsNRNj+vfuQfFIkrrUFmM4vogucxKj/4nzYgAEAAEAAQANY292ZXIuZGVmby5pZQAA \
https://defo.ie/ech-check.php
...
* OpenSSL/3.3.0: error:0A00054B:SSL routines::ech required
...
好消息是:贴错 ECHConfigList 时,服务器可以通过 TLS 层的 retry_configs 机制回发正确值,curl 会把它打印在 verbose 输出里:
...
* ECH: retry_configs AQD+DQA8DAAgACBvYqJy+Hgk33wh/ZLBzKSPgwxeop7gvojQzfASq7zeZQAEAAEAAQANY292ZXIuZGVmby5pZQAA/g0APEMAIAAgXkT5r4cYs8z19q5rdittyIX
8gfQ3ENW4wj1fVoiJZBoABAABAAEADWNvdmVyLmRlZm8uaWUAAP4NADw2ACAAINXSE9EdXzEQIJZA7vpwCIQsWqsFohZARXChgPsnfI1kAAQAAQABAA1jb3Zlci5kZWZvLmllAAD+DQA8c
QAgACASeiD5F+UoSnVoHvA2l1EifUVMFtbVZ76xwDqmMPraHQAEAAEAAQANY292ZXIuZGVmby5pZQAA
* ECH: retry_configs for defo.ie from cover.defo.ie, 319
...
此时可以复制该 base64 值重试。当前限制:retry_configs 的读取只对 OpenSSL 与 AWS-LC/BoringSSL 构建可用(wolfSSL 缺少对应 API)。并且目前 curl 还没有实现 retry_configs 的自动化二次握手——对命令行工具,可行的替代手段是:用 dig/kdig 重新取 HTTPS RR 后手动传 ecl:,或从上一轮的 verbose 输出里提取 retry_configs 值再发起一次请求。
retry_configs 的源码位置在 lib/vtls/openssl.c 的 ossl_trace_ech_retry_configs():先尝试新 API SSL_ech_get1_retry_config(),再回退到旧 API SSL_get0_ech_retry_configs(),并同步读取 ECH 状态与内外层 SNI 名用于日志。
默认设置:.curlrc 与环境变量的配合
curl 支持用 ~/.curlrc 固化默认参数,因此可以把 DoH 与 ECH 一起设为长期默认:
cat ~/.curlrc
doh-url=https://one.one.one.one/dns-query
silent
ech=true
配套注意事项(均来自原文档的踩坑记录):
- 如果系统自带的 curl 读到了含
ech的.curlrc,会警告ech是未知选项。加入silent行可压掉这类噪音,但需注意:另有脚本可能依赖非静默行为,取舍需自行判断。文档还提到历史上用silent=TRUE,但最新构建中该写法反而会“毒化”后续配置行(使后续行被忽略),因此改用裸silent。 - 若想长期指向自编译的 OpenSSL,可
export LD_LIBRARY_PATH=$HOME/code/openssl。副作用是部分程序会检测到 OpenSSL 版本不匹配,例如git push报OpenSSL version mismatch. Built against 30000080, you have 30200000——执行git push前先unset LD_LIBRARY_PATH或换用另一个 shell。
配置就绪后命令行即可简化到最简形式:
./src/curl https://defo.ie/ech-check.php
# ...
# SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
为什么默认建议 --ech true 而不是 hard:true 是机会主义的——尝试 ECH,但若客户端找不到任何 ECHConfig 值则不失败;hard 在 DNS 中没有 ECHConfig 时直接硬失败,因此现阶段不适合作为默认值。但要注意两者的共同底线:一旦客户端真正发起了 ECH,而服务端解密失败,连接就会失败。
源码实现走读:从 DNS 到 TLS 握手
编译开关的双宏设计
ECH 相关代码由两个宏分别保护(docs/ECH.md 原文如此说明):
USE_HTTPSRR:HTTPS RR 的拉取与存储代码。这部分具有通用性——将来即使没有 ECH,HTTPS RR 中的 ALPN 值(alpn=)或 IP 地址提示(ipv4hint=/ipv6hint=)也有独立用途;USE_ECH:ECH 专有逻辑。
二者通过 configure.ac / CMakeLists.txt 可分别启停,但规则是:启用 USE_ECH 会强制启用 USE_HTTPSRR,且两者都要求 CURL_DISABLE_DOH 不得开启(原文档调侃道:“对于执着的人,仍可能存在一些能自相矛盾的构建组合 :-)”)。
DoH 侧:复用 dohprobe 拉取 HTTPS RR
文档指出主要新增代码在 lib/doh.c(现仓库中位于 lib/vdns/doh.c):
- 复用现有的
dohprobe()机制,在同一次 DoH 查询里请求目标域名的 HTTPS RR; - 取到值后由新增的
doh_store_https()函数存入dohentry结构的新字段——该函数现位于 lib/vdns/doh.c; - DoH 流程走通后,
Curl_doh_take_result()会顺带把 HTTPS RR 数据通过Curl_dns_entry结构返回,供后续 TLS 会话建立阶段取用。
HTTPS RR 的解码实现独立在 lib/vdns/httpsrr.c(配套头文件 lib/vdns/httpsrr.h),解析出的 ECHConfigList 与长度存于 DNS 条目中(echconfiglist / echconfiglist_len),供 TLS 层消费。
TLS 侧:ossl_init_ech 的三路输入
核心功能改动在 lib/vtls/openssl.c 的 ossl_init_ech(),它按优先级处理三个来源:
- GREASE 模式:
tls_ech == CURLECH_GREASE时调用SSL_set_enable_ech_grease(ssl, 1); - 命令行
ecl::从STRING_ECH_CONFIG取 base64 串,curlx_base64_decode()解码后SSL_set1_ech_config_list()注入;失败且模式为CURLECH_HARD时返回错误; - DoH/DNS 缓存:从 DNS 结果
rinfo->echconfiglist直接取二进制配置注入。
三条路任一成功进入 ECH 尝试(trying_ech_now)后,还会调用 SSL_ech_set1_server_names() 处理外层/内层 SNI(对应 pn: 覆盖 public_name 的场景)。失败处理集中在连接失败回调处:ECH 状态非 SSL_ECH_STATUS_SUCCESS 且模式为 CURLECH_HARD 时,verbose 输出 ECH: ech-hard failed 并终止连接(见 lib/vtls/openssl.c)。
握手后,SSL_ech_get1_status() 会给出内/外层 SNI 与实际状态,最终体现为测试页回显的 SSL_ECH_STATUS: success。
wolfSSL 与 BoringSSL 的镜像实现
- lib/vtls/wolfssl.c 中新增了与 OpenSSL 版本镜像的 ECH 代码(受
USE_ECH保护); - AWS-LC/BoringSSL 走 lib/vtls/openssl.c 内
#ifdef OPENSSL_IS_BORINGSSL分支,API 差异大多是等价替换; - lib/vtls/rustls.c 也参与
USE_ECH分支(Rustls 后端在 CMake 侧被直接视为具备 ECH 能力)。
已知限制
原文档的 Limitations 一节值得完整继承,分为“可暂时无视”与“当前真实限制”两层。
可暂缓的改进:
- HTTPS RR 中若出现
alpn=标签,本可以把它作为“内层 ALPN”传给 OpenSSL,但目前尚未实现。
当前真实限制:
- 只处理第一个 HTTPS RR:多个 RR 同时发布时如何挑“对”的那条并不容易——用
ipv4hint/ipv6hint与实际解析到的 A/AAAA 值做匹配可能是个好基础。文档作者检查时,支持 ECH 的浏览器对多条 HTTPS RR 的处理也不理想(该结论可能已过时,需复查); - IP 地址提示(hints)尚未利用:HTTPS RR 可以携带
ipv4hint=/ipv6hint=,curl 目前没有据此做连接选择。作者推测结合“multi-CDN”部署场景的思考可能给出答案,但现阶段无定论; - SVCB/HTTPS 的
aliasMode(CNAME at apex)完全未处理:理论上可以模拟“跟随 CNAME”,但是否值得做不明。文档记录当时 Chrome 不支持aliasMode,Firefox 未再检查; - libcurl 应用侧未调查:以上所有讨论都基于命令行工具形态,libcurl API 用户需要哪些配套改动尚未研究;
- 测试体系缺口:常规 curl 测试框架(runtests)要求一个 ECH-enabled 服务器与 DoH 服务器,目前未实现,只能靠脚本覆盖(见下节)。
测试现状:脚本与两个基础用例
仓库中的 tests/ech_tests.sh 是一个 1000+ 行的手工脚本,对已知支持 ECH 的服务器(Cloudflare、defo.ie 等)、有 HTTPS RR 但不做 ECH 的服务器、以及两者皆无的服务器,遍历各种 --ech 选项组合进行验证。脚本头部有一个关键前置检查:如果 ~/.curlrc 中存在激活的 ech 配置,脚本直接退出,因为默认值会污染正/负测试的判定(“把一个 fail 变成 success 或反过来”):
# Exit with an error if there is an active ech stanza in ~/.curlrc
: "${CURL_CFG_FILE=$HOME/.curlrc}"
active_ech=$(grep ech "$CURL_CFG_FILE" | grep -v "#.*ech")
if [[ "$active_ech" != "" ]]; then
echo "You seem to have an active ECH setting in $CURL_CFG_FILE"
...
exit 1
fi
脚本自身的 TODO 注释也承认:它需要“翻译成近似正式的 curl 测试”,而翻译成本包括自建 ECH-enabled 服务器和 DoH 服务器。
另一方面,常规测试框架下已有两个基础用例,目标是验证客户端在要求时确实发送 GREASE 或真实 ECH 扩展、以及在 ECH 失败时正确报错(stunnel 无 ECH 能力,被用作“不会解密 ECH”的对照):
data/test4000:GREASE ECH,预期结果——连接成功;data/test4001:真实 ECH,预期结果——以错误 101(ECH required)失败。
这两个用例与其它同类测试一样依赖 stunnel 工具(Ubuntu 上 sudo apt install stunnel4 即可安装)。
补充:无 DoH 场景与本地测试
无 DoH 时的 ECH 支持
上述全部能力都以“curl 自身使用 DoH”为前提。文档讨论了一个尚未解决的用例:当系统 stub 解析器本身支持 DoT/DoH 时(例如作者本机用 stubby+unbound 监听 localhost:53),从网络威胁模型看 curl 也应该支持 ECH,但不必自己走 DoH。目前的探索方向都未落地:
- 扩展 c-ares 支持 HTTPS RR——但 HTTPS/SVCB 的
tag=value扩展性与 c-ares“为每种支持的 RRtype 定义专用解码结构”的风格是否匹配存疑,且不确定下游 curl 部署中有多少实际使用 c-ares; - 引入其它支持 HTTPS RR 的通用 DNS 库——不确定它能否被几乎所有 curl 构建与下游发行版采用。
当前结论:先把“用 DoH”的方案跑一段时间积累经验,此用例暂搁置。
本地 localhost 测试
针对本地调试,可以用 OpenSSL s_server 搭一个 ECH 服务器(作者团队在另一个仓库发布了详细步骤)。基本姿势是:
# 在 ech-dev-utils 仓库中启动 ECH 服务器(脚本支持大量 ECH 相关选项,echsvr.sh -h 查看)
./scripts/echsvr.sh -d
另开窗口用 curl 打向它,用 --connect-to 把域名映射到本地端口:
cd $HOME/code/curl/
./src/curl -vvv --insecure --connect-to foo.example.com:8443:localhost:8443 \
--ech ecl:AD7+DQA6uwAgACBix2B78sX+EQhEbxMspDOc8Z3xVS5aQpYP0Cxpc2AWPAAEAAEAAQALZXhhbXBsZS5jb20AAA==
注意 --connect-to 把 foo.example.com:8443 重定向到 localhost:8443,而 ECH 的内层 SNI 仍是 foo.example.com,这与 ECHConfigList 中编码的 public_name 对应。
小结
curl 的 ECH 支持是一个边界清晰的实验性实现:autotools 与 CMake 均提供 --enable-ech / -DUSE_ECH=1 开关并强制联动 HTTPS RR 能力;运行时以 --ech 的六种取值控制 GREASE、机会式尝试、强制尝试与显式配置注入;数据通路为 “DoH 复用 dohprobe() 拉取 HTTPS RR → doh_store_https() 落缓存 → Curl_doh_take_result() 交付 → ossl_init_ech() 经 SSL_set1_ech_config_list() 喂入 TLS 库”。多后端(OpenSSL fork、BoringSSL、wolfSSL、Rustls)通过各自受宏保护的分支镜像实现,能力差异(如 pn:、retry_configs、GREASE 语义)在文档与源码中均有明确标注。由于 retry_configs 自动化、多条 HTTPS RR 选择、aliasMode 与 libcurl 应用侧支持均未完成,在生产环境启用前应以本文“已知限制”一节为准绳评估风险。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00