macOS下使用dotnet watch时curl报tlsv1 alert protocol version错误
针对你遇到的问题——macOS升级到Monterey/Ventura后,dotnet watch run启动的F# ASP.NET应用无法被curl正常调用(报TLS版本错误),但直接运行dll一切正常,Windows下也无问题——以下是几个具体的排查方向,你可以逐一尝试:
对比dotnet watch与直接运行的SSL配置/日志差异
两种启动方式的环境可能存在细微差别,dotnet watch可能加载了额外的配置或覆盖了SSL相关设置。你可以:- 在应用的
appsettings.json中把日志级别调到Debug,启用TLS相关日志,查看两种启动方式下应用输出的TLS协商细节; - 运行
dotnet watch run时添加环境变量,比如DOTNET_LOG_LEVEL=debug,观察工具启动时是否有SSL相关的警告或异常; - 对比两种启动方式下应用进程的环境变量,看是否有
ASPNETCORE_Kestrel__Certificates__Default等SSL相关变量的差异。
- 在应用的
验证dotnet watch使用的.NET Runtime版本
有时候dotnet watch工具可能绑定了和全局不同的.NET Runtime版本,导致SSL行为不一致:- 分别运行
dotnet --version和dotnet watch --version,确认两者的版本是否匹配(都应为6.0.301相关); - 用
dotnet --list-runtimes查看已安装的Runtime,确保6.0.301是当前有效的版本; - 尝试在项目目录下运行
dotnet watch --verbosity detailed run,查看工具启动时加载的Runtime路径是否正确。
- 分别运行
强制指定.NET的SSL提供者
.NET在macOS上支持两种SSL提供者:Apple的Secure Transport和OpenSSL,新版本macOS可能对其中一种的兼容性有变化。你可以尝试在启动dotnet watch时设置环境变量:COMPlus_SslProvider=Apple dotnet watch run -v --project Server/Server.fsproj或者换成OpenSSL:
COMPlus_SslProvider=OpenSSL dotnet watch run -v --project Server/Server.fsproj测试两种情况是否能解决curl的TLS错误。
检查自签名证书的兼容性与加载方式
虽然直接运行时证书正常,但dotnet watch可能在加载证书时的逻辑不同:- 重新生成自签名证书,使用更兼容的算法(比如RSA 2048位密钥、SHA256签名算法),替换原证书后再测试;
- 确认dotnet watch启动时,应用是否正确读取到了指定的证书文件,而不是 fallback 到其他证书(比如系统默认的开发证书);
- 用
openssl x509 -in your-cert.pfx -text -noout检查证书的有效期、签名算法、扩展字段,确保符合macOS 12.6+/13+的安全要求。
分析服务器支持的TLS版本与Cipher Suites
分别在dotnet watch启动和直接运行dll时,用openssl s_client命令查看服务器的TLS配置:openssl s_client -connect localhost:5001 -tls1_2替换
tls1_2为tls1_3等,对比两种情况下服务器返回的Protocol和Cipher Suite信息。如果dotnet watch启动的服务器只支持旧版本TLS(而curl默认禁用),或者Cipher Suite不兼容,就会导致报错——虽然你加了--tlsv1.x参数,但可能服务器根本不支持对应的版本,需要进一步调整Kestrel的TLS配置。更新dotnet watch工具到最新版本
旧版本的dotnet watch可能和新版本macOS存在兼容性问题,尝试更新工具:dotnet tool update --global dotnet-watch更新完成后再重新启动应用测试。
内容的提问来源于stack exchange,提问作者Flavio Colavecchia

