Reverse proxy to another server

1. The problem I’m having:

Caddy reverse proxy works fine for services running on localhost, however, it is failing to forward connection to service running on another host.

2. Error messages and/or full log output:

{"level":"error","ts":1682112395.053308,"logger":"http.log.error","msg":"read tcp 192.168.0.183:57463->192.168.0.1:3001: read: connection reset by peer","request":{"remote_ip":"172.70.207.54","remote_port":"22698","proto":"HTTP/2.0","method":"GET","host":"ntop.greghao.com","uri":"/favicon.ico","headers":{"X-Forwarded-For":["99.150.202.198"],"Sec-Ch-Ua-Platform":["\"macOS\""],"Sec-Fetch-Dest":["image"],"Referer":["https://ntop.greghao.com/"],"Cf-Ray":["7bb8b4c50be308b2-LAX"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-origin"],"Sec-Fetch-Mode":["no-cors"],"Cookie":[],"Cf-Connecting-Ip":["99.150.202.198"],"Cdn-Loop":["cloudflare"],"Sec-Ch-Ua":["\"Chromium\";v=\"112\", \"Google Chrome\";v=\"112\", \"Not:A-Brand\";v=\"99\""],"Dnt":["1"],"Accept":["image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"],"Accept-Language":["en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7"],"Cf-Ipcountry":["US"],"Accept-Encoding":["gzip"],"X-Forwarded-Proto":["https"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"ntop.greghao.com"}},"duration":0.004290625,"status":502,"err_id":"hyfsz6xjh","err_trace":"reverseproxy.statusError (reverseproxy.go:1299)"}

3. Caddy version:

❯ caddy version
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

a. System environment:

MacOS Ventura 13.3.1

b. Command:

brew services caddy start

d. My complete Caddy config:

❯ caddy fmt
{
	email ---
}
(basic-auth) {
	basicauth / {
		--- ---
	}
}

sabnzbd.greghao.com {
	reverse_proxy http://127.0.0.1:8080
}

portainer.greghao.com {
	reverse_proxy http://127.0.0.1:9090
}

trans.greghao.com {
	reverse_proxy http://127.0.0.1:9091
}

radarr.greghao.com {
	import basic-auth
	reverse_proxy http://127.0.0.1:9092
}

sonarr.greghao.com {
	import basic-auth
	reverse_proxy http://127.0.0.1:9093
}

tautulli.greghao.com {
	reverse_proxy http://127.0.0.1:9094
}

www.greghao.com {
	import basic-auth
	reverse_proxy http://127.0.0.1:9095
}

jackett.greghao.com {
	import basic-auth
	reverse_proxy http://127.0.0.1:9096
}

overseerr.greghao.com {
	reverse_proxy http://127.0.0.1:9097
}

ntop.greghao.com {
	import basic-auth
        reverse_proxy * http://192.168.0.1:3001
}

From what I can see from ntopng’s documentation (assuming you are using this software based on the port and subdomain), port :3000 is http and :3001 is https.

You are trying to force http:// on :3001, the https:// port, in http://192.168.0.1:3001.
This won’t work.
Use reverse_proxy * http://192.168.0.1:3000 instead (or reserve_proxy 192.168.0.1:3000 because http:// is the default for reverse_proxy upstreams and * can be omitted, as it is also the default matcher.

Thanks for the quick reply. Updating to port 3000 did solve my issue! I’m now able to connect. But interestingly, connecting to http://ntop.greghao.com I’m redirected to https://ntop.greghao.com:3001 which spits out a SSL cert error.

In trying to solve this, I attempted to update to the below:

ntop.greghao.com {
	reverse_proxy https://192.168.0.1:3001
}

Which unfortunately spat out an error.

{"level":"error","ts":1682126387.1057112,"logger":"http.log.error","msg":"x509: certificate signed by unknown authority","request":{"remote_ip":"172.70.210.54","remote_port":"33336","proto":"HTTP/2.0","method":"GET","host":"ntop.greghao.com","uri":"/favicon.ico","headers":{"Cf-Ipcountry":["US"],"Accept-Language":["en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Sec-Ch-Ua-Mobile":["?0"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"],"Accept":["image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"],"Sec-Fetch-Site":["same-origin"],"Sec-Fetch-Mode":["no-cors"],"Cdn-Loop":["cloudflare"],"X-Forwarded-Proto":["https"],"Cf-Connecting-Ip":["99.150.202.198"],"Referer":["https://ntop.greghao.com/"],"Cookie":[],"Sec-Ch-Ua-Platform":["\"macOS\""],"Sec-Fetch-Dest":["image"],"Priority":["u=1, i"],"Cf-Ray":["7bba0a5f49457c73-LAX"],"Authorization":[],"Sec-Ch-Ua":["\"Chromium\";v=\"112\", \"Google Chrome\";v=\"112\", \"Not:A-Brand\";v=\"99\""],"Dnt":["1"],"Accept-Encoding":["gzip"],"X-Forwarded-For":["99.150.202.198"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"ntop.greghao.com"}},"duration":0.015209791,"status":502,"err_id":"7y9sjccn0","err_trace":"reverseproxy.statusError (reverseproxy.go:1299)"}

Caddy (and your whole system actually) does not trust ntop’s certificate, as it isn’t issued from a globally trusted CA like Lets Encrypt or ZeroSSL, but instead probably self-signed.

You can either import ntop’s certificate into your system’s trust store, or disable tls verification in Caddy for that upstream.
I won’t be able to provide a guide or help on how to do the former. You can probably find a lot of guides out there in the wild already.
The latter is less secure due to being vulnerable to MITM attacks between Caddy and your ntop server, but also less involved:

ntop.greghao.com {
	reverse_proxy 192.168.0.1:3001 {
		transport http {
			tls_insecure_skip_verify
		}
	}
}

Note that I removed the https:// prefix from 192.168.0.1:3001, because tls_insecure_skip_verify automatically forces https://.

Exerpt from the reverse_proxy docs (transport http section):

  • 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.

You may or may not also have to set tls_server_name. That depends on how ntop handles things, which I simply don’t know.
Also see reverse_proxy docs (HTTPS section).

Edit: fixed my typo (transport http { } must go in reverse_proxy { })

4 Likes

Thank you! I got the above to work with some slight fix. Just in case anyone else needs this in the future, there’s one additional {} pair that’s necessary:

ntop.greghao.com {
	reverse_proxy 192.168.0.1:3001 {
	transport http {
		tls_insecure_skip_verify
		}
	}
}

Many thanks again for your help :slight_smile: :slight_smile:

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.