Caddy TLS Reverse Proxy in a FreeNAS Jail

Intended Audience

This post will be of interest if you want to access private network resources securely using subdomains (e.g. https://subdomain.mydomain.com.au) or subdirectories (e.g. https://mydomain.com.au/subdirectory) rather than with IP addresses and port numbers.

Assumptions

  1. You use a Fritz!Box for internet access.
  2. Your ISP supplies you with a dynamic IPv4 address.
  3. You are not in a double-NAT situation.
  4. Your ISP hasn’t deployed Carrier-Grade NAT (CGNAT)

Initial Build

To put it all together, refer to the section TLS with DNS Validation in the amazingly useful resource Reverse Proxy using Caddy (with optional automatic TLS). At the time of this build, I was using FreeNAS 11.3-U1 and Caddy 1.0.

Below are redacted screenshots that provide some clues on how all the various components work together. If all the ducks line up, Caddy will burst into life.

Caddy

For DNS validation, Caddy is built with the Cloudflare DNS provider plugin.

screenshot.198.png

Domain Registrar

As it’s providing DNS hosting, Cloudflare requires that the domain use its name servers.

screenshot.202.png

Cloudflare

Cloudflare records are configured for dynamic IP addresses.

screenshot.201.png

DNS-O-Matic

DNS-O-Matic is configured to update Cloudflare

screenshot.203.png

Fritz!Box

The Fritz!Box sends the updated external IP address to DNS-O-Matic.

screenshot.204.png

For certificate renewals to work, ports 80 and 443 need to remain open to the internet.

screenshot.205.png

Internet Service Provider (ISP)

Ensure your ISP is not blocking port 80 and 443.

screenshot.206.png

DNSMasq

Configure your local DNS resolver, in my case DNSMasq, to resolve the FQDN to the Caddy jail IP.

 address=/mydomain.com.au/10.1.1.30

Specific Configuration Examples

Several application scenarios including Caddyfile code blocks are described in the following sections.


Landing Page (www.mydomain.com.au, mydomain.com.au)

Caddyfile code block:

www.mydomain.com.au mydomain.com.au {
  tls {
  dns cloudflare
  }
  gzip
  root /usr/local/www/html/
  (Subdirectory code blocks are appended here)
}
(Subdomain code blocks are appended here)

The landing page index.html is located in /user/local/www/html/.


Heimdall Landing Page (www.mydomain.com.au, mydomain.com.au)

Caddyfile code block:

www.mydomain.com.au mydomain.com.au {
  tls {
  dns cloudflare
  }
  gzip 
  proxy / http://10.1.1.23 {
  transparent 
  }  
  (Subdirectory code blocks are appended here) 
} 
(Subdomain code blocks are appended here)

Plex (plex.mydomain.com.au – private network only)

Step 1: Add a Caddy code block

plex.mydomain.com.au {
  tls {
  dns cloudflare
  }
  gzip
  proxy / http://10.1.1.27:32400 {
  transparent
  }
}

Tautulli (mydomain.com.au/tautulli)

Step 1: Add a Caddy code block

  proxy /tautulli http://10.1.1.26:8181 {
  transparent
  header_upstream X-Forwarded-For {remote}
  }

Step 2: Set the HTTP Root setting in Tautulli to /tautulli.

screenshot.207.png


Transmission (mydomain.com.au/transmission)

Step 1: Add a Caddy code block

  proxy /transmission http://10.1.1.28:9091 {
  transparent
  }

Step 2: Whitelist the domain in Transmission 

Shell into the Transmission jail and stop Transmission.

service transmission stop

Edit the Transmission settings file.

nano /config/transmission-home/settings.json

Whitelist the FQDN.

"rpc-host-whitelist": "mydomain.com.au",

Configure Transmission login.

"rpc-authentication-required": true,
"rpc-password": "password",
"rpc-username": "username",

Save the changes and exit the editor. Restart Transmission.

service transmission start

Nextcloud (cloud.mydomain.com.au)

Step 1: Install Nextcloud

Using the resource Scripted installation of Nextcloud 18 in iocage jail, install Nextcloud at IP 10.1.1.29. Importantly, set HOST_NAME=”cloud.mydomain.com.au” and NO_CERT=1 in the script configuration file nextcloud-config. After installation, check that you can access the Nextcloud login page at http://10.1.1.29.

Step 2: Add a Caddy code block

cloud.mydomain.com.au {
  tls {
    dns cloudflare
  }
  gzip
  proxy / 10.1.1.29/ {
    transparent
  }
}

Step 3: Add a CNAME record for the subdomain

To access Nextcloud externally using this new address, at your DNS provider, add a CNAME record for the subdomain e.g. with Cloudflare

screenshot.210.png


Fritz!Box (gatekeeper.mydomain.com.au)

The Fritz!Box does use a Let’s Encrypt certificate to allow it to be accessed securely from the internet (see bottom half of the screenshot below). However, the FritzBox has a unique and unmemorable internet address and port (see top half of the screenshot). Furthermore, communication with the Fritz!Box on the local network is still unsecured.

screenshot.174.png

Using this Caddy resource, I’m able to address both these issues i.e. provide secure communications to the FritzBox both inside and outside the local network, and, use a memorable address to access it. It’s surprisingly straightforward to do, requiring just three steps.

Step 1: Add a Caddy code block

gatekeeper.mydomain.com.au {
  tls {
        dns cloudflare
  }
  gzip
  proxy / http://10.1.1.1/ {
        transparent
  }
}

Step 2: Add an exception for DNS rebind protection

In the Fritz!Box, add the address used in the Caddy code block as an exception for DNS rebind protection. If you stop at step 2, you will have secure communication with the Fritz!Box on the private network.

screenshot.175.png

Step 3: Add a CNAME record for the subdomain

To access the Fritz!Box externally using this new address, at your DNS provider, add a CNAME record for the subdomain e.g. with Cloudflare

screenshot.176.png

Troubleshooting Tools

Some useful tools for troubleshooting.

caddy.log

Shell into the Caddy jail.

Jails ⇒ transmission ⇒ Shell

View the log contents.

cat /var/log/caddy.log

Certificate search

Enter your domain name at https://crt.sh/ to see what certificates have been issued and when they expire.

References

  1. Reverse Proxy using Caddy (with optional automatic TLS)
  2. Wikipedia: Reverse proxy
  3. Forward Proxy vs. Reverse Proxy
  4. Wikipedia: TLS termination proxy
  5. Let’s Encrypt – How It Works
  6. Let’s Encrypt – Challenge Types
  7. Dynamic DNS settings for AVM FritzBox router
  8. How to set up DNS-O-MATIC for Cloudflare (and the other way around) and a FritzBox
  9. Manage dynamic IPs in Cloudflare DNS programmatically
  10. What is: Subdomain
  11. When to Use Subdomains and Subdirectories
  12. What Is Cloudflare And Should You Use It?
  13. What is Transport Layer Security (TLS)?
  14. Carrier-grade NAT
  15. Scripted installation of Nextcloud 18 in iocage jail

Keep Reading

PreviousNext

Comments

Leave a Reply