Matthew Evans

Infrastructure and Security Ninja. I know DevOps-fu.

Securing Your Nginx Reverse Proxy with a Cloudflare Authenticated Origin Pull

22 Sep 2018 » nginx, cloudflare, security

Pre-requisites needed:

  1. DNS hosting with Cloudflare
  2. A properly working Nginx Reverse Proxy

The purpose of this article:

  1. Use the DDoS, Security, and CDN features of Cloudflare, while isolating our infrastructure from the Internet-at-Large.
  2. Eliminate Let’s Encrypt from our local environment and thus, the renewal hassle.
  3. Install an ‘Authenticated Origin Pull’ certificate from Cloudflare to prevent unauthorized access to our Nginx Reverse Proxy.
  4. Install a free Cloudflare provided ‘Origin’ certificate into our Nginx environment to eliminate Let’s Encrypt, ensure all Cloudflare to Nginx traffic is encrypted with a valid certificate, and remove the certificate renewal burden for ~10 years.

Phase 1 - Gathering resources from Cloudflare:

  1. Log into your Cloudflare portal and go to the Crypto tab.
  2. Click Create Certificate in the Origin Certificates section.
  3. Private key type: ECDSA
  4. Click Next.
    • Note: I chose to let Cloudflare generate my private key and CSR, but you can always upload your own if you want enhanced security.
  5. Save your certificate to origin.crt and your key to origin.key.
  6. Download the Cloudflare ‘Authenticated Origin Pull’ certificate from the bottom of this page.
    • If you trust me (you shouldn’t), just right-click and ‘Save Target As …’ on this link.
  7. Save it as origin-pull.crt.

Phase 2 - Configuring your Nginx reverse proxy:

  1. Start by uploading all your certs to your Nginx server, making sure they are accessible by nginx.
    • FWIW - I use /etc/nginx/ssl
  2. Nginx has a master process that runs as root, so for maximum security you should make sure the certs are owned by root and only readable by that account.
    • chown root:root /etc/nginx/ssl/*
    • chmod 0600 /etc/nginx/ssl/*
  3. Your files should look like this after performing the steps above:

     [email protected]:/etc/nginx/ssl# ls -l
     -rw-------. 1 root root 1143 Jul 5 01:43 origin.crt
     -rw-------. 1 root root 241 Jul 5 01:43 origin.key
     -rw-------. 1 root root 2151 Jul 5 01:44 origin-pull.crt
  4. Edit your existing reverse proxy configuration file and add/modify to match as needed:

     server {
      listen 80 default_server;
      server_name _;
      return 301 https://$host$request_uri;
     server {
      listen 443 ssl http2;
      root /usr/share/nginx/html;
      ssl_certificate /etc/nginx/ssl/origin.crt;
      ssl_certificate_key /etc/nginx/ssl/origin.key;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers HIGH:!aNULL:!MD5;
      ssl_client_certificate /etc/nginx/ssl/origin-pull.crt;
      ssl_verify_client on;
  5. Verify your config is correct by issuing an nginx -t.

     [email protected]:/etc/nginx/ssl# nginx -t
     nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
     nginx: configuration file /etc/nginx/nginx.conf test is successful
  6. Reload nginx via your service manager (usually systemd):
    • systemctl reload nginx

You are now using a Cloudflare issued certificate that shouldn’t expire for 10 years and you are verifying that all requests to your Nginx reverse proxy are originating from Cloudflare, mitigating a man-in-the-middle attack on your reverse proxy. You can take this a step further by locking down port 80/443 to the IP ranges of Cloudflare in your firewall - a pfSense alias comes in very handy here.