I am using Yarp as a load balancer for ASP.NET applications. The ASP.NET applications require a client certificate.
I am having a problem where I cannot set the ClientCertificate as part of the handler.SSLOptions.ClientCertificate unless I hardcode the certificate in the Yarp initialization. Instead of hardcoding the certificate path, I want to take the certificate that is sent in with the request to Yarp and then dynamically set the handler.SSLOptions.ClientCertificate with that certificate so it is sent to the destination. If I use the AddTransforms, AddClientCertHeader, it does properly relay the certificate, but it puts it in the request header, not the handler.SSLOptions.ClientCertificate.
Thank you very much for any help you may offer and I hope you have great day coding!
Screenshot of HttpClient Setup:
Screenshot of Transform Setup:
When I try this code block, the certificate is set perfectly. However, I can only use one certificate that is hardcoded.
builder.Services.AddReverseProxy()
.ConfigureHttpClient((context, handler) =>
{
handler.SslOptions.ClientCertificates = new X509Certificate2Collection(clientCert);
})
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
When I try this code block, the calling certificate is properly relayed, but it only allows me to put it in the header.
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
.AddTransforms(builderContext =>
{
builderContext.AddClientCertHeader(headerName: "ssl.ClientCertificate");
});
YARP can't use the incoming client certificate as a client certificate, because it lacks the private key.
Setting handler.SslOptions.ClientCertificate lets the YARP server authenticate to the backend... it's not representing a user, but the YARP server/service itself.
ClientCertHeader is the only way that YARP (or any proxy) can forward the information about the TLS client cert it saw. If it could re-assert the certificate than anyone with man-in-the-middle (MitM) could also do so, and that would fundamentally break mutual authentication.
If it's an application requirement that it use TLS Client Authentication then you'll have to "directly" connect to the application (which can still involve NAT/LB/routing, but not "proxying").