@hugehard/ech
v0.1.3
Published
Local HTTPS inspector and proxy with Encrypted Client Hello support
Readme
ECH
一个支持 TLS Encrypted Client Hello(ECH)的本地 HTTP/HTTPS 代理与调试工具。代理服务和 Web 管理界面默认共用 127.0.0.1:8080。
典型的浏览器链路如下:
Chrome → ZeroOmega → http://127.0.0.1:8080 → ECH 上游链路 → 目标网站ZeroOmega 只负责把 Chrome 流量转发到本地代理,ECH 握手、DNS HTTPS(TYPE65)查询和上游连接由本包的原生程序完成。
它不只是 ECH 客户端,还可以作为本地开发代理、HTTPS 抓包工具和轻量 Mock 服务使用:
- 把线上 JS、CSS 或接口地址改写到本地开发服务器。
- 用
host://把域名连接到指定 IP,同时保留原域名、TLS SNI 和证书校验。 - 按域名选择直连、系统代理或全局配置的上游代理。
- 修改请求 Header、响应 Header,模拟状态码和响应内容。
- 模拟网络延迟,或主动阻断指定请求。
- 查看请求与响应详情、搜索请求、重放请求、复制 curl。
- 用多个可开关的规则集管理开发、测试和故障模拟规则。
支持的平台
- macOS Apple Silicon(arm64)
- Windows x64
- Linux x86_64
- Node.js 18 或更高版本
macOS Intel 暂未包含原生二进制。本文主要说明 Chrome 在 macOS 和 Windows 上的使用方法。
五分钟安装
在终端或 PowerShell 中依次执行:
npm install -g @hugehard/ech
ech start
ech install-ca
ech extension然后完成两项浏览器操作:
- 在 Chrome 中安装命令准备好的离线 ZeroOmega 插件。
- 在 ZeroOmega 中导入
ECH配置并选择ECH情景模式。
完成后可以运行:
ech open浏览器会打开本地管理界面 http://127.0.0.1:8080。
第一步:安装 npm 包
macOS
打开“终端”,执行:
npm install -g @hugehard/ech
ech helpWindows
打开 PowerShell,执行:
npm install -g @hugehard/ech
ech help如果能够看到 ech 的命令列表,说明安装成功。如果提示 ech: command not found 或“无法将 ech 识别为命令”,请关闭并重新打开终端;仍然无效时,检查 npm 全局 bin 目录是否已经加入 PATH。
升级已有安装:
npm install -g @hugehard/ech@latest
ech restart升级不会删除 ~/.ech-inspector/ 中已有的配置、规则和本地 CA。
第二步:启动代理并生成本地 CA
首次启动:
ech start启动成功会显示类似内容:
ECH Inspector started (pid 12345).
Proxy + UI: http://127.0.0.1:8080确认运行状态:
ech status首次启动会在用户目录创建:
~/.ech-inspector/config.json
~/.ech-inspector/rules.txt
~/.ech-inspector/ca.pem
~/.ech-inspector/ca-key.pem
~/.ech-inspector/inspector.logWindows 中的默认位置为:
%USERPROFILE%\.ech-inspector\ca.pem 是需要加入系统信任库的本地 CA 证书。ca-key.pem 是本地 CA 私钥,不能复制、上传或分享;拿到该私钥的人可以伪造本机代理签发的证书。
第三步:安装并信任证书
HTTPS 流量经过本地代理时,代理需要使用 ECH Inspector Local CA 为目标域名动态签发证书。如果系统没有信任这张 CA,Chrome 会显示 NET::ERR_CERT_AUTHORITY_INVALID 等证书错误。
必须先运行一次 ech start 生成证书,再运行:
ech install-camacOS 自动安装
ech start
ech install-ca该命令会把 ~/.ech-inspector/ca.pem 加入当前用户的 login keychain,并设置为受信任根证书。macOS 可能要求输入当前账户密码或确认钥匙串操作。
安装后请使用 Command + Q 完全退出 Chrome,再重新打开。只关闭 Chrome 窗口不等于退出程序。
可以用下面的命令检查证书是否存在:
security find-certificate -c "ECH Inspector Local CA" "$HOME/Library/Keychains/login.keychain-db"macOS 手动安装
如果 ech install-ca 失败:
- 打开“钥匙串访问”。
- 选择左侧的“登录”钥匙串。
- 选择菜单“文件 → 导入项目”。
- 导入
~/.ech-inspector/ca.pem。 - 搜索
ECH Inspector Local CA并双击证书。 - 展开“信任”,把“使用此证书时”改为“始终信任”。
- 关闭窗口并按系统提示确认。
- 使用
Command + Q完全退出并重启 Chrome。
在 Finder 中打开证书目录:
open "$HOME/.ech-inspector"Windows 自动安装
在普通 PowerShell 中执行即可,不需要写入计算机级证书库:
ech start
ech install-ca该命令等价于把证书加入“当前用户 → 受信任的根证书颁发机构”:
certutil.exe -user -addstore Root "$env:USERPROFILE\.ech-inspector\ca.pem"如果 Windows 显示安全警告,请核对证书名称为 ECH Inspector Local CA 后确认。安装完成后,完全退出所有 Chrome 窗口和后台进程,再重新打开 Chrome。
可以检查证书是否已安装:
certutil.exe -user -store Root "ECH Inspector Local CA"Windows 手动安装
如果自动命令失败:
- 按
Win + R,输入certmgr.msc并回车。 - 展开“受信任的根证书颁发机构 → 证书”。
- 右键“证书”,选择“所有任务 → 导入”。
- 选择
%USERPROFILE%\.ech-inspector\ca.pem;看不到文件时将文件类型切换为“所有文件”。 - 选择“将所有的证书都放入下列存储”,目标选择“受信任的根证书颁发机构”。
- 完成导入,并确认能看到
ECH Inspector Local CA。 - 完全退出并重启 Chrome。
证书安装常见问题
- 提示
CA does not exist:先执行ech start,确认启动成功后再执行ech install-ca。 - 仍显示证书不受信任:确认安装的是
ca.pem,不是ca-key.pem,然后完全退出并重启 Chrome。 - 重新生成过 CA:旧 CA 和新 CA 不相同,需要重新执行
ech install-ca。 - 使用自定义数据目录:证书位于
$ECH_INSPECTOR_DATA_DIR/ca.pem,不再是默认路径。 - 某些应用使用自己的证书库:需要把
ca.pem单独导入该应用;系统已信任不代表所有应用都会自动信任。
第四步:离线安装 Chrome 插件
最终用户不需要访问 Chrome Web Store。运行:
ech extension命令会完成以下操作:
- 将官方签名的 ZeroOmega v3.5.0 CRX 复制到用户数据目录。
- 准备一个“加载已解压的扩展程序”兜底目录。
- 根据当前
config.json生成ZeroOmegaOptions-ECH.bak。 - 打开
chrome://extensions/。 - 在 macOS Finder 或 Windows 资源管理器中定位 CRX 文件。
扩展 ID 为:
pfnededegaaopdmhkdmcofjmoldfiped默认离线文件位置如下。
macOS:
~/.ech-inspector/extension/zeroomega-3.5.0.crx
~/.ech-inspector/extension/zeroomega-3.5.0-unpacked/
~/.ech-inspector/extension/ZeroOmegaOptions-ECH.bakWindows:
%USERPROFILE%\.ech-inspector\extension\zeroomega-3.5.0.crx
%USERPROFILE%\.ech-inspector\extension\zeroomega-3.5.0-unpacked\
%USERPROFILE%\.ech-inspector\extension\ZeroOmegaOptions-ECH.bak需要重新查看这些路径时运行:
ech extension --path方法 A:拖拽 CRX
- 在 Chrome 地址栏输入
chrome://extensions/。 - 打开页面右上角的“开发者模式”。
- 找到
zeroomega-3.5.0.crx。 - 将 CRX 文件拖到扩展程序页面中间。
- Chrome 弹出确认窗口后,点击“添加扩展程序”。
- 打开扩展详情,核对 ID 为
pfnededegaaopdmhkdmcofjmoldfiped。
不同 Chrome 版本对离线 CRX 的限制不同。如果拖拽成功,可以跳过下一节;如果提示只能从 Chrome Web Store 安装、扩展无效或直接拒绝拖入,请使用方法 B。
方法 B:加载已解压的扩展程序
- 保持
chrome://extensions/的“开发者模式”处于开启状态。 - 点击“加载已解压的扩展程序”。
- 选择
zeroomega-3.5.0-unpacked目录本身,不要选择它的上一级extension目录。 - 确认扩展列表出现
Proxy SwitchyOmega 3 (ZeroOmega)。 - 核对扩展 ID 为
pfnededegaaopdmhkdmcofjmoldfiped。
使用已解压方式后,不要删除或移动该目录,否则 Chrome 无法继续加载插件。npm 包升级后可以再次运行 ech extension 更新离线文件,然后在 chrome://extensions/ 点击插件卡片上的刷新按钮。
固定插件图标
- 点击 Chrome 工具栏右上角的拼图图标。
- 找到
Proxy SwitchyOmega 3 (ZeroOmega)。 - 点击旁边的固定图标,让它常驻工具栏。
第五步:配置 ZeroOmega
本地代理类型必须选择 HTTP,不要选择 SOCKS。HTTPS 网站会通过 HTTP 代理的 CONNECT 通道工作。
新用户:导入自动生成的配置
如果这是新安装的 ZeroOmega,没有需要保留的旧配置,推荐使用自动生成的备份:
ech extension options该命令会打开 ZeroOmega 选项页,并在 Finder/资源管理器中定位 ZeroOmegaOptions-ECH.bak。
在 ZeroOmega 中:
- 点击左侧“导入/导出”。
- 找到“选项”。
- 点击“从备份文件恢复”。
- 选择
ZeroOmegaOptions-ECH.bak。 - 看到“导入选项成功”后,点击工具栏中的 ZeroOmega 图标。
- 选择
ECH情景模式。
备份会根据当前 ECH 配置生成,默认内容是:
情景模式:ECH
协议:HTTP
服务器:127.0.0.1
端口:8080
快速切换:ECH / [直接连接]注意:从备份恢复会替换 ZeroOmega 现有的全部情景模式和设置。已经在使用 ZeroOmega 的用户不要导入,应该手动添加配置。
已有用户:手动新建 ECH 情景模式
- 点击 ZeroOmega 图标,进入“选项”。
- 点击左侧“新建情景模式”。
- 情景模式名称填写
ECH。 - 类型选择“代理服务器”。
- 点击“创建”。
- 协议选择
HTTP。 - 服务器填写
127.0.0.1。 - 端口填写
8080。 - 点击左侧“应用选项”保存。
- 点击工具栏中的 ZeroOmega 图标,选择
ECH。
如果修改过 proxyHost 或 proxyPort,请以 ech status 显示的地址为准,不要照抄默认端口。
第六步:验证是否正常
1. 检查本地服务
ech status正常结果应包含:
ECH Inspector is running
Proxy + UI: http://127.0.0.1:80802. 检查 ZeroOmega
点击工具栏中的 ZeroOmega 图标,确认当前选中的是 ECH,而不是 [直接连接] 或 [系统代理]。
3. 打开管理界面
ech open也可以直接访问:
http://127.0.0.1:80804. 发起测试请求
在 Chrome 中打开需要经过本地代理的网站,然后回到管理界面的 Network 页面查看请求。只要请求出现,并且 Chrome 没有证书告警,说明插件、代理和 CA 信任链已经接通。
需要实时看错误日志时运行:
ech logs -f日常使用
开始使用:
ech start然后在 ZeroOmega 中选择 ECH。
暂时停用代理时,先在 ZeroOmega 中切换到 [直接连接],再执行:
ech stop如果直接停止本地服务但 ZeroOmega 仍选中 ECH,Chrome 会因为无法连接 127.0.0.1:8080 而打不开网页。
完整功能介绍
1. Web 管理界面和请求记录
运行:
ech open管理界面与代理共用 http://127.0.0.1:8080,包括两个主要页面。
Network 页面
Network 页面用于确认请求实际走了哪条链路,以及检查请求和响应内容:
- 按 URL、请求方法或错误信息搜索。
- 查看状态码、耗时、上游类型和完整 URL。
- 查看请求 Header、请求 Body、响应 Header、响应 Body。
- 查看请求使用的是
direct、rewrite、ech、ech-auto或回退链路。 - “重放”会使用内存记录中的请求方法、Body 和原始 Header 再发起一次请求。
- “复制 curl”会生成可在终端复现请求的命令;文本 Body 会写入命令,二进制 Body 不会直接写入。
- “清空”只清除内存中的请求记录,不会删除规则、配置或证书。
- “下载 CA”可以下载当前
ca.pem,供需要独立证书库的应用导入。
请求详情和接口 JSON 会对 Authorization、Cookie、Set-Cookie、API Key 等敏感 Header 脱敏;但“重放”和“复制 curl”需要使用原始 Header,因此复制出的 curl 可能包含凭据。
如果请求 Body 超过 captureBodyLimit,界面只保留截断后的预览,重放和复制 curl 也只能使用这部分内容;大文件上传不应依赖该功能完整重放。
Rules 页面
Rules 页面用于直接编辑规则,不需要手动寻找 rules.txt:
ON/OFF:总开关。关闭后所有规则停止生效,但规则内容仍保留。Create / Rename / Delete:创建、重命名或删除规则集。- 每个规则集可以独立启用或停用,适合区分“本地开发”“测试环境”“Mock”“故障模拟”。
Import / Export:导入或导出当前规则集的文本。Save:校验并立即应用。语法错误时会显示具体行号,错误配置不会生效。Command/Ctrl + S:保存。Command/Ctrl + /:注释或取消注释当前行。
规则保存在数据目录的 rules.txt 和 rules.txt.workspace.json 中,重启后继续生效。
2. 规则基本格式
每行是一条规则:
匹配范围 操作 [操作 ...]空行和以 # 开头的行会被忽略。同一行可以组合多个操作:
api.example.com/v1 includeFilter://m:GET reqHeaders://X-Debug=1 reqDelay://300匹配范围
| 写法 | 匹配范围 | 适用场景 |
| --- | --- | --- |
| * | 所有进入规则处理的请求 | 全局 Header 或统一故障模拟 |
| api.example.com | 精确域名 | 针对一个服务 |
| *.example.com | 所有子域名,不包含根域名 example.com | 针对一组子域 |
| api.example.com/v1 | 域名相同且路径以 /v1 开头 | 针对一组 API |
| https://api.example.com/v1 | 从 URL 写法中提取域名和路径前缀,协议本身不参与匹配 | 更易读的域名加路径写法 |
| /https:\/\/cdn\.example\.com\/assets\/(.*)/ | Go RE2 正则匹配完整 URL | JS/CSS 地址改写和复杂匹配 |
| /pattern/i | 忽略大小写的正则 | 大小写不固定的 URL |
正则还支持 m 和 s 标志。保存规则时会校验正则;不支持 JavaScript 正则特有的 lookbehind 等 RE2 不支持的语法。
HTTPS 抓包范围
HTTPS 默认使用 CONNECT 透明隧道,不会解密全部网站。下列情况才会进入本地 TLS 抓包:
- 域名命中
captureHosts。 - 域名命中
ech://...或echConfig://...规则。 - 域名命中 URL 改写规则。
因此,如果只写下面这条规则:
api.example.com reqHeaders://X-Debug=1它可以处理明文 HTTP,但 HTTPS 请求还需要把域名加入 captureHosts,或者与 ECH/URL 改写规则组合:
{
"captureHosts": "api.example.com,*.dev.example.com"
}host:// 和 proxy:// 属于连接层规则,即使不解密 HTTPS 也可以作用于 CONNECT 隧道。
3. URL、JS 和 CSS 地址改写
目的
把浏览器原本要访问的线上资源转发到另一个 HTTP/HTTPS 地址,常用于:
- 将线上 JS 或 CSS 替换成本地 Vite、Webpack 等开发服务器的文件。
- 把线上 API 临时转到本地后端。
- 在不修改页面源码和 DNS 的情况下调试已部署页面。
固定地址改写
cdn.example.com/assets/app.js http://127.0.0.1:5173/app.js请求 https://cdn.example.com/assets/app.js 时,代理会向 http://127.0.0.1:5173/app.js 发请求。请求方法和 Body 会保留,发往上游的 Host 会改成新地址的 Host。
使用正则改写一组资源
/https:\/\/cdn\.example\.com\/assets\/(.*)/ http://127.0.0.1:5173/$1例如:
https://cdn.example.com/assets/js/app.abc123.js会被改写为:
http://127.0.0.1:5173/js/app.abc123.js只替换带 hash 的主入口 JS:
/https:\/\/cdn\.example\.com\/assets\/app\..*\.js/ http://127.0.0.1:5173/app.js捕获组规则:
$0:整个匹配内容。$1到$9:对应正则捕获组。$$:输出一个字面量$。
同一个请求匹配多条 URL 改写规则时,只使用第一条,所以应把精确规则放在通用规则前面。HTTPS URL 改写会自动启用对应域名的 TLS 抓包,无需再加入 captureHosts。
4. host:// 指定连接 IP
目的
跳过本地 DNS 结果,强制把某个域名连接到指定 IP,常用于:
- 调试本地或测试服务器。
- 绕过错误或被污染的 DNS 解析结果。
- 把请求定向到某个灰度节点。
- 在不修改系统 hosts 文件的情况下临时切换地址。
写法
api.example.com host://127.0.0.1也兼容传统 hosts 写法:
127.0.0.1 api.example.com可以配置多个 IP,前一个连接失败后继续尝试下一个:
api.example.com host://192.0.2.10,192.0.2.11host:// 只替换实际 TCP 连接地址,原 URL Host、HTTP Host、TLS SNI 和证书校验仍然使用 api.example.com。这与 URL 改写不同:URL 改写会把请求的目标 URL 和上游 Host 一起改成新地址。
单独使用 host:// 时,HTTPS 默认保持端到端隧道,因此目标 IP 必须能够为原域名提供有效证书。如果该域名还在 captureHosts 或 ECH 规则中,本地代理会先解密浏览器流量,再使用原域名和指定 IP 连接上游。
host:// 只控制直接连接时的目标 IP。如果同一个域名被 proxy://system 或全局上游代理接管,目标域名通常由上游代理解析,host:// 不会传给那个上游代理。
5. 上游代理和代理链路
目的
控制未走 ECH 或 URL 改写的请求如何继续访问网络,适用于:
- 本机已经有公司代理或第三方代理,需要继续串联。
- 某些域名必须绕过系统代理直接访问。
- 大多数请求直连,只有特定域名跟随系统代理。
全局 fallbackProxy
在 config.json 中配置:
{
"fallbackProxy": "direct"
}可选值:
direct:直接连接目标,默认值。system:读取系统或环境变量中的 HTTP/HTTPS 代理。http://proxy.example.com:8080:所有普通上游请求使用指定 HTTP 代理。https://proxy.example.com:8443:使用指定 HTTPS 代理。http://user:[email protected]:8080:使用带 Basic 认证的上游代理。配置文件包含明文凭据,应限制文件权限。
macOS 的 system 会读取系统 HTTP/HTTPS 代理,同时遵守 ExceptionsList 和 ExcludeSimpleHostnames。Windows 和 Linux 的 system 使用 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY。
如果全局代理指回本工具自己的监听地址,启动会拒绝该配置,避免形成代理死循环。
按域名覆盖
api.example.com proxy://system
internal.example.com proxy://directproxy://system:这个域名使用系统代理。proxy://direct:这个域名强制直连,覆盖全局fallbackProxy。
规则中的 proxy:// 目前只支持 system 和 direct,不能直接填写自定义代理 URL;自定义 URL 应放在全局 fallbackProxy 中。
6. 修改请求 Header
目的
- 给请求增加调试标识或灰度标识。
- 临时注入测试用 Authorization。
- 修改 User-Agent、Origin 或其他上游识别字段。
单个 Header:
api.example.com reqHeaders://X-Debug=1多个 Header 使用 &:
api.example.com reqHeaders://X-Debug=1&X-Environment=local包含空格或特殊字符时可以使用括号,或者进行 URL 编码:
api.example.com reqHeaders://(Authorization=Bearer test-token)
api.example.com reqHeaders://Authorization=Bearer%20test-token代理使用覆盖语义:如果请求本来已经存在同名 Header,新值会替换旧值。对 HTTPS 使用该能力时,域名必须处于 HTTPS 抓包范围。
7. 修改响应 Header
目的
- 本地联调时临时开放 CORS。
- 禁用浏览器缓存。
- 修改 Content-Type 或测试前端对响应头的处理。
示例:
api.example.com resHeaders://Access-Control-Allow-Origin=*&Cache-Control=no-store修改 JSON Content-Type:
api.example.com resHeaders://Content-Type=application/json响应 Header 修改既适用于真实上游响应,也适用于本地 Mock 响应。同名 Header 会被规则值覆盖。对 HTTPS 使用时同样需要进入抓包范围。
8. Mock 状态码和响应 Body
目的
不访问真实上游,直接由本地代理返回结果,常用于:
- 前端等待后端接口时先模拟数据。
- 测试 401、403、404、429、500 等异常状态。
- 快速验证空数据、错误数据和降级页面。
返回 JSON:
api.example.com/v1/user statusCode://200 resBody://({"id":1,"name":"Local"}) resHeaders://Content-Type=application/json模拟服务错误:
api.example.com/v1/order statusCode://503 resBody://(service unavailable)statusCode 必须在 100 到 599 之间。只有配置 statusCode://... 才会触发本地 Mock;单独写 resBody://... 不会拦截真实请求。Mock 命中后不会连接上游。
9. 模拟请求延迟
目的
- 测试 Loading、Skeleton 和超时提示。
- 模拟弱网或慢接口。
- 检查重复提交、请求取消和并发行为。
延迟 1500 毫秒:
api.example.com/v1/order reqDelay://1500延迟范围是 0 到 300000 毫秒。一个请求同时命中多条延迟规则时,延迟时间会累加。
10. 阻断请求
目的
- 测试资源加载失败。
- 临时屏蔽某个接口、埋点或第三方脚本。
- 模拟网络层失败,而不是返回一个 HTTP 状态码。
推荐写法:
api.example.com/blocked enable://abort也支持:
api.example.com/blocked block://true阻断与 Mock 不同:Mock 会返回指定 HTTP 响应,阻断会让请求以代理错误结束。对 HTTPS 使用时需要进入抓包范围。
11. 按请求方法过滤
目的
同一个路径可能同时处理 GET、POST、PUT 等请求,方法过滤可以只对其中一种生效。
只 Mock GET:
api.example.com/v1/user includeFilter://m:GET statusCode://200 resBody://({"id":1})只延迟 POST:
api.example.com/v1/order includeFilter://m:POST reqDelay://2000目前文本规则只支持 includeFilter://m:METHOD 这一种 includeFilter 写法。
12. 多条规则的组合与优先级
一个请求可以命中多条规则,处理原则如下:
- 请求 Header、响应 Header 和延迟可以由多条规则叠加。
- 同名 Header 被后匹配到的规则覆盖。
- 多条延迟规则的时间会累加。
- ECH 模式、
host://和proxy://的后匹配值覆盖前值。 - URL 改写只执行第一条匹配规则。
- Block 或 Mock 按规则顺序处理,先遇到的终止操作生效。
- 规则集按 Rules 页面中的顺序组合,每个规则集内部按文本从上到下执行。
因此应把更精确的 URL 改写、Block 和 Mock 放在更通用的规则前面。
13. ECH 规则
运行以下命令查看配置文件位置:
ech configrules.txt 与 config.json 位于同一目录。规则示例:
example.com ech://require
api.example.com ech://auto
legacy.example.com ech://offech://require:必须使用 ECH;失败时明确报错,不降级到普通 TLS。ech://auto:优先使用 ECH,失败时允许回退到普通 TLS。ech://off:关闭该域名的 ECH。
三种写法都会让命中的 HTTPS 域名进入本地抓包。ech://off 的含义是上游使用普通 TLS,不是关闭本地抓包;如果只想让请求保持完全透明的端到端隧道,不要为该域名添加 ECH 规则,也不要把它加入 captureHosts。
显式指定 ECHConfig 和连接地址:
example.com ech://require echConfig://BASE64_ECH_CONFIG host://192.0.2.10echConfig://BASE64_ECH_CONFIG:使用明确的 ECHConfig,适合验证指定配置或绕过自动发现结果;未写ech://时默认按require处理。host://192.0.2.10:指定承载 ECH 请求的连接 IP,同时继续使用原域名作为 SNI 和证书校验名称。- 显式设置
echConfig://或host://后,工具尊重该固定目标,不会自动切换到 relay。
默认情况下,工具先通过可信 DoH 获取 ECH bootstrap,再查询目标域名的 HTTPS(TYPE65)记录。ECHConfig 和 IP hints 会按 DNS TTL 缓存并自动刷新;服务端返回 retry_configs 时会更新配置并重试。
如果目标记录下发的 IP hints 暂时拒绝当前 ECHConfig,工具会继续尝试 Cloudflare ECH relay。ech://require 在两条 ECH 路径都失败时会明确报错,不会降级成普通 TLS。显式配置 echConfig:// 或 host:// 时不会自动改道。
常见故障
ERR_PROXY_CONNECTION_FAILED
原因通常是 ZeroOmega 已选择 ECH,但本地代理没有运行。
ech start
ech statusNET::ERR_CERT_AUTHORITY_INVALID
重新执行:
ech start
ech install-ca确认系统信任库中存在 ECH Inspector Local CA,然后完全退出并重启 Chrome。
CRX 无法拖入或提示必须从商店安装
这是 Chrome 对离线 CRX 的限制。打开开发者模式,使用“加载已解压的扩展程序”,选择 zeroomega-3.5.0-unpacked。
ZeroOmega 提示代理设置无法控制
通常是另一个代理插件或浏览器策略正在控制 Chrome 代理。禁用其他代理类扩展,再重新选择 ECH。
页面显示 Bad Gateway 或 upstream request failed
先确认使用的是最新版:
npm install -g @hugehard/ech@latest
ech restart
ech logs -f日志会记录目标 ECH 路径、relay 尝试和最终错误。ech://require 不会静默降级到普通 TLS。
停止代理后所有网页都打不开
在 ZeroOmega 中选择 [直接连接]。只执行 ech stop 不会自动修改 Chrome 的代理设置。
端口 8080 被占用
运行 ech config,编辑 config.json 中的 proxyPort,然后:
ech restart
ech extension重新生成并导入 ECH Profile,或者手动把 ZeroOmega 端口改成新端口。
常用命令
ech start 后台启动代理
ech stop 停止代理
ech restart 重启代理
ech status 查看状态和监听地址
ech logs 查看最近日志
ech logs -f 实时跟踪日志
ech open 打开 Web 管理界面
ech install-ca 信任本地 CA
ech extension 准备并打开离线插件安装流程
ech extension options 打开插件选项并定位 ECH 配置备份
ech extension --path 输出 CRX、unpacked 和配置备份路径
ech config 输出 config.json 路径
ech help 查看命令帮助配置
默认 config.json:
{
"proxyHost": "127.0.0.1",
"proxyPort": 8080,
"fallbackProxy": "direct",
"captureHosts": "",
"maxSessions": 500,
"captureBodyLimit": 1048576,
"upstreamPoolSize": 32,
"maxConnectionAge": "10m"
}每个配置项的目的:
| 配置项 | 默认值 | 作用 |
| --- | --- | --- |
| proxyHost | 127.0.0.1 | 本地代理和管理 UI 的监听地址。保持回环地址可避免局域网或公网中的其他设备访问管理接口。 |
| proxyPort | 8080 | 本地 HTTP 代理和管理 UI 共用的端口。修改后也要同步修改 ZeroOmega Profile。 |
| fallbackProxy | direct | 普通 TLS、透明隧道和非 ECH 请求的默认上游路线,可选直连、系统代理或明确的 HTTP(S) 代理 URL。 |
| captureHosts | 空 | 主动进行 HTTPS 解密和请求记录的域名列表,逗号分隔,支持 *.example.com 和 *。ECH 与 URL 改写规则会自动启用对应域名,不必重复填写。 |
| maxSessions | 500 | 内存中最多保留多少条请求记录。达到上限后淘汰最旧记录;不会写入磁盘。 |
| captureBodyLimit | 1048576 | 每条请求和响应最多保留多少字节的 Body 预览,默认 1 MiB。它只限制界面中的记录,不截断实际转发内容。 |
| upstreamPoolSize | 32 | 可复用的原生上游连接句柄数量。并发较高时可以增加,但会占用更多连接和内存。 |
| maxConnectionAge | 10m | 上游连接句柄复用的最长时间。到期后重建,以避免长期复用失效的连接或旧 ECH 状态。 |
| logMaxSize | 10485760 | 单个日志文件达到多少字节后轮转,默认 10 MiB。未写出时 CLI 会自动补默认值。 |
| logBackups | 3 | 最多保留多少个历史日志文件。设置为 0 表示不保留轮转备份。 |
captureHosts 示例:
{
"captureHosts": "api.example.com,*.dev.example.com"
}* 会解密所有通过代理的 HTTPS 流量,只适合明确需要全量调试的环境。范围越大,代理能看到的敏感数据越多,也会增加证书签发、记录和内存开销;日常使用应优先填写具体域名。
fallbackProxy 支持 direct、system 或明确的 http://host:port、https://host:port。macOS 的 system 会读取系统 HTTP/HTTPS 代理并遵守例外列表;Linux 和 Windows 从 HTTP_PROXY、HTTPS_PROXY、NO_PROXY 读取。
按域名覆盖上游代理:
api.example.com proxy://system
assets.example.com proxy://direct其他规则示例:
api.example.com host://127.0.0.1
api.example.com reqHeaders://x-debug=1
api.example.com resHeaders://cache-control=no-store
api.example.com reqDelay://500
api.example.com enable://abort
api.example.com mockStatus://200 mockBody://ok
/https:\/\/cdn\.example\.com\/(.*)/ http://127.0.0.1:8000/$1环境变量
export ECH_INSPECTOR_DATA_DIR=/path/to/data
export ECH_INSPECTOR_CONFIG=/path/to/config.jsonPowerShell 示例:
$env:ECH_INSPECTOR_DATA_DIR = "D:\ech-data"
$env:ECH_INSPECTOR_CONFIG = "D:\ech-data\config.json"安全说明
- 代理和管理 UI 默认只监听回环地址,不要把管理端口暴露到公网。
- 可以把
ca.pem导入本机信任库,但绝对不要分享ca-key.pem。 - Web 管理界面的请求记录只保存在内存中。
- 敏感 Header 会在详情和 API JSON 中脱敏。
- 用户主动执行“复制 curl”或“重放”时会使用本机内存中的原始 Header,复制出的命令可能包含 Cookie 或 Authorization,请勿发给不可信的人。
- 不再使用时,可以在“钥匙串访问”或
certmgr.msc中删除ECH Inspector Local CA,并在 Chrome 中移除或禁用 ZeroOmega。
第三方插件说明
包内提供 Proxy SwitchyOmega 3(ZeroOmega)v3.5.0 的官方签名 CRX、解压兜底、GPL-3.0-or-later 许可证和对应源码归档。ZeroOmega 是独立第三方项目,与本包不存在隶属或合作关系。详细信息见 extension/THIRD_PARTY_NOTICES.md。
Node.js 只用于命令行管理;代理、证书签发和 ECH 传输由随包提供的原生程序完成。
