Blocking access to a website outside of whitelist

1. The problem I’m having:

Hi there, I’m trying to make it so one of my websites uses a whitelist to block IPs not on it from successfully connecting to the service I am hosting.

I am on the same local network (but not the same machine) as the server that hosts both the caddy container and the service container that I am trying to add a whitelist to.

When I attempt to connect via the LAN IP i.e. when I connect to my server’s IP on my local network via http, it works just fine.
However when I try to connect via my domain name, I get the “Your address is not whitelisted” message.
I have tried whitelisting both my public IPV4 and my public IPV6, to no avail.

2. Error messages and/or full log output:

It seems like even when I use debug in my caddyfile, I still don’t get any lines relating to this website. I just get generic setup lines.

3. Caddy version:

4. How I installed and ran Caddy:

Caddy is installed via Docker compose, sharing the same compose file as Authelia.

a. System environment:

Ubuntu Server 24.04.2 LTS (GNU/Linux 6.8.0-59-generic x86_64)

b. Command:

docker compose up -d

c. Service/unit/compose file:

  caddy:
    image: caddy:latest
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./caddy/data:/data
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile

d. My complete Caddy config:

test.testy.eu {
        @denied not remote_ip 82.65.75.74 82.65.75.74/28 private_ranges 2a01:e0a:244:f670:9969:9124:c45a:8ec
        abort @denied
        respond "Your address is not whitelisted."
        reverse_proxy 192.168.1.171:3000
}

(I have blocks for other subdomains but I don’t think this is relevant - I don’t have any generic blocks that would apply to all rules)

5. Links to relevant resources:

You didn’t share your full Caddyfile, so it’s hard to know exactly what’s going on. What do you see when you try to connect? What did you configure Caddy to do in that case?

Looking at this part of your Docker Compose:

If this is your full setup, then you’re running in bridge mode. That means all traffic will appear to come from the Docker bridge network’s IP address. The private_ranges setting includes the bridge network range (172.16.0.0/12), so your requests won’t get blocked - they’ll just follow whatever logic you’ve set up for internal IPs. That’s why you’re seeing the message consistently - it’s working exactly as configured.

You can add a log directive inside your test.testy.eu block like this:

test.testy.eu {
  …
  log
}

That’ll help you confirm where requests are coming from.

What you can do:

  1. Switch your container to host network mode instead of bridge mode, and
  2. Review and fix your test.testy.eu config - right now, it’s not set up correctly. Even with other settings in place, the current config will still show the message you’re seeing when coming from your LAN.
2 Likes

Hi and thanks for replying :slight_smile:

When I try to connect I get the error message I configured.
image

Like I said, my caddy file is just a bunch of redirects.
like this:

stuff.testy.eu {
        reverse_proxy 192.168.1.171:9333
}

This is the only one on which I want to add the extra whitelist filter.

I was trying to say that when I connect manually to 192.168.1.171:3000 on my browser, I can see the page as intended.

But when I try to access it by typing test.testy.eu, that’s when I get the message.

I don’t get it, if private_ranges includes the docker IP address then why does it not redirect me to the page?

I mean I can definitely change my docker to host mode, but I don’t get what’s wrong with the config.

I have enabled host mode on my docker, and also logging in the block.

This is the log I get:

authelia-caddy-1     | {"level":"info","ts":1747072972.3238144,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"192.168.1.254","remote_port":"44406","client_ip":"192.168.1.254","proto":"HTTP/2.0","method":"GET","host":"test.testy.eu","uri":"/","headers":{"Sec-Fetch-Dest":["document"],"Sec-Fetch-Mode":["navigate"],"Te":["trailers"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0"],"Sec-Gpc":["1"],"Cookie":["REDACTED"],"Sec-Fetch-User":["?1"],"Accept-Language":["en-US,en;q=0.5"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Priority":["u=0, i"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Site":["none"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"test.testy..eu"}},"bytes_read":0,"user_id":"","duration":0.000019625,"size":32,"status":200,"resp_headers":{"Content-Type":["text/plain; charset=utf-8"],"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}

So I see my remote IP is the local IP of my computer 192.168.1.254 which should be included in the private_ranges.

So you were indeed right in that my caddy config is incorrect but I do not know why.
Do you have a resource that could guide me in the right direction?

I tried following the example here:

I managed to make it work with:

test.testy.eu {
        log
        @blocked not remote_ip 82.65.75.74 82.65.75.74/28 private_ranges 2a01:e0a:244:f670:9969:9124:c45a:8ec
        respond @blocked "Your address is not whitelisted." 403
        reverse_proxy 192.168.1.171:3000
}
1 Like

That’s happening because of this block in your config:

test.testy.eu {
        @denied not remote_ip 82.65.75.74 82.65.75.74/28 private_ranges 2a01:e0a:244:f670:9969:9124:c45a:8ec
        abort @denied
        respond "Your address is not whitelisted."
        reverse_proxy 192.168.1.171:3000
}

The issue is that these two lines:

        @denied not remote_ip 82.65.75.74 82.65.75.74/28 private_ranges 2a01:e0a:244:f670:9969:9124:c45a:8ec
        abort @denied

never actually match, because both your Docker bridge network and your LAN fall under private_ranges. So, the logic continues down to:

        respond "Your address is not whitelisted."
        reverse_proxy 192.168.1.171:3000

and here’s the catch - Caddy follows a directive order, and respond has higher priority than reverse_proxy. That means Caddy will always hit the respond line and never reach reverse_proxy.

I wanted you to check out the directive order yourself for the learning value :wink: but it looks like you’ve already figured it out and fixed it perfectly with this:

        @blocked not remote_ip 82.65.75.74 82.65.75.74/28 private_ranges 2a01:e0a:244:f670:9969:9124:c45a:8ec
        respond @blocked "Your address is not whitelisted." 403
        reverse_proxy 192.168.1.171:3000
}

Nicely done!

2 Likes

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