错误报告
标题
Clash sniff-tls-sni 开启时导致 Gradle/Fabric 依赖下载异常,表现为 Maven/Fabric 仓库 TLS 握手失败
环境信息
- 主机代理:Clash,mixed-port: 7890
- 构建环境:WSL/Linux 子环境
- 构建工具:Gradle 9.2.1
- Mod 工具链:Fabric Loom 1.15.4
- Java:21
- 相关 Clash 配置变更:
- 早期:dns.enhanced-mode: fake-ip,experimental.sniff-tls-sni: true
- 当前可用:dns.enhanced-mode: redir-host,experimental.sniff-tls-sni: false
问题描述
在使用 Clash 作为主机代理、WSL 通过 127.0.0.1:7890 出网的环境中,Gradle 构建 Fabric 项目时出现网络相关构建失败。失败并非 Java 编译慢或 javac 性能问题,而是依赖解析和构建前置下载阶段异常中断。
该问题在 redir-host + sniff-tls-sni=false 后恢复正常,说明根因与 Clash 的 TLS SNI 嗅探行为高度相关。
具体错误表现
构建期间出现以下典型报错:
- Gradle/Fabric 依赖解析失败:
- Could not resolve all files for configuration ':modImplementation'
- Could not resolve net.fabricmc:fabric-loader:0.18.4
- Could not resolve net.fabricmc.fabric-api:...
- 具体网络错误:
- Could not GET 'https://maven.fabricmc.net/...pom'
- The server may not support the client's requested TLS protocol versions: (TLSv1.2, TLSv1.3)
- Remote host terminated the handshake
- 早期阶段还出现过:
- Network is unreachable
- Could not GET 'https://plugins.gradle.org/...
- Could not GET 'https://plugins-artifacts.gradle.org/...
- Loom 还有一个次要提示:
- Previous process has disowned the lock due to abrupt termination
- Found existing cache lock file ..., rebuilding loom cache
这说明之前有异常终止留下缓存锁,但这不是主因,只是连带现象。
什么是通的,什么是不通的
问题配置下的网络表现可以分成几类:
- 本地代理端口可达:
- 127.0.0.1:7890 是通的
- 通过代理访问部分站点是通的:
- downloads.gradle.org 可通
- Gradle wrapper zip 下载可成功
- curl 通过代理访问部分 Maven/Fabric 资源可成功
- 普通 JDK HttpURLConnection 通过代理访问 Maven/Fabric 资源也可成功
- Gradle 自身访问特定仓库时不通:
- maven.fabricmc.net 通过 Gradle 解析依赖时经常失败
- repo.maven.apache.org 在 Gradle 某些阶段也出现 TLS EOF / handshake termination
- plugins.gradle.org / plugins-artifacts.gradle.org 早期阶段出现过失败
- 在 fake-ip 模式下,DNS 表现异常但这不是最终主因:
- 域名会解析成 198.18.0.x
- 这是 Clash fake-ip-range: 198.18.0.1/16 的正常表现
- --noproxy 直连时常超时
- IPv6 为 Network is unreachable
这些现象说明 fake-ip 会干扰排障,但最终导致 Gradle 失败的关键触发点不是 fake-ip 本身,而是 TLS 路径上的兼容性问题
原因分析
根据现象和配置切换结果,高置信判断如下:
- fake-ip 会让 WSL/Java/Gradle 这类开发环境看到虚假的 198.18.0.x 地址,增加排障噪声,但不是最终唯一根因。
- 真正导致构建失败的关键因素是 experimental.sniff-tls-sni: true。
- 当 TLS SNI 嗅探开启时,Gradle 的 HTTPS/TLS 请求在访问 maven.fabricmc.net 等仓库时会被对端提前中止,表现为:
- Remote host terminated the handshake
- SSLHandshakeException
- EOFException
- 这不是“整个代理坏了”,因为:
- 本地代理端口是通的
- curl 可通
- 普通 JDK HTTP 请求可通
- Gradle wrapper 下载也可通
- 因此问题更像是:
- Clash 的 TLS SNI 嗅探
- 当前代理出口链路
- Gradle 使用的 HTTP/TLS 客户端栈
三者组合后出现兼容性问题。
解决结果
将 Clash 调整为以下状态后,构建恢复正常:
- dns.enhanced-mode: redir-host
- experimental.sniff-tls-sni: false
其中:
- redir-host 的作用是减少 fake-ip 对开发环境的干扰
- sniff-tls-sni: false 是本次问题恢复正常的关键变更
结论
本问题不是项目依赖版本错误,也不是 Java 编译性能问题,而是代理层网络行为导致的 Gradle TLS 握手异常。
最终结论如下:
- fake-ip 会放大 WSL/Gradle 排障复杂度
- sniff-tls-sni: true 会导致 Gradle 访问 Fabric/Maven 仓库时出现 TLS 握手失败
- 在本环境下,redir-host + 关闭 sniff-tls-sni 是有效修复方案