ECH — Xray-core
Encrypted Client Hello(ECH)通过用服务器发布的公钥加密 ClientHello, 将 SNI 对中间观察者隐藏。Xray 在标准 tlsSettings 块上以四个字段 形式暴露 ECH —— 没有独立的 ECH 结构体。
配置
ECH 位于 streamSettings.tlsSettings:
| 字段 | 适用端 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|---|
echServerKeys | 入站 | string | (未设置) | base64 ECH 密钥包 | 服务端 ECH 密钥集合。与 TLS 证书一起生成。 |
echConfigList | 出站 | string | (未设置) | base64 ECHConfigList | 锚定一份特定的配置列表。未设置时由客户端通过 HTTPS DNS 记录自动发现。 |
echForceQuery | 出站 | string | (级联) | hkdf、dns | 强制使用特定的发现机制。 |
echSockopt | 出站 | SocketConfig | (未设置) | 套接字选项 | 应用于 ECH 发现 DNS 请求的套接字选项。 |
示例
入站 —— 与常规 TLS 一并提供 ECH:
json
{
"streamSettings": {
"security": "tls",
"tlsSettings": {
"serverName": "example.com",
"certificates": [{ "certificateFile": "/etc/ssl/cert.pem", "keyFile": "/etc/ssl/key.pem" }],
"echServerKeys": "<base64 ECHConfigList + private keys>"
}
}
}出站 —— 通过 HTTPS DNS 自动发现 ECH:
json
{
"streamSettings": {
"security": "tls",
"tlsSettings": {
"serverName": "example.com",
"alpn": ["h2", "http/1.1"]
}
}
}ECH 是机会性的 —— 未显式设置 echConfigList 时,Xray 会查询 serverName 的 HTTPS DNS 记录,并采用其中发布的配置(若有)。
出站 —— 锚定特定的 ECH 配置:
json
{
"streamSettings": {
"security": "tls",
"tlsSettings": {
"serverName": "example.com",
"echConfigList": "<base64 ECHConfigList>",
"echForceQuery": "dns"
}
}
}说明
- ECH 要求 TLS 1.3。如需在协议层强制,请设置
minVersion: "1.3"。 - 上面示例中的 ECH
serverName(example.com)是 公开名称 —— 线路上可见的 SNI。ECH 加密的 inner ServerName 来自请求的实际目的 地。 - 仅在两端都受你掌控时再锚定
echConfigList。自动发现更稳健,因为 已发布的配置可以在客户端无需重新配置的情况下轮换。 echForceQuery: "dns"会跳过内存 HKDF 缓存,强制一次新的 DNS 查询;密钥频繁轮换时有用。
跨内核说明
- sing-box 在
tls.ech下提供专用的InboundECHOptions与OutboundECHOptions。参见 ECH — sing-box。 - mihomo 在每个 proxy 上提供
ech-opts子块,含三个字段 (enable、config、query-server-name)。参见 ECH — mihomo。
源码: infra/conf/transport_internet.go:663-666 · v26.6.1 (94ffd50)
