Scenario 10.3: Deployment mTLS

Categoria: TLS/mTLS
Complessità: Alta
Prerequisiti: Certificati server e client, PKI
Tempo stimato: 30-45 minuti


Descrizione

Questo scenario descrive il deployment completo di un'infrastruttura mTLS per l'autenticazione reciproca tra client e server.

Ambiti di utilizzo:

  • Architetture Zero-Trust
  • Service-Mesh (Istio, Linkerd)
  • Sicurezza API
  • Comunicazione microservizi
  • Autenticazione dispositivi IoT

Architettura

flowchart TD subgraph PKI ROOT[Root-CA] --> INT_SRV[Intermediate-CA Server] ROOT --> INT_CLI[Intermediate-CA Client] end subgraph Server INT_SRV --> SRV_CERT[Certificato server] SRV_CERT --> API[API Server] end subgraph Clients INT_CLI --> CLI1[Client 1] INT_CLI --> CLI2[Client 2] INT_CLI --> CLI3[Servizio A] end CLI1 <-->|mTLS| API CLI2 <-->|mTLS| API CLI3 <-->|mTLS| API


1. Struttura PKI per mTLS

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
 
public class MtlsPkiSetup
{
    public void CreateMtlsPki(string basePath)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // Root-CA
        using var rootKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
        var rootCert = ctx.CreateSelfSignedCertificate(
            rootKey,
            new DnBuilder().AddCN("mTLS Root CA").AddO("Example").Build(),
            validDays: 3650,
            extensions: new ExtBuilder()
                .BasicConstraints(ca: true, pathLengthConstraint: 2, critical: true)
                .KeyUsage(KeyUsageFlags.KeyCertSign | KeyUsageFlags.CrlSign, critical: true)
                .Build()
        );
        SaveCertAndKey(basePath, "root-ca", rootCert, rootKey);
 
        // Intermediate-CA Server
        using var serverIntKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
        var serverIntCert = CreateIntermediateCa(
            ctx, rootCert, rootKey, serverIntKey,
            "mTLS Server Intermediate CA",
            new[] { "dns:.example.com" }  // Name Constraint
        );
        SaveCertAndKey(basePath, "server-int-ca", serverIntCert, serverIntKey);
 
        // Intermediate-CA Client
        using var clientIntKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
        var clientIntCert = CreateIntermediateCa(
            ctx, rootCert, rootKey, clientIntKey,
            "mTLS Client Intermediate CA",
            null  // Nessun Name Constraint per client
        );
        SaveCertAndKey(basePath, "client-int-ca", clientIntCert, clientIntKey);
 
        Console.WriteLine("PKI mTLS creata");
    }
}

2. Configurazione server

// ASP.NET Core Kestrel mTLS
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(443, listenOptions =>
    {
        listenOptions.UseHttps(httpsOptions =>
        {
            // Certificato server
            httpsOptions.ServerCertificate = new X509Certificate2(
                "server.pfx", "ServerPassword!");
 
            // Richiedere certificato client
            httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
 
            // CA client accettate
            httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
            {
                // Accettare solo certificati della nostra Client-CA
                return ValidateClientCertificate(cert, chain);
            };
        });
    });
});
 
bool ValidateClientCertificate(X509Certificate2 cert, X509Chain? chain)
{
    // Caricare CA client trusted
    var trustedClientCa = new X509Certificate2("client-int-ca.crt.pem");
 
    // Costruire chain personalizzata
    var customChain = new X509Chain();
    customChain.ChainPolicy.CustomTrustStore.Add(trustedClientCa);
    customChain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
    customChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
 
    // Verificare Extended Key Usage: clientAuth
    customChain.ChainPolicy.ApplicationPolicy.Add(
        new Oid("1.3.6.1.5.5.7.3.2"));
 
    return customChain.Build(cert);
}

3. Configurazione client

public HttpClient CreateMtlsClient(string clientCertPath, string clientKeyPath, string password)
{
    using var ctx = PqCryptoContext.Initialize();
 
    // Caricare certificato client
    var clientCert = ctx.LoadCertificateWithPrivateKey(
        clientCertPath,
        clientKeyPath,
        password
    );
 
    // Trust Store server
    var trustedServerCa = ctx.LoadCertificate("server-int-ca.crt.pem");
 
    var handler = new HttpClientHandler
    {
        ClientCertificateOptions = ClientCertificateOption.Manual,
        SslProtocols = SslProtocols.Tls13,
 
        ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            var customChain = new X509Chain();
            customChain.ChainPolicy.CustomTrustStore.Add(trustedServerCa);
            customChain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
 
            // Extended Key Usage: serverAuth
            customChain.ChainPolicy.ApplicationPolicy.Add(
                new Oid("1.3.6.1.5.5.7.3.1"));
 
            return customChain.Build(cert);
        }
    };
 
    handler.ClientCertificates.Add(clientCert);
 
    return new HttpClient(handler)
    {
        DefaultRequestHeaders = { { "User-Agent", "mTLS-Client/1.0" } }
    };
}

4. Nginx mTLS Reverse Proxy

server {
    listen 443 ssl http2;
    server_name api.example.com;
 
    # Certificato server
    ssl_certificate     /etc/nginx/ssl/server-chain.pem;
    ssl_certificate_key /etc/nginx/ssl/server.key.pem;
 
    # Autenticazione client
    ssl_client_certificate /etc/nginx/ssl/client-ca-chain.pem;
    ssl_verify_client on;
    ssl_verify_depth 2;
 
    # Verifica CRL
    ssl_crl /etc/nginx/ssl/client-ca.crl;
 
    # TLS 1.3
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;
 
    # OCSP Stapling per cert server
    ssl_stapling on;
    ssl_stapling_verify on;
 
    location / {
        # Inoltrare info client al backend
        proxy_set_header X-Client-Cert-Subject $ssl_client_s_dn;
        proxy_set_header X-Client-Cert-Issuer $ssl_client_i_dn;
        proxy_set_header X-Client-Cert-Serial $ssl_client_serial;
        proxy_set_header X-Client-Cert-Fingerprint $ssl_client_fingerprint;
        proxy_set_header X-Client-Verify $ssl_client_verify;
 
        proxy_pass http://backend:8080;
    }
}

5. Kubernetes mTLS (Istio)

# PeerAuthentication - mTLS per tutti i servizi nel namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT  # mTLS obbligatorio
---
# DestinationRule - mTLS per connessioni in uscita
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: default
  namespace: production
spec:
  host: "*.production.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL  # Certificati gestiti da Istio
---
# AuthorizationPolicy - Autorizzazione basata su certificato
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: api-access
  namespace: production
spec:
  selector:
    matchLabels:
      app: api-server
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/production/sa/frontend-service"]
        namespaces: ["production"]

6. Monitoring e logging

public class MtlsLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<MtlsLoggingMiddleware> _logger;
 
    public MtlsLoggingMiddleware(RequestDelegate next, ILogger<MtlsLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }
 
    public async Task InvokeAsync(HttpContext context)
    {
        var clientCert = context.Connection.ClientCertificate;
 
        if (clientCert != null)
        {
            _logger.LogInformation(
                "Richiesta mTLS: Subject={Subject}, Thumbprint={Thumbprint}, " +
                "Serial={Serial}, NotAfter={NotAfter}",
                clientCert.Subject,
                clientCert.Thumbprint,
                clientCert.SerialNumber,
                clientCert.NotAfter
            );
 
            // Avviso per certificati in scadenza
            var daysUntilExpiry = (clientCert.NotAfter - DateTime.UtcNow).Days;
            if (daysUntilExpiry < 30)
            {
                _logger.LogWarning(
                    "Certificato client scade tra {Days} giorni: {Subject}",
                    daysUntilExpiry,
                    clientCert.Subject
                );
            }
        }
 
        await _next(context);
    }
}

Deployment mTLS specifici per settore

Settore Infrastruttura Rotazione cert Particolarità
Cloud Native Istio/Linkerd Automatica (SPIFFE) Service Mesh
Settore finanziario Hardware LB 90 giorni Supportato HSM
Sanità On-Premise 1 anno Air-Gap possibile
IoT Edge Gateway 2-5 anni Funzionamento offline

Scenari correlati

Relazione Scenario Descrizione
Prerequisito 10.1 Server TLS Lato server
Prerequisito 10.2 Client TLS Lato client
Correlato 9.1 Auth mTLS Autenticazione
Estensione 10.4 TLS ibrido Upgrade PQ

« ← 10.2 Client TLS | ↑ Panoramica TLS | 10.4 TLS ibrido → »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: il 30/01/2026 alle 07:02