Scenarij 10.3: Uvajanje mTLS

Kategorija: TLS/mTLS
Kompleksnost: ⭐⭐⭐⭐ (Visoka)
Predpogoji: Strežniški in odjemalčevi certifikati, PKI
Predviden čas: 30-45 minut


Opis

Ta scenarij opisuje popolno uvajanje mTLS infrastrukture za obojestransko avtentikacijo med odjemalci in strežniki.

Področja uporabe:

  • Zero-Trust arhitekture
  • Service-Mesh (Istio, Linkerd)
  • API varnost
  • Komunikacija mikrostoritev
  • Avtentikacija IoT naprav

Arhitektura

flowchart TD subgraph PKI ROOT[Korenski CA] --> INT_SRV[Vmesni CA za strežnike] ROOT --> INT_CLI[Vmesni CA za odjemalce] end subgraph Strežnik INT_SRV --> SRV_CERT[Strežniški certifikat] SRV_CERT --> API[API strežnik] end subgraph Odjemalci INT_CLI --> CLI1[Odjemalec 1] INT_CLI --> CLI2[Odjemalec 2] INT_CLI --> CLI3[Storitev A] end CLI1 <-->|mTLS| API CLI2 <-->|mTLS| API CLI3 <-->|mTLS| API


1. PKI struktura za mTLS

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
 
public class MtlsPkiSetup
{
    public void CreateMtlsPki(string basePath)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // Korenski 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);
 
        // Vmesni CA za strežnike
        using var serverIntKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
        var serverIntCert = CreateIntermediateCa(
            ctx, rootCert, rootKey, serverIntKey,
            "mTLS Server Intermediate CA",
            new[] { "dns:.example.com" }  // Omejitev imen
        );
        SaveCertAndKey(basePath, "server-int-ca", serverIntCert, serverIntKey);
 
        // Vmesni CA za odjemalce
        using var clientIntKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
        var clientIntCert = CreateIntermediateCa(
            ctx, rootCert, rootKey, clientIntKey,
            "mTLS Client Intermediate CA",
            null  // Brez omejitev imen za odjemalce
        );
        SaveCertAndKey(basePath, "client-int-ca", clientIntCert, clientIntKey);
 
        Console.WriteLine("mTLS PKI ustvarjen");
    }
}

2. Konfiguracija strežnika

// ASP.NET Core Kestrel mTLS
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(443, listenOptions =>
    {
        listenOptions.UseHttps(httpsOptions =>
        {
            // Strežniški certifikat
            httpsOptions.ServerCertificate = new X509Certificate2(
                "server.pfx", "ServerPassword!");
 
            // Zahtevanje odjemalčevega certifikata
            httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
 
            // Sprejeti CA-ji za odjemalce
            httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
            {
                // Sprejem samo certifikatov naše CA za odjemalce
                return ValidateClientCertificate(cert, chain);
            };
        });
    });
});
 
bool ValidateClientCertificate(X509Certificate2 cert, X509Chain? chain)
{
    // Nalaganje zaupanja vrednega CA za odjemalce
    var trustedClientCa = new X509Certificate2("client-int-ca.crt.pem");
 
    // Gradnja prilagojene verige
    var customChain = new X509Chain();
    customChain.ChainPolicy.CustomTrustStore.Add(trustedClientCa);
    customChain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
    customChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
 
    // Preverjanje razširjene uporabe ključa: clientAuth
    customChain.ChainPolicy.ApplicationPolicy.Add(
        new Oid("1.3.6.1.5.5.7.3.2"));
 
    return customChain.Build(cert);
}

3. Konfiguracija odjemalca

public HttpClient CreateMtlsClient(string clientCertPath, string clientKeyPath, string password)
{
    using var ctx = PqCryptoContext.Initialize();
 
    // Nalaganje odjemalčevega certifikata
    var clientCert = ctx.LoadCertificateWithPrivateKey(
        clientCertPath,
        clientKeyPath,
        password
    );
 
    // Shramba zaupanja za strežnik
    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;
 
            // Razširjena uporaba ključa: 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 povratni posrednik

server {
    listen 443 ssl http2;
    server_name api.example.com;
 
    # Strežniški certifikat
    ssl_certificate     /etc/nginx/ssl/server-chain.pem;
    ssl_certificate_key /etc/nginx/ssl/server.key.pem;
 
    # Avtentikacija odjemalca
    ssl_client_certificate /etc/nginx/ssl/client-ca-chain.pem;
    ssl_verify_client on;
    ssl_verify_depth 2;
 
    # Preverjanje CRL
    ssl_crl /etc/nginx/ssl/client-ca.crl;
 
    # TLS 1.3
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;
 
    # OCSP Stapling za strežniški certifikat
    ssl_stapling on;
    ssl_stapling_verify on;
 
    location / {
        # Posredovanje informacij o odjemalcu zaledni storitvi
        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 za vse storitve v imenskem prostoru
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT  # mTLS obvezen
---
# DestinationRule - mTLS za izhodne povezave
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: default
  namespace: production
spec:
  host: "*.production.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL  # Istio upravljani certifikati
---
# AuthorizationPolicy - Avtorizacija na podlagi certifikatov
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. Nadzor in beleženje

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(
                "mTLS zahteva: Subject={Subject}, Thumbprint={Thumbprint}, " +
                "Serial={Serial}, NotAfter={NotAfter}",
                clientCert.Subject,
                clientCert.Thumbprint,
                clientCert.SerialNumber,
                clientCert.NotAfter
            );
 
            // Opozorilo pri certifikatih, ki kmalu potečejo
            var daysUntilExpiry = (clientCert.NotAfter - DateTime.UtcNow).Days;
            if (daysUntilExpiry < 30)
            {
                _logger.LogWarning(
                    "Odjemalčev certifikat poteče čez {Days} dni: {Subject}",
                    daysUntilExpiry,
                    clientCert.Subject
                );
            }
        }
 
        await _next(context);
    }
}

Panožna uvajanja mTLS

Panoga Infrastruktura Rotacija certifikatov Posebnost
Cloud Native Istio/Linkerd Samodejno (SPIFFE) Service Mesh
Finančni sektor Strojni uravnalniki obremenitve 90 dni Podprto s HSM
Zdravstvo On-Premise 1 leto Air-Gap možen
IoT Robni prehod 2-5 let Brez povezave zmožno

Povezani scenariji

Povezava Scenarij Opis
Predpogoj 10.1 TLS strežnik Strežniška stran
Predpogoj 10.2 TLS odjemalec Odjemalčeva stran
Povezano 9.1 mTLS avtentikacija Avtentikacija
Razširitev 10.4 Hibridni TLS PQ nadgradnja

« ← 10.2 TLS odjemalec | ↑ Pregled TLS | 10.4 Hibridni TLS → »


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

Zuletzt geändert: dne 30.01.2026 ob 06:46