使用ngrok与dotnet时遭遇SSLV3_ALERT_HANDSHAKE_FAILURE等SSL握手错误
解决Dotnet 6 API通过ngrok隧道对外访问时的SSL握手失败问题
问题背景
本地运行Dotnet 6 API,需通过ngrok创建隧道供无线IoT设备访问,但外部访问ngrok分配的地址时出现SSL握手失败。本地访问https://localhost:7063正常,已尝试多种ngrok命令、更新依赖、重新信任开发证书,但问题依旧。
已尝试的操作
- 测试过的ngrok命令:
ngrok http --host-header=rewrite --scheme=https https://localhost:7063 ngrok http https://localhost:7063 ngrok http --host-header=localhost:7063 https://localhost:7063 ngrok http 7063 - 执行
brew update && brew upgrade升级到ngrok 3.2.2 - 更新OpenSSL版本
- 执行
dotnet dev-certs https --trust重新生成并信任Dotnet HTTPS开发证书
错误信息
- Postman报错:
Error: write EPROTO 5026831912:error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE:../../../../src/third_party/boringssl/src/ssl/tls_record.cc:594:SSL alert number 40 5026831912:error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO:../../../../src/third_party/boringssl/src/ssl/handshake.cc:644: - curl报错:
curl: (35) LibreSSL/3.3.6: error:1404B410:SSL routines:ST_CONNECT:sslv3 alert handshake failure
系统环境
MacBook Pro M1 Pro 32GB RAM Ventura 13.3.1 API - Dotnet 6 ngrok - 3.2.2
解决方案
1. 调整ngrok命令(核心修复)
不要让ngrok代理本地的HTTPS服务,而是让ngrok对外提供可信SSL证书,转发到本地端口并正确传递Host头。推荐使用以下命令:
ngrok http --host-header=localhost:7063 7063
或者强制对外暴露HTTPS:
ngrok http --scheme=https --host-header=localhost:7063 7063
原理:ngrok会为分配的域名自动签发受信任的SSL证书,外部设备无需信任本地自签证书。如果直接代理https://localhost:7063,ngrok会转发本地的自签证书,外部设备因不信任该证书导致握手失败。
2. 检查Dotnet API的Kestrel配置
确保appsettings.json中Kestrel的HTTPS绑定正确,避免限制过严的SSL协议或套件:
"Kestrel": { "Endpoints": { "Https": { "Url": "https://localhost:7063", "SslProtocols": ["Tls12", "Tls13"] } } }
如果API强制要求特定加密套件,需确保与ngrok支持的套件兼容。
3. 查看ngrok管理界面排查
启动ngrok后访问http://localhost:4040,查看请求的详细日志,确认SSL握手阶段的具体失败原因,比如是否是协议版本不兼容。
4. 适配IoT设备的旧TLS版本
如果IoT设备仅支持TLS 1.0/1.1(不推荐,存在安全风险),可修改ngrok配置文件~/.ngrok2/ngrok.yml:
tls_min_version: "tls1.0" tls_max_version: "tls1.3"
修改后重启ngrok即可。
内容的提问来源于stack exchange,提问作者Mark McGookin
相关产品推荐
相关产品推荐

