You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:05:15