mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 08:24:01 +03:00
Pass real client IPs through with PROXY protocol v2
Without this, mtg and Caddy see HAProxy's container IP for every connection, which breaks meaningful logging, abuse handling, and any IP-based blocklist logic. HAProxy sends a PROXY protocol v2 header on its TCP backends; mtg enables proxy-protocol-listener, and Caddy wraps :8443 with a proxy_protocol listener before tls. The :80 path (ACME HTTP-01 passthrough) is unchanged — client IP there is not useful and HAProxy's http mode already adds X-Forwarded-For if anyone wants it. Requested in https://github.com/9seconds/mtg/pull/462 review.
This commit is contained in:
@@ -3,6 +3,25 @@
|
||||
# ACME HTTP-01 challenges arrive on :80 via HAProxy's acl passthrough.
|
||||
http_port 80
|
||||
https_port 8443
|
||||
|
||||
# HAProxy forwards connections to :8443 with a PROXY protocol v2
|
||||
# header (see haproxy.cfg `send-proxy-v2`). The proxy_protocol
|
||||
# listener wrapper strips the header and exposes the real client IP
|
||||
# to Caddy's access log. The `tls` wrapper must follow so that TLS
|
||||
# is terminated on the unwrapped connection.
|
||||
#
|
||||
# `allow` lists the networks permitted to send PROXY headers. These
|
||||
# ranges cover docker compose's default bridge networks; tighten
|
||||
# them if you pin a specific subnet in docker-compose.yml.
|
||||
servers :8443 {
|
||||
listener_wrappers {
|
||||
proxy_protocol {
|
||||
timeout 5s
|
||||
allow 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
|
||||
}
|
||||
tls
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{$DOMAIN} {
|
||||
|
||||
@@ -43,6 +43,19 @@ docker compose up -d
|
||||
docker compose exec mtg mtg access /config/config.toml
|
||||
```
|
||||
|
||||
## Real client IPs (PROXY protocol)
|
||||
|
||||
HAProxy forwards TCP connections to mtg and Caddy with a PROXY protocol
|
||||
v2 header so both backends see the real client IP instead of HAProxy's
|
||||
container address. The three pieces must stay in sync:
|
||||
|
||||
- `haproxy.cfg` — `send-proxy-v2` on the `mtg` and `web` backend `server` lines
|
||||
- `mtg-config.toml` — `proxy-protocol-listener = true`
|
||||
- `Caddyfile` — `listener_wrappers { proxy_protocol { ... } tls }` on `:8443`
|
||||
|
||||
If you disable one, disable all three, otherwise the backend will fail
|
||||
to parse the connection.
|
||||
|
||||
## ACME (Let's Encrypt) notes
|
||||
|
||||
HAProxy passes `/.well-known/acme-challenge/` requests on `:80` to
|
||||
|
||||
@@ -46,10 +46,16 @@ frontend tls
|
||||
default_backend web
|
||||
|
||||
backend mtg
|
||||
server mtg mtg:3128
|
||||
# send-proxy-v2 prepends a PROXY protocol v2 header so mtg sees the
|
||||
# real client IP instead of HAProxy's. mtg must have
|
||||
# `proxy-protocol-listener = true` in its config.
|
||||
server mtg mtg:3128 send-proxy-v2
|
||||
|
||||
backend web
|
||||
server web web:8443
|
||||
# send-proxy-v2 prepends a PROXY protocol v2 header so Caddy logs the
|
||||
# real client IP instead of HAProxy's. Caddy must enable the
|
||||
# proxy_protocol listener wrapper on :8443 (see Caddyfile).
|
||||
server web web:8443 send-proxy-v2
|
||||
|
||||
backend web_acme
|
||||
mode http
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
secret = "PASTE_YOUR_SECRET_HERE"
|
||||
bind-to = "0.0.0.0:3128"
|
||||
|
||||
# HAProxy in front sends PROXY protocol v2 headers so mtg can see the
|
||||
# real client IP. Keep this in sync with haproxy.cfg (`send-proxy-v2`).
|
||||
proxy-protocol-listener = true
|
||||
|
||||
[defense.anti-replay]
|
||||
enabled = true
|
||||
max-size = "1mib"
|
||||
|
||||
Reference in New Issue
Block a user