all systems self-hosted

~/selfhostjournal $

← All articles

,

Traefik GeoBlock locked out my own AI assistant: allowing a published IP range

4–6 minutes

In short

Problem: After I switched on Traefik GeoBlock, Claude’s connector to Home Assistant stopped working, while Home Assistant itself was fine for everyone at home.

Solution: The connector calls from Anthropic’s servers in the US, and GeoBlock only allowed my own countries. One allowedIPAddresses entry with the provider’s published IP range fixed it.

Tested with: Traefik 3, GeoBlock plugin (PascalMinder) 0.3.8, Home Assistant with an MCP server for Claude

In Hardening Traefik I put GeoBlock in front of every service: only visitors from the countries my family lives in get through, everyone else gets a 403. It worked exactly as planned. A bit too well, as it turned out: it also locked out a visitor I wanted, my own AI assistant.

This is a short story about a security measure that does its job, breaks something you need, and how to find out which one it was.

1. The symptom

I use Claude with a connector to Home Assistant, so I can ask about sensors, automations and logs in plain language. Shortly after the hardening, the connector couldn’t reach Home Assistant anymore. Every attempt failed.

At the same time, Home Assistant was perfectly fine: the dashboard loaded at home, the app on my phone worked, automations ran. Only this one client was affected.

2. What I checked first (and why it misled me)

A connector that signs in with OAuth has plenty of parts that can break, so that’s where you look first:

  • Sign-in and tokens: an expired token or a broken OAuth setup would explain a failing client. But reconnecting doesn’t help when the requests are blocked before they arrive.
  • Home Assistant logs: nothing. No failed login, no error from the MCP integration, not even a request.
  • The URL: it opens fine in the browser.

The empty Home Assistant log was the real clue, and it’s easy to read it the wrong way. “No errors” sounded like “nothing wrong in Home Assistant”. It actually meant: the requests never arrived. Something in front of Home Assistant was answering them. And “it works in my browser” proved nothing, because my browser comes from an allowed country.

3. The real cause: Traefik GeoBlock did its job

Claude’s connectors don’t run in my browser or on my phone. They call my server from Anthropic’s infrastructure, which sits in the US. For GeoBlock that’s just another request from a country that isn’t on the list.

Two logs show it. GeoBlock writes every denied request to its own file. A line looks like this (example address):

INFO: GeoBlock: 2026/10/16 09:14:52 geoblock@docker: request denied [203.0.113.17] for country [US] due to: country is not allowed

And the Traefik access log shows the 403 with an empty backend ("-" after the router name). That dash means the request never reached the service (again an example line):

203.0.113.17 - - [16/Oct/2026:09:14:52 +0000] "POST /api/webhook/… HTTP/1.1" 403 0 "-" "-" 4711 "homeassistant@docker" "-" 1ms

The log is full of scanners from all over the world, so the connector’s requests don’t stand out by themselves. Compare the denied addresses with the range Anthropic publishes for its outgoing traffic, and they do.

Tip: when one client fails and the app’s own log is empty, look at the reverse proxy first. A 403 with no backend in the access log is the typical sign of a middleware saying no.

4. The fix: allow the published IP range

GeoBlock has an option for exactly this: allowedIPAddresses. Addresses in this list are let through no matter which country they come from. One more label on the Traefik container:

      # Claude connectors call from Anthropic's published outbound range
      # source: https://platform.claude.com/docs/en/api/ip-addresses
      - "traefik.http.middlewares.geoblock.plugin.geoblock.allowedIPAddresses[0]=160.79.104.0/21"

Then recreate the container so Traefik reads the new labels:

docker compose up -d traefik

The range above is the one Anthropic lists at the time of writing. Check Anthropic’s IP address page for the current one before you copy it. The same approach works for any other service that has to reach you from abroad, as long as its provider publishes its IP ranges.

Warning: only allow ranges the provider publishes officially. Never add an IP you found in your own log just because it looks right, and never open a whole country for one service. Also keep in mind what an exception means: this range is shared by all of the provider’s customers, not just you. GeoBlock lets them through, so the login of the service behind it still has to hold. In my case Home Assistant’s own sign-in and CrowdSec are still in place.

5. How to verify

  1. Check that Traefik picked up the label:
    docker inspect traefik --format '{{ index .Config.Labels "traefik.http.middlewares.geoblock.plugin.geoblock.allowedIPAddresses[0]" }}'
  2. Use the connector once (in my case: ask Claude for a sensor value).
  3. Make sure the range no longer shows up as denied:
    grep -E '\[160\.79\.1(0[4-9]|1[01])\.' traefik-logs/geoblock.log | tail
    No new lines after the restart means GeoBlock lets the connector through.

What I learned

  • “Works in my browser” is no test for a geo-block. Ask where the failing client really calls from.
  • An empty application log is a finding, not a dead end: the request was stopped earlier.
  • Before switching on an allow list, write down every service that calls in from outside: AI connectors, webhooks, monitoring, push services. Each one needs a deliberate exception or a different path.

The full GeoBlock and CrowdSec setup is in Hardening Traefik: geo-blocking, CrowdSec and single sign-on.

Everything here worked in my setup at the time of writing. Software changes, and your setup is different: back up first, test carefully, and use the steps at your own risk. Details in the legal notice.