.NET8应用部署Google Cloud Run时遇SSL解密失败或坏记录MAC错误
问题:Cloud Run Job中C#应用调用法国INPI HTTPS端点出现SSL解密错误
我有一个仅依赖Microsoft.*包的基础C#应用,需要连接法国公共信息HTTPS端点:https://registre-national-entreprises.inpi.fr/api。应用已打包为Docker镜像,Dockerfile内容如下:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /app # prepare rocksdbsharp RUN apt-get update && apt-get install -y --no-install-recommends \ libc6-dev \ libsnappy1v5 \ zlib1g \ libbz2-1.0 \ libgflags2.2 \ liblz4-1 \ libzstd1 \ && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y bzip2 lz4 librocksdb-dev COPY . . WORKDIR /app/*redacted* RUN dotnet restore ./*redacted*.csproj RUN dotnet publish ./*redacted*.csproj -c Release -o /out # runtime image FROM mcr.microsoft.com/dotnet/aspnet:8.0 COPY --from=build-env /out . COPY --from=build-env /usr/lib /usr/lib COPY --from=build-env /usr/local/lib/ /usr/local/lib/ COPY --from=build-env /usr/local/bin/ /usr/local/bin/ ENV LD_LIBRARY_PATH="/usr/lib:/usr/local/bin:/usr/local/lib:${LD_LIBRARY_PATH}" ENTRYPOINT ["dotnet", "*redacted*.dll"]
本地直接运行.NET应用或Docker镜像均正常,但部署到Google Cloud Run Job时出现以下SSL解密错误:
2024-03-21 14:31:10.716 CET ---> System.IO.IOException: The decryption operation failed, see inner exception. 2024-03-21 14:31:10.716 CET ---> Interop+OpenSsl+SslException: Decrypt failed with OpenSSL error - SSL_ERROR_SSL. 2024-03-21 14:31:10.716 CET ---> Interop+Crypto+OpenSslCryptographicException: error:0A000119:SSL routines::decryption failed or bad record mac 2024-03-21 14:31:10.716 CET --- End of inner exception stack trace --- 2024-03-21 14:31:10.716 CET at Interop.OpenSsl.Decrypt(SafeSslHandle context, Span`1 buffer, SslErrorCode& errorCode) 2024-03-21 14:31:10.716 CET at System.Net.Security.SslStreamPal.DecryptMessage(SafeDeleteSslContext securityContext, Span`1 buffer, Int32& offset, Int32& count) 2024-03-21 14:31:10.716 CET --- End of inner exception stack trace --- 2024-03-21 14:31:10.716 CET at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken) 2024-03-21 14:31:10.716 CET at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token) 2024-03-21 14:31:10.716 CET at System.Net.Http.HttpConnection.FillAsync(Boolean async) 2024-03-21 14:31:10.716 CET at System.Net.Http.HttpConnection.ChunkedEncodingReadStream.CopyToAsyncCore(Stream destination, CancellationToken cancellationToken) 2024-03-21 14:31:10.716 CET at System.Net.Http.HttpConnectionResponseContent.<SerializeToStreamAsync>g__Impl|6_0(Stream stream, CancellationToken cancellationToken) 2024-03-21 14:31:10.716 CET at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
已尝试的无效方案
禁用TCP分段卸载等网络优化:
ethtool -K eth0 tso off gro off gso off ufo off
该命令无法在Dockerfile中执行,且Cloud Run环境不允许直接修改网络接口参数。降级TLS版本和调整OpenSSL安全级别:
sed -i 's/MinProtocol = TLSv1.3/MinProtocol = TLSv1/' /etc/ssl/openssl.cnf \ && sed -i 's/CipherString = DEFAULT@SECLEVEL=2/CipherString = DEFAULT@SECLEVEL=1/' /etc/ssl/openssl.cnf目标端点支持TLS 1.3,且该操作未解决问题。
补充信息
- 错误仅在响应体较大(>200KB)的请求中出现,无论是否使用VPC都会触发。
- 怀疑与MTU参数有关,但不确定在Cloud Run无自定义子网的场景下能否配置MTU,也无法确认是否相关。
- 已查看Cloud Run配额文档,其中的大小限制针对容器本身,而非容器发起的请求/响应,暂排除配额问题。
解决方案
1. 禁用.NET HttpClient的分块编码自动处理
该错误与大响应体的分块传输(Chunked Encoding)有关,Cloud Run的网络层可能在分块数据传输中干扰了SSL解密。可以通过修改HttpClient的配置,强制禁用分块编码的自动处理:
var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.None, UseChunkedEncoding = false }; var httpClient = new HttpClient(handler);
2. 调整OpenSSL的记录大小限制
在Dockerfile的runtime阶段添加环境变量和配置,限制OpenSSL的SSL记录大小,避免大响应体导致的解密错误:
# 在runtime image阶段添加 ENV SSL_CIPHER_SUITE="DEFAULT@SECLEVEL=1" ENV SSL_MIN_PROTOCOL="TLSv1.2" ENV SSL_MAX_PROTOCOL="TLSv1.3" # 强制设置SSL记录最大长度为16KB RUN echo "ssl_conf = ssl_sect\n[ssl_sect]\nsystem_default = system_default_sect\n[system_default_sect]\nMaxRecordSize = 16384" >> /etc/ssl/openssl.cnf
3. 使用.NET的内置TLS实现替代OpenSSL
.NET 8默认在Linux上使用OpenSSL,可以通过环境变量切换到旧版HttpHandler实现,规避OpenSSL在大响应体下的解密问题:
# 在runtime image阶段添加环境变量 ENV DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
4. 适配网络MTU的缓冲区设置
虽然Cloud Run不允许直接修改MTU,但可以在应用中设置Socket的发送和接收缓冲区大小,间接适配网络MTU:
var socketHandler = new SocketsHttpHandler { SendBufferSize = 1460, // 匹配标准MTU 1500的有效载荷大小 ReceiveBufferSize = 1460 }; var httpClient = new HttpClient(socketHandler);
内容的提问来源于stack exchange,提问作者Vince.Bdn
相关产品推荐
相关产品推荐

