Implementing Mutual TLS Authentication with Nginx

Generating Certificates

To establish mutual authentication, you must first create a Certificate Authority (CA) and sign your server and client certificates. Use the following commands to generate the necessary keys and certifictaes:

# Generate the root CA private key
openssl genrsa -out root_authority.key 4096
# Generate the root CA self-signed certificate
openssl req -new -x509 -days 3650 -key root_authority.key -out root_authority.crt

# Generate server private key
openssl genrsa -out service.key 4096
# Generate server certificate signing request (CSR)
openssl req -new -key service.key -out service.csr
# Sign the server CSR with the root CA
openssl x509 -req -in service.csr -CA root_authority.crt -CAkey root_authority.key -CAcreateserial -out service.crt -days 3650

# Generate client private key
openssl genrsa -out peer.key 4096
# Generate client CSR
openssl req -new -key peer.key -out peer.csr
# Sign the client CSR with the root CA
openssl x509 -req -in peer.csr -CA root_authority.crt -CAkey root_authority.key -CAcreateserial -out peer.crt -days 3650

Configuring Nginx as an SSL Server

To enforce mTLS, the Nginx server must be configured to verify client certificates against your established CA.

server {
    listen 8080 ssl;
    
    ssl_certificate /path/to/service.crt;
    ssl_certificate_key /path/to/service.key;
    
    # Require client certificate verification
    ssl_client_certificate /path/to/root_authority.crt;
    ssl_verify_client on;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    
    location / {
        return 200 "mTLS connection established";
    }
}

Configuring Nginx as an SSL Proxy

When Nginx acts as a proxy for an upstream mTLS service, it must present the client certificate and establish trust for the upstream server.

server {
    listen 8081;
    
    location / {
        proxy_pass https://backend.example.com;
        
        # Client side authentication credentials
        proxy_ssl_certificate /path/to/peer.crt;
        proxy_ssl_certificate_key /path/to/peer.key;
        
        # Trusted CA for verifying the upstream server's certificate
        proxy_ssl_trusted_certificate /path/to/root_authority.crt;
        proxy_ssl_verify on;
        proxy_ssl_server_name on;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Tags: nginx ssl mtls openssl Security

Posted on Thu, 07 May 2026 10:53:29 +0000 by jrodd32