How to Build Transparent Encrypted Channels Between Data Centers with mTLS and Nginx

This guide explains how to securely connect two data‑center deployments over the public Internet by using TLS/mTLS, Certificate Authorities, and Nginx proxy configurations, providing step‑by‑step certificate generation, server and client setup, and both HTTP and TCP stream examples.

Programmer DD
Programmer DD
Programmer DD
How to Build Transparent Encrypted Channels Between Data Centers with mTLS and Nginx

When deploying services across data centers without a dedicated line, traffic must traverse the public Internet, requiring security measures such as allowing only known IPs and encrypting the traffic.

Only allow known IPs (firewall or iptables).

Encrypt the traffic.

The article explains TLS/SSL fundamentals, the need for asymmetric encryption, how certificates prove identity, the role of Certification Authorities (CAs), and why certificate validation is essential.

TLS/SSL Principles

TLS encrypts data in transit and prevents man‑in‑the‑middle attacks. It uses a public‑key pair: the public key is published in a certificate, the private key remains secret. Data encrypted with the public key can only be decrypted with the private key, and the private key can sign data that anyone can verify with the public key.

During a TLS handshake the client downloads the server’s certificate, encrypts a random value with the server’s public key, and the server decrypts it with its private key, establishing a shared secret for symmetric encryption.

Beyond encryption, the client must also verify that the certificate is issued by a trusted CA and that the certificate belongs to the claimed domain.

Certificate Authority (CA) Role

A CA is a trusted third‑party that signs certificates after verifying the applicant’s ownership of the domain. Clients trust a CA’s root certificate stored locally (e.g., /etc/ssl/certs). The trust chain may include intermediate CAs.

CA responsibilities include protecting its private key, validating certificate requests, and revoking mis‑issued certificates promptly.

Mutual TLS (mTLS)

mTLS adds client authentication: after the server presents its certificate, the client also presents its own certificate, which the server validates against the same trusted CA.

Solution: Transparent Encrypted Channel with Nginx

Two Nginx instances are deployed, one in each data center, and they authenticate each other via mTLS. Applications send plain HTTP to the local Nginx, which encrypts the traffic to the remote Nginx.

Certificate Generation

Generate a CA key (password‑protected) and self‑signed root certificate:

$ openssl genrsa -des3 -out ca.key 4096
$ openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Generate a server key and CSR, then sign it with the CA:

$ openssl genrsa -out server.key 4096
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Generate a client key and certificate similarly.

Remote Nginx (Server) Configuration

server {
    listen 443 ssl;
    server_name _;
    ssl_certificate /home/vagrant/cert/server.crt;
    ssl_certificate_key /home/vagrant/cert/server.key;
    ssl_verify_client on;
    ssl_client_certificate /home/vagrant/cert/ca.crt;
    location / { proxy_pass http://127.0.0.1:8000; }
}

Run a FastAPI application on port 8000 behind this Nginx.

Local Nginx (Client) Configuration

upstream remote { server 127.0.0.1:443; }
server {
    listen 80;
    location / {
        proxy_pass https://remote;
        proxy_ssl_trusted_certificate /home/vagrant/cert/ca.crt;
        proxy_ssl_verify on;
        proxy_ssl_server_name on;
        proxy_ssl_name proxy.example.com;
        proxy_ssl_certificate /home/vagrant/cert/client.crt;
        proxy_ssl_certificate_key /home/vagrant/cert/client.key;
    }
}

Clients can now curl the local Nginx (port 80) and the request is encrypted to the remote Nginx without modifying application code.

TCP Stream Proxy Example (Redis)

Replace the HTTP proxy with a TCP stream proxy to forward Redis traffic securely.

stream {
    server {
        listen 443 ssl;
        proxy_pass 127.0.0.1:6379;
        ssl_certificate /home/vagrant/cert/server.crt;
        ssl_certificate_key /home/vagrant/cert/server.key;
        ssl_verify_client on;
        ssl_client_certificate /home/vagrant/cert/ca.crt;
    }
}

Local Nginx forwards port 80 to the remote stream using similar mTLS settings.

References are listed at the end of the original article.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

encryptionTLSCertificate AuthoritymTLS
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.