Using this docker-compose config:
services:
geoipfilter:
image: mpdcampbell/traefik-geoip-filter
container_name: geoipfilter
volumes:
- ./goeip:/geoip
ports:
- 8080:8080
environment:
- MAXMIND_ID=yourIDhere
- MAXMIND_KEY=yourKeyhere
#Set the filter to act as an allowlist or blocklist
- FILTER_TYPE=block
- COUNTRY_CODES=FR
- BLOCK_STATUS_CODE=403
The /traefik location is intended to return only 200 (or 403 when the request IP matches $inIPList).
location /traefik {
add_header Content-Type "default_type text/plain";
if ($inIPList = 1) {
return 403;
}
return 200;
}
But there are some edge cases in which other HTTP status codes are returned, which messes with the Traefik filter. Traefik is relying on a strict 200/403 response and misinterprets the additional status codes, causing authorization failures.
Test setup
#!/usr/bin/env bash
BASE_URL="http://localhost:8080/traefik"
run_test() {
local description="$1"
shift # move command-line arguments to the left
local http_code
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$@")
printf "%-45s → %s\n" "$description" "$http_code"
}
run_test "200 OK (plain request)" -i "$BASE_URL"
run_test "200 OK (If-Modified-Since)" \
-i -H "If-Modified-Since: $(date -R)" "$BASE_URL"
run_test "304 Not Modified (If-None-Match: *)" \
-i -H 'If-None-Match: *' "$BASE_URL"
run_test "412 Precondition Failed (If-Match)" \
-i -H 'If-Match: "non-existent-etag"' "$BASE_URL"
run_test "412 Precondition Failed (If-Unmodified-Since)" \
-i -H "If-Unmodified-Since: $(date -d '1 day ago' -R)" "$BASE_URL"
run_test "403 X-Forwarded-For France is Blocked" \
-i -H "X-Forwarded-For: 1.178.90.1" "$BASE_URL"
Observed behavior
200 OK (plain request) → 200
200 OK (If-Modified-Since) → 200
304 Not Modified (If-None-Match: *) → 304
412 Precondition Failed (If-Match) → 412
412 Precondition Failed (If-Unmodified-Since) → 412
403 X-Forwarded-For France is Blocked → 403
Expected behavior
Only 200 (when $inIPList = 1) or 404 (otherwise). No conditional GET or precondition handling should affect the response.
Possible cause
Nginx’s built‑in conditional request handling (e.g., if_modified_since, if_none_match, if_match, if_unmodified_since) is automatically applied when the response body is empty or when certain headers are present, overriding the explicit return directives.
Suggested fix
Strip all headers except X-Forwarded-For using nginx as a proxy to itself.
Using this docker-compose config:
The /traefik location is intended to return only 200 (or 403 when the request IP matches $inIPList).
But there are some edge cases in which other HTTP status codes are returned, which messes with the Traefik filter. Traefik is relying on a strict 200/403 response and misinterprets the additional status codes, causing authorization failures.
Test setup
Observed behavior
Expected behavior
Only 200 (when
$inIPList = 1) or 404 (otherwise). No conditional GET or precondition handling should affect the response.Possible cause
Nginx’s built‑in conditional request handling (e.g.,
if_modified_since,if_none_match,if_match,if_unmodified_since) is automatically applied when the response body is empty or when certain headers are present, overriding the explicitreturndirectives.Suggested fix
Strip all headers except
X-Forwarded-Forusing nginx as a proxy to itself.