Caddy Reverse Proxy to Multiple Sites on Port 80

Whenever you are proxying to a https backend, there are two pitfalls:

  1. The Host header, which gets inherited from the connection/vhost by default
  2. The TLS SNI/server name, which sets the server name in the initial TLS handshakes with the upstream, basically. That’s before any headers (like the Host header) even get sent

Excerpts from reverse_proxy (Caddyfile directive) — Caddy Documentation

When proxying over HTTPS, you may need to override the Host header such that it matches the TLS SNI value, which is used by servers for routing and certificate selection. See the HTTPS section below for more details.

and

Since (most) headers retain their original value when being proxied, it is often necessary to override the Host header with the configured upstream address when proxying to HTTPS, such that the Host header matches the TLS ServerName value. For example:

reverse_proxy https://example.com {
	header_up Host {upstream_hostport}
}

If your config looks like

matice.com {
        reverse_proxy https://216.108.230.119
}

then Caddy keeps the Host header value set to matice.com, but the TLS server name will be set to 216.108.230.119, to which your upstream server says “nope”


Your workaround (putting the IP+hostname into the hosts file and pointing Caddy to the hostname) works, because Caddy will then use matice.com as TLS server name (SN)

Instead of that, you could also just make Caddy that you don’t want to read the SN from the upstream target (in your case IP) and override it:

matice.com {
	reverse_proxy https://216.108.230.119 {
		transport http {
			tls_server_name matice.com
		}
	}
}

Strictly speaking, you could also drop that leading https:// in your upstream target, because

  • tls uses HTTPS with the backend. This will be enabled automatically if you specify backends using the https:// scheme or port :443, or if any of the below tls_* options are configured.

but feel free to keep it for better readability or whatever /shrug

The actual is tls_server_name option is documented here and here

4 Likes