Fixing .NET SslException on Linux Container
.NET 8 / C# LINUX / OPENSSL GOOGLE CLOUD RUN
Fixing .NET SslException on Linux Container
Deployments: The ‘RequireEncryption’ Policy Pitfall
Author: DevOps & Software Architecture Engineering Category: Troubleshooting & Cloud Deployments
A common friction point when migrating .NET services from Windows development machines to Linux
container environments (such as Google Cloud Run, AWS Fargate, or Kubernetes) is subtle differences in
native TLS/SSL implementations. Code that executes perfectly on local Windows workstations can abruptly
fail in production container environments with mysterious cryptographic stack traces.
This technical note breaks down a classic Windows vs. Linux SSL interop failure in .NET and presents the
resolution.
- The Symptom
Consider a standard scenario: A .NET application makes outbound HTTPS requests using HttpClient or
SocketsHttpHandler . During local testing on Windows, all HTTP operations complete cleanly. However, as
soon as the service is deployed to a Linux container environment, all outbound HTTPS calls fail with an
HttpRequestException wrapping an underlying SslException .
The application logs reveal an error trace similar to the following:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner
exception.
—> System.Security.Authentication.AuthenticationException: Authentication failed, see inner
exception.
—> Interop+OpenSsl+SslException: The ‘RequireEncryption’ encryption policy is not supported
by this installation of OpenSSL.
at Interop.OpenSsl.CalculateEffectiveProtocols(SslAuthenticationOptions
sslAuthenticationOptions)
at Interop.OpenSsl.GetOrCreateSslContextHandle(SslAuthenticationOptions
sslAuthenticationOptions, Boolean allowCached)
at Interop.OpenSsl.AllocateSslHandle(SslAuthenticationOptions sslAuthenticationOptions)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeDeleteSslContext& context,
ReadOnlySpan`1 inputBuffer, Int32& consumed, SslAuthenticationOptions
sslAuthenticationOptions)
Despite the exception mentioning RequireEncryption , the connection attempt aborts before any HTTP
traffic or TLS handshaking can take place.
2. The Root Cause
.NET relies on operating system abstraction layers for network security:
DevOps & .NET Engineering Engineering Notes Page 1 of 3
Platform Underlying Security Layer Encryption Policy Handling
Windows SChannel (Schannel.dll)
Natively supports granular policy enforcement including
EncryptionPolicy.RequireEncryption via OS APIs.
Linux
OpenSSL ( libssl /
Interop.OpenSsl )
Relies on OpenSSL’s native cipher suite negotiation. Does
not support mapping .NET’s legacy OS-level policy flags
down to OpenSSL constructs.
In .NET, SslClientAuthenticationOptions.EncryptionPolicy defaults to
EncryptionPolicy.RequireEncryption . When running on Windows, SChannel handles this flag natively.
When executing on Linux, .NET routes TLS setup through Interop.OpenSsl . Upon inspecting the policy,
the Linux interop layer explicitly throws an exception because OpenSSL cannot bind .NET’s policy enum
directly to an OpenSSL context flag.
3. The Solution
To resolve this issue without altering container base images or lowering system-wide security configurations,
explicitly set the EncryptionPolicy property inside your SslClientAuthenticationOptions to
EncryptionPolicy.AllowNoEncryption .
Myth vs. Reality: Setting EncryptionPolicy.AllowNoEncryption does NOT disable TLS encryption or
allow unencrypted plain text. Instead, it instructs .NET’s interop layer to pass cipher negotiation directly to
OpenSSL’s internal engine rather than attempting Windows-style pre-flight policy validation.
Updated Code Example
Modify your SocketsHttpHandler or SslStream configuration as follows:
var handler = new SocketsHttpHandler
{
AutomaticDecompression = DecompressionMethods.All,
SslOptions = new SslClientAuthenticationOptions
{
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13,
// Bypasses .NET OpenSSL interop check on Linux while maintaining full TLS encryption
EncryptionPolicy = EncryptionPolicy.AllowNoEncryption
}
};
using var client = new HttpClient(handler);
- Deployment Notes for Serverless & Containers
No Dockerfile modifications required: If you use Buildpack-based continuous deployment (e.g.,
gcloud run deploy directly from source code), this code-level fix is sufficient. Rebuilding and
redeploying the application source solves the problem immediately.
•
DevOps & .NET Engineering Engineering Notes Page 2 of 3
Cross-Platform Consistency: EncryptionPolicy.AllowNoEncryption works identically across both
Windows (SChannel) and Linux (OpenSSL) environments, making your codebase cross-platform
compliant.
Document generated for technical reference & troubleshooting archive.