Enable Two-Way SSl Verification Between Reverse Proxy and Proxied Server
I have two servers now, one in Canada and one in France. Due to the disk storage, I put this site on the France server and build a reverse proxy on the Canada server for a better time delay. Because I don’t want users to access the France server, I enable proxy_ssl_verify and and ssl_client_verify in NGINX. This article records a brief process of the set up. All servers are with Debian Jessie and NGINX 1.11.5.
I use certtool from GnuTLS to generate CA and sign certificates. More certtool options can be referenced here.
Generating CA for each server
$ certtool --generate-privkey --outfile ca-key.pem
$ cat << _EOF_ >ca.tmpl
cn = "My Server"
organization = "MyCorp"
serial = 1
expiration_days = -1
ca
signing_key
cert_signing_key
crl_signing_key
_EOF_
$ certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
Generating a local server certificate for each server
I use ecc key for a better performance.
$ certtool --generate-privkey --ecc --outfile server-key.pem
$ cat << _EOF_ >server.tmpl
cn = "<IP or Hostname>"
organization = "MyCompany"
expiration_days = -1
signing_key
tls_www_server # use tls_www_client on reverse proxy server and tls_www_server on proxied server
_EOF_
$ certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
Now we have the needed certificates for SSL verify. Below is the SSL verify part of NGINX config and don’t forget to exchange the ca-cert.pem on two servers.
Proxied server NGINX config:
ssl_certificate /path-to/server-cert.pem;
ssl_certificate_key /path-to/server-key.pem;
ssl_client_certificate /path-to/ca-cert.pem;
ssl_verify_client on;
ssl_verify_depth 1;
Reverse proxy NGINX config:
proxy_pass <Hostname>;
proxy_ssl_certificate /path-to/server-cert.pem;
proxy_ssl_certificate_key /path-to/server-key.pem;
proxy_ssl_trusted_certificate /path-to/ca-cert.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 1;
Now we can set up two-way SSL verify between reverse proxy server and proxied server successfully. For better security, I also use some http headers like X-Frame-Options, X-XSS-Protection, X-Content-Type-Options and X-Content-Security-Policy. I use Mozilla SSL Configuration Generator to generate SSL cipher suite. And because the cpu of servers doesn’t support AES-NI, I build NGINX from source with openssl and Cloudflare openssl patch to let NGINX support ChaCha20 and Poly1305 cipher for a better performance.