SearXNG: stop rate-limiting local subagents (pass_ip covers slirp/loopback)

Root cause of the 429s: the ip_limit rate limiter caps JSON (format!=html)
requests at API_MAX=4 per IP per hour, and that constant is hardcoded in
Python (searx/botdetection/ip_limit.py), not settable in limiter.toml. The
only bypass is pass_ip (filter_request returns before ip_limit runs).

Rootless podman strips the client IP on published-port hits, so the container
sees a slirp/bridge source (10.88.x/10.89.x), never the real client - hence
even a LAN-IP curl 429'd on /search. Expand pass_ip to loopback + the host's
private podman/slirp ranges (plus the existing LAN) so local subagents present
a trusted source and skip the rate limit entirely. All these ranges are
reachable only from the host or LAN, never the internet.
This commit is contained in:
Frank
2026-08-19 12:29:27 -07:00
parent 3d4604c19f
commit 4fa9fdf36e
2 changed files with 33 additions and 2 deletions
+16 -2
View File
@@ -39,10 +39,24 @@ link_token = false
[botdetection.ip_lists]
# ip_lists outranks every other method: an IP in pass_ip gets unrestricted
# access and is not checked by user-agent or other bot detection.
# The whole homelab LAN is trusted.
# access and is not checked by user-agent, rate limiting, or other bot
# detection. This is the ONLY bypass for the rate limiter (ip_limit): its JSON
# cap (API_MAX = 4 requests/IP/hour) is hardcoded in Python and cannot be
# raised from this file.
#
# Rootless podman strips the client IP on published-port hits: a request to the
# published port reaches the container with a slirp/bridge source (10.88.x /
# 10.89.x), never the real client IP. Only Caddy's X-Forwarded-For restores it.
# So a local subagent that hits the port directly must present a pass_ip source
# or it hits the 4/hour JSON cap. We trust loopback, the homelab LAN, and the
# host's own private podman/slirp ranges; all are reachable only from the host
# or LAN, never the internet.
pass_ip = [
'127.0.0.1/32',
'::1',
'192.168.0.0/24',
'10.88.0.0/16',
'10.89.0.0/16',
]
# Blocklist (none).