Redirect reverse proxy to /path

1. Caddy version (caddy version):

v2.5.1

2. How I run Caddy:

Command line (CLI)

a. System environment:

Windows Server 2016

b. Command:

caddy_windows_amd64.exe run --watch

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:

{
	http_port 80
	https_port 443
}
Server2016, localhost, 127.0.0.1, 10.10.7.10 {
	log {
		level DEBUG
		format console
		output file ./log/caddy.log
	}
	tls ./certs/server.pem ./certs/server.key {
		protocols tls1.2 tls1.3
		client_auth {
			mode 					require_and_verify
			trusted_leaf_cert_file	./certs/clients/client01.cer
			trusted_leaf_cert_file	./certs/clients/client02.cer
			trusted_leaf_cert_file	./certs/server.pem
		}
	}
	route /fileserver1/* {
		#respond "Redirecting to fileserver1!!!"
		handle_path /fileserver1/* {
			reverse_proxy * localhost:7777
			redir localhost:7777/client01/
		}
	}
	route /fileserver2/* {
		#respond "Redirecting to fileserver2!!!"
		handle_path /fileserver2/* {
			reverse_proxy * localhost:8888
		}
	}
	route * {
		respond "Main Page!!!"
	}
}

3. The problem I’m having:

I’m currently testing internally before I can put on production. I was able to use internal CA with our server and client certificates. When accessing https://server2016/fileserver1 from the client side the browser is prompted to provide a certificate. When the client certificate is selected page continues to load and the file directory structure is displayed. Accessing the page using a web browser https://server2016/fileserver1 would be reverse proxy to localhost:7777 which runs rclone serve http.

We would like to be able to filter base on what client certificate is presented in the header then return localhost:7777/client01/ which is a sub directory on the root on the fileserver.

Hopefully my explanation is clear enough, I am very new to Caddy so I might be missing something glaringly obvious or it might not even be a option but we’re trying to explore every avenue for help.

4. Error messages and/or full log output:

Error shows status 302 from the caddy.log

Log output from caddy using DEBUG output file command above.

1.6541561430708594e+09 info http.log.access.log0 handled request {“request”: {“remote_ip”: “10.10.7.11”, “remote_port”: “49689”, “proto”: “HTTP/2.0”, “method”: “GET”, “host”: “server2016”, “uri”: “/fileserver1/client01/”, “headers”: {“Sec-Ch-Ua-Platform”: ["“Windows”"], “Upgrade-Insecure-Requests”: [“1”], “User-Agent”: [“Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36”], “Sec-Fetch-Dest”: [“document”], “Accept-Encoding”: [“gzip, deflate, br”], “Sec-Ch-Ua”: ["" Not A;Brand";v=“99”, “Chromium”;v=“102”, “Google Chrome”;v=“102"”], “Sec-Ch-Ua-Mobile”: ["?0"], “Accept”: [“text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9”], “Sec-Fetch-Site”: [“none”], “Sec-Fetch-Mode”: [“navigate”], “Sec-Fetch-User”: ["?1"], “Accept-Language”: [“en-US,en;q=0.9”]}, “tls”: {“resumed”: false, “version”: 772, “cipher_suite”: 4867, “proto”: “h2”, “server_name”: “server2016”, “client_common_name”: “client01”, “client_serial”: “33652285”}}, “user_id”: “”, “duration”: 0, “size”: 0, “status”: 302, “resp_headers”: {“Server”: [“Caddy”], “Location”: [“localhost:7777/client01/”], “Content-Type”: []}}

5. What I already tried:

I’m able to hit the root of the fileserver1 by not having the redir localhost:7777/client01/

route /fileserver1/* {
	#respond "Redirecting to fileserver1!!!"
	handle_path /fileserver1/* {
		reverse_proxy * localhost:7777
		redir localhost:7777/client01/
	}
}

6. Links to relevant resources:

1 Like

Remove this. This is already the defaults, so setting this has no use. It’ll only prevent future versions of Caddy from automatically providing theoretical TLS 1.4 support, if it later adds support for it. Let Caddy do the smart thing.

Caddy never emits access logs at lower than INFO, so setting DEBUG here won’t do anything.

To clarify, you configured access logs, which are not the same as Caddy’s runtime logs (which are emitted to stdout/stderr by default). Those do have debug logs. You can use the debug global option to turn those on, or use the log global option (not directive, as in, configure it in the global options block, not within a site block) to customize them further.

Remove these, those are already the defaults as well.

Sounds like you want a rewrite, not a redirect. Different things. An HTTP redirect is a special kind of HTTP response which tells the browser “hey, make a new request at this new path, please!” It uses the Location header as the target location. See the log you posted, you can see that header there. But that doesn’t make sense here because localhost:7777 is a backend which your client cannot (or should not) directly access.

A rewrite is an internal modification of the path (and/or query) of the request before continuing handling. It sounds like what you want is to rewrite the URL to remove /fileserver1 from the front of the URL (which handle_path will do for you implicitly), and then replace it with /client01. So to do that, do this:

handle_path /fileserver1/* {
	rewrite * /client01{uri}
	reverse_proxy localhost:7777
}

Also, you can remove your route directives wrapping the handle_path, they don’t do anything for you, they’re redundant. And replace your last route with a handle which will act as your fallback for otherwise not matched handles.

2 Likes

This worked very well as advertized! I’m very appreciative in the detailed explaination and edits/improvement towards my caddyfile config.

2 Likes