Skip to content

TLS Client Setup

yahor.mazko edited this page Aug 10, 2026 · 1 revision

This page describes how to configure TLS on the client side of a SharpRpc connection. For the server side see TLS Server Setup.

Enabling TLS

Client-side transport security is configured by passing a TcpSecurity instance to the TcpClientEndpoint constructor. Use TcpSecurity.None for plain TCP or SslSecurity for TLS:

var security = new SslSecurity();
var endpoint = new TcpClientEndpoint("myserver.com", 812, security);
var client = MyContract_Gen.CreateClient(endpoint);

If the server hosts multiple services on one port, specify the service name — TLS is configured per service binding on the server, so the client's security setting must match the security of the binding it connects to:

var endpoint = new TcpClientEndpoint("myserver.com", "func/ssl", 812, security);

Settings

All settings are configured on the SslSecurity instance before the endpoint is used.

Setting Type Default Description
serverCertValidator (constructor argument) RemoteCertificateValidationCallback null Custom validation of the server certificate. When null, standard SslStream validation is used (the certificate must chain to a trusted root and match the host name).
Protocols SslProtocols SslProtocols.None Allowed TLS protocol versions. None lets the operating system choose the best available version (recommended).
EnableRevocationCheck bool true Online revocation check of the server certificate chain. Disable for certificates that have no revocation infrastructure (e.g. self-signed).
ClientCertificates X509CertificateCollection null Certificates to present to the server for mutual TLS. See below.

Server certificate validation

When the server uses a certificate that does not chain to a trusted root (e.g. a self-signed certificate), pass a custom validator to the constructor. A typical approach is thumbprint pinning:

var security = new SslSecurity((sender, cert, chain, errors) =>
    cert is X509Certificate2 c && c.Thumbprint == ExpectedServerThumbprint)
{
    EnableRevocationCheck = false,
};

Returning false from the validator aborts the connection.

Mutual TLS (presenting a client certificate)

Available since version 1.9.22.

To present a client certificate when the server requests one, set ClientCertificates. The certificate must include its private key (e.g. loaded from a PFX file or a certificate store):

var clientCert = new X509Certificate2("client.pfx", "password");

var security = new SslSecurity(serverCertValidator)
{
    ClientCertificates = new X509CertificateCollection { clientCert },
};
var endpoint = new TcpClientEndpoint("myserver.com", 812, security);

Certificate selection rules:

  • A certificate is only transmitted if the server requests one (RequireClientCertificate = true on the server side). Otherwise nothing is sent, even if ClientCertificates is configured.
  • If the server supplies an acceptable-issuers list, the first certificate whose issuer matches is presented.
  • If no certificate matches (or the server sends no issuer list), the first certificate in the collection is presented. This makes self-signed client certificates work out of the box — the default .NET selection logic would silently send nothing for them.

Configuring more than one certificate is useful during certificate rotation (old and new certificate configured simultaneously) or when one client connects to environments with different CAs.

Error handling and diagnostics

  • A failed TLS handshake surfaces as an RpcException with RpcRetCode.InvalidCredentials; the message contains the underlying SslStream error.
  • When the server rejects the client certificate, the rejection may arrive after the client has already completed its side of the handshake (typical for TLS 1.2). In that case the connection is established from the client's point of view and then immediately drops on the first read/write. If connections consistently drop right after connecting, check the server log for certificate validation errors.

Clone this wiki locally