Scenario 10.1: TLS Server Setup

Category: TLS/mTLS
Complexity: ⭐⭐⭐ (Medium)
Prerequisites: Server certificate, private key
Estimated Time: 20-30 Minutes


Description

This scenario describes the setup of a TLS server with Post-Quantum secure certificates. TLS 1.3 is mandatory for modern security.

Components:


Workflow

flowchart LR CERT[Prepare Certificate] --> CHAIN[Create Chain] CHAIN --> CONFIG[Configure TLS] CONFIG --> TEST[Test] TEST --> DEPLOY[Deployment] style CONFIG fill:#e8f5e9


Code Example: ASP.NET Core Kestrel

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
 
var builder = WebApplication.CreateBuilder(args);
 
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(443, listenOptions =>
    {
        listenOptions.UseHttps(httpsOptions =>
        {
            // Load server certificate
            httpsOptions.ServerCertificate = LoadCertificateChain(
                "server.crt.pem",
                "server.key.pem",
                "intermediate-ca.crt.pem"
            );
 
            // Enforce TLS 1.3
            httpsOptions.SslProtocols = SslProtocols.Tls13;
 
            // Enable OCSP Stapling
            httpsOptions.OnAuthenticate = (context, sslOptions) =>
            {
                sslOptions.CertificateRevocationCheckMode = X509RevocationMode.Online;
            };
        });
 
        // Enable HTTP/2
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
    });
});
 
var app = builder.Build();
 
// Enable HSTS
app.UseHsts();
 
app.MapGet("/", () => "TLS Server active");
 
app.Run();
 
static X509Certificate2 LoadCertificateChain(
    string certPath,
    string keyPath,
    string chainPath)
{
    using var ctx = PqCryptoContext.Initialize();
 
    // Server certificate with private key
    var cert = ctx.LoadCertificateWithPrivateKey(certPath, keyPath, null);
 
    // Add chain (for complete chain)
    var intermediate = ctx.LoadCertificate(chainPath);
 
    // Create PFX with chain
    var pfxBytes = ctx.ExportToPfx(cert, cert.GetRSAPrivateKey(), new[] { intermediate }, null);
    return new X509Certificate2(pfxBytes);
}

Nginx Configuration

server {
    listen 443 ssl http2;
    server_name www.example.com;
 
    # Server certificate (with chain)
    ssl_certificate     /etc/nginx/ssl/server-chain.pem;
    ssl_certificate_key /etc/nginx/ssl/server.key.pem;
 
    # TLS 1.3 only
    ssl_protocols TLSv1.3;
 
    # Cipher suites (TLS 1.3 default)
    # ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    ssl_prefer_server_ciphers off;
 
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/ca-chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
 
    # Security Headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
 
    # Session configuration
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
 
    location / {
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Apache Configuration

<VirtualHost *:443>
    ServerName www.example.com
 
    # Enable SSL
    SSLEngine on
 
    # Certificates
    SSLCertificateFile      /etc/apache2/ssl/server.crt.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/server.key.pem
    SSLCertificateChainFile /etc/apache2/ssl/intermediate-ca.crt.pem
 
    # TLS 1.3 only
    SSLProtocol -all +TLSv1.3
 
    # OCSP Stapling
    SSLUseStapling On
    SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors off
 
    # HSTS
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
 
    # Disable compression (BREACH)
    SSLCompression off
 
    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Create Certificate Chain

# Server certificate + Intermediate = Chain
cat server.crt.pem intermediate-ca.crt.pem > server-chain.pem
 
# Verify order
openssl crl2pkcs7 -nocrl -certfile server-chain.pem | openssl pkcs7 -print_certs -noout
 
# Validate chain
openssl verify -CAfile root-ca.crt.pem -untrusted intermediate-ca.crt.pem server.crt.pem

Test TLS Configuration

# SSL Labs API (if public)
# https://www.ssllabs.com/ssltest/
 
# Local test with OpenSSL
openssl s_client -connect localhost:443 -tls1_3 -brief
 
# Check cipher suites
openssl s_client -connect localhost:443 -cipher 'TLS_AES_256_GCM_SHA384' </dev/null
 
# Check certificate chain
openssl s_client -connect localhost:443 -showcerts </dev/null 2>/dev/null | openssl x509 -text -noout
 
# Check OCSP Stapling
openssl s_client -connect localhost:443 -status </dev/null 2>/dev/null | grep -A 5 "OCSP Response"
 
# testssl.sh (comprehensive)
./testssl.sh localhost:443

C# Test Client

public async Task TestTlsConnection(string url)
{
    var handler = new HttpClientHandler
    {
        ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            Console.WriteLine($"Server: {cert.Subject}");
            Console.WriteLine($"Issuer: {cert.Issuer}");
            Console.WriteLine($"Algorithm: {cert.SignatureAlgorithm.FriendlyName}");
            Console.WriteLine($"Valid until: {cert.NotAfter}");
 
            if (chain != null)
            {
                Console.WriteLine($"Chain length: {chain.ChainElements.Count}");
                foreach (var element in chain.ChainElements)
                {
                    Console.WriteLine($"  - {element.Certificate.Subject}");
                }
            }
 
            if (errors != SslPolicyErrors.None)
            {
                Console.WriteLine($"SSL Errors: {errors}");
                return false;
            }
 
            return true;
        }
    };
 
    using var client = new HttpClient(handler);
    var response = await client.GetAsync(url);
 
    Console.WriteLine($"Status: {response.StatusCode}");
    Console.WriteLine($"Protocol: {response.Version}");
}

Industry-Specific TLS Requirements

Industry Minimum TLS Cipher Suites Special Feature
PCI-DSS TLS 1.2+ Strong ciphers Annual audit
HIPAA TLS 1.2+ AES-256 Audit logging
BSI TR-02102 TLS 1.2+ BSI-compliant suites PFS mandatory
Energy/SCADA TLS 1.2+ ICS-specific Long-term support

Relationship Scenario Description
Prerequisite 3.1 Server Certificate Create certificate
Next Step 10.2 TLS Client Configure client
Extension 10.3 mTLS Deployment Mutual authentication

« ← TLS Overview | ↑ Scenarios | 10.2 TLS Client → »


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