Distributed Denial Of Service in Chi with Mutual Tls
Distributed Denial Of Service in Chi with Mutual Tls — how this specific combination creates or exposes the vulnerability
In Chi, enabling Mutual TLS (mTLS) means the server requests and validates client certificates before proceeding with application logic. While mTLS strengthens authentication, it can change the timing and resource profile of requests, which in turn can affect the Distributed Denial of Service (DDoS) surface. When mTLS is enforced, the server must perform extra work—parsing certificates, verifying signatures against a trusted pool, and possibly checking revocation via CRL or OCSP—before the request is accepted. If an attacker sends many connections with invalid or heavy certificates, or floods the endpoint with TLS handshakes that fail after the cryptographic verification step, this can consume CPU and memory, contributing to resource exhaustion.
Another specific risk in Chi arises from how long-lived mTLS sessions and connection pools interact with DDoS. For example, if the server maintains many open mTLS connections and the client certificate validation is synchronous and blocking, an attacker can keep connections open (for example, by sending incomplete Client Hellos or by manipulating the TLS state machine) to exhaust file descriptors or thread pools. Additionally, if the server routes requests based on certificate properties (common in microservice authorization) and the validation logic is not bounded, crafted certificates with deeply nested or large attributes can increase parsing time, effectively turning a cryptographic check into a vector for CPU-based DDoS.
DDoS in this context is not about overwhelming network bandwidth alone, but about exploiting the combined cost of mTLS verification and application processing in Chi. Because mTLS adds mandatory cryptographic work before routing or business checks, the cost per request is higher than in plaintext or one-way TLS scenarios. If rate limiting or concurrency controls are configured at the HTTP handler level without accounting for mTLS overhead, an attacker can send fewer connections than in a non-mTLS setup and still degrade service. Understanding this helps you design mitigations that consider both protocol costs and application-level backpressure.
Mutual Tls-Specific Remediation in Chi — concrete code fixes
To reduce DDoS risk while keeping mTLS in Chi, focus on bounding certificate validation work, limiting concurrency, and failing fast on obviously invalid handshakes. The following Chi code examples show practical patterns.
1. Limit concurrency and set timeouts on the HTTP server
Control the maximum number of concurrent requests and enforce deadlines so that resource exhaustion is less likely. This does not depend on whether mTLS is used, but it is more important when each request is more expensive.
using System.Net;
using Chi;
var host = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
options.Limits.KeepAliveTimeout = TimeSpan.FromSeconds(30);
options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
})
.Configure(app =>
{
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", () => "OK");
});
})
.UseUrls("https://*:5001");
})
.Build();
await host.RunAsync();
2. Use a bounded client certificate policy and cache validation results
Avoid performing expensive checks on every request by using a custom policy that validates only what you need and by caching results where appropriate. In Chi, you typically configure this via Kestrel options.
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Server.Kestrel.Https;
var host = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.AllowedCipherSuites = new[]
{
// Prefer cipher suites that provide forward secrecy and are efficient
TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
};
httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
{
// Basic, bounded checks to avoid expensive or unbounded work
if (cert is null) return false;
if (cert.NotAfter < DateTimeOffset.UtcNow) return false;
if (cert.NotBefore > DateTimeOffset.UtcNow) return false;
// Use a bounded chain policy to avoid deep or malicious chains
var policy = new X509ChainPolicy
{
RevocationMode = X509RevocationMode.NoCheck, // Avoid OCSP/CRL DDoS surface
VerificationFlags = X509VerificationFlags.NoFlag
};
using var chain = new X509Chain();
chain.ChainPolicy = policy;
bool isValid = chain.Build(cert);
return isValid;
};
});
})
.UseUrls("https://*:5001");
})
.Build();
await host.RunAsync();
3. Fail fast with middleware for obviously malformed requests
Add lightweight middleware early in the pipeline to reject requests that cannot be valid mTLS requests, reducing wasted work downstream.
app.Use(async (context, next) =>
{
// If TLS is not established or client cert is missing, fail fast
if (!context.Request.IsHttps || context.Connection.ClientCertificate is null)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("TLS required");
return;
}
await next();
});
4. Prefer session resumption and limit certificate chain depth
Configure Kestrel to favor session tickets and limit validation complexity. This reduces per-handshake CPU cost and lowers the chance of CPU-heavy certificate chains causing DoS.
// In UseKestrel configuration
options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13;
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
// Prefer ECDHE cipher suites and avoid legacy algorithms
});