Multiple trusted_proxies directives

1. The problem I’m having:

I have deployed Caddy as a reverse proxy that serves both internal and external request. I use unbound with transparent and stub zones to provide private IPs to internal clients and use Cloudflare publicly for public external clients.

I recently started using Cloudflare Zero trust with Cloudflared and notices that the Forwarded-For header always had the local systems IP as the cloudflared service and caddy are on the same host. After doing some research I discovered that I needed to start using Trusted Proxies with client_ip_headers. I found and builtin a module designed to make this easier GitHub - WeidiDeng/caddy-cloudflare-ip though it does in fact also appear to have its own problems since it looks like cloudflare may not be publishing all of its zero trust tunnel addresses.

In my first attempts it did not appear to work at all. I thought I had set something up wrong. After quite a bit of head scratching I realized that the real trusted proxy in this case was cloudflared running along side caddy. After using trusted_proxies static private_ranges I was back in business getting the headers forwarded as I expected.

However, I do not have everything running through a zero trust access tunnel. So I thought I could try using two trusted_proxies directives, but that does not appear to be the case. In inspecting the runtime JSON if I have two trusted proxy directives it looks like the last one wins. I assume it is not currently possible to have more than one trusted proxies global directive. Is that by design, an enhancement, or a bug?

2. Error messages and/or full log output:

There isn’t an error per se, rather an observed behavior. If I configure caddy like this I only get the private ranges trusted_proxies in the runtime JSON configuration. I’ve also attempted to combine static and the cloudflare module but it does not work.

        servers {
                # Cloudflare Trusted Proxy IPs
                 trusted_proxies cloudflare {
                       interval 12h
                       timeout 15s
                trusted_proxies static private_ranges
                # Set Real Ip Headers from Trusted Proxies
                client_ip_headers Cf-Connecting-Ip X-Real-IP

Runtime Config in JSON format. Note the Cloudflare Module information for trusted_proxies appears to be missing. I did try the module on its own and it seems to have a hash value here.

                                        "trusted_proxies": {
                                                "ranges": [

3. Caddy version:


4. How I installed and ran Caddy:

Built with xcaddy latest

a. System environment:

Rocky Linux 8.9

5. Links to relevant resources:

You can use GitHub - fvbommel/caddy-combine-ip-ranges: IP prefix module for Caddy that combines the output of other IP prefix modules. to combine multiple IP sources together.

1 Like