Trust the RFC 1918 ranges as proxies when TRUSTED_PROXIES is unset (closes #333) #336
@@ -147,7 +147,7 @@ TTY detection, and security headers are always applied.
|
|||||||
| `RETENTION_SWEEP_INTERVAL` | How often the retention reaper and archive sweeper run (Go duration, must be positive) | `1h` |
|
| `RETENTION_SWEEP_INTERVAL` | How often the retention reaper and archive sweeper run (Go duration, must be positive) | `1h` |
|
||||||
| `SESSION_IDLE_TIMEOUT` | Idle session timeout (Go duration) | `24h` |
|
| `SESSION_IDLE_TIMEOUT` | Idle session timeout (Go duration) | `24h` |
|
||||||
| `RECEIVER_RATE_LIMIT` | Receiver requests/minute per IP per entrypoint (10x that per IP across the route) | `120` |
|
| `RECEIVER_RATE_LIMIT` | Receiver requests/minute per IP per entrypoint (10x that per IP across the route) | `120` |
|
||||||
| `TRUSTED_PROXIES` | CIDRs whose forwarded headers are trusted. A set value replaces the default. If clients connect directly from private addresses, set it to the proxy's address alone. See [Trusted proxies](#trusted-proxies) | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` (RFC 1918) |
|
| `TRUSTED_PROXIES` | CIDRs whose forwarded headers are trusted. A set value replaces the default. Under the default, any client with a private address, whether it connects directly or through the proxy, can choose its own rate-limit key by sending its own `X-Forwarded-For`; if any clients have private addresses, set it to the proxy's address alone. See [Trusted proxies](#trusted-proxies) | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` (RFC 1918) |
|
||||||
| `ALLOWED_EGRESS_CIDRS` | CIDRs that delivery targets may reach despite the SSRF blocklist. Read [Allowing egress to your own network](#allowing-egress-to-your-own-network) before setting it | `""` (none) |
|
| `ALLOWED_EGRESS_CIDRS` | CIDRs that delivery targets may reach despite the SSRF blocklist. Read [Allowing egress to your own network](#allowing-egress-to-your-own-network) before setting it | `""` (none) |
|
||||||
|
|
||||||
#### Allowing egress to your own network
|
#### Allowing egress to your own network
|
||||||
@@ -391,16 +391,21 @@ reaching webhooker over a Docker network or a private LAN without
|
|||||||
anything set. A set value replaces the default entirely. A set but
|
anything set. A set value replaces the default entirely. A set but
|
||||||
unparseable value aborts startup.
|
unparseable value aborts startup.
|
||||||
|
|
||||||
Trusting those ranges has two consequences:
|
Trusting those ranges has two consequences for clients with private
|
||||||
|
addresses:
|
||||||
|
|
||||||
- Any peer in them chooses its own rate-limit key through
|
- Any such client, whether it connects directly or through the proxy,
|
||||||
`X-Forwarded-For` (see the requirements below). If your clients
|
can choose its own rate-limit key by sending its own
|
||||||
connect to webhooker directly from private addresses, set
|
`X-Forwarded-For`. A direct client's header is walked because the
|
||||||
`TRUSTED_PROXIES` to the proxy's address alone.
|
client is itself trusted; behind the proxy, the client's own address
|
||||||
- Clients whose own addresses are private are skipped as trusted hops
|
is skipped as a trusted hop when the chain is walked (below), so the
|
||||||
when the chain is walked (below), so one that sends no
|
entry it wrote is taken as the client. If any of your clients have
|
||||||
`X-Forwarded-For` of its own shares the proxy's bucket. Setting the
|
private addresses, you must set `TRUSTED_PROXIES` to the proxy's
|
||||||
list to the proxy's address alone gives each its own bucket.
|
address alone.
|
||||||
|
- A client behind the proxy that sends no `X-Forwarded-For` of its own
|
||||||
|
shares the proxy's bucket, because its own address is skipped too.
|
||||||
|
Setting the list to the proxy's address alone gives each its own
|
||||||
|
bucket.
|
||||||
|
|
||||||
A proxy the list does not cover, such as nginx on the same host
|
A proxy the list does not cover, such as nginx on the same host
|
||||||
reaching webhooker over loopback, is not trusted: every request through
|
reaching webhooker over loopback, is not trusted: every request through
|
||||||
@@ -766,14 +771,16 @@ repository's `Dockerfile` and runs it. The app needs:
|
|||||||
|
|
||||||
- **Environment variables:**
|
- **Environment variables:**
|
||||||
- `WEBHOOKER_ENVIRONMENT=prod`
|
- `WEBHOOKER_ENVIRONMENT=prod`
|
||||||
- `TRUSTED_PROXIES`: normally leave it unset. Docker networks use
|
- `TRUSTED_PROXIES`: Docker networks use private addresses, so the
|
||||||
private addresses, so the default covers your reverse proxy on
|
default covers your reverse proxy on that network. Under the
|
||||||
that network. If the network's addresses are outside the RFC 1918
|
default, any client with a private address, whether it connects
|
||||||
ranges, or clients reach the app from private addresses other
|
directly or through the proxy, can choose its own rate-limit key
|
||||||
than through the proxy, set it to the proxy's address there. The
|
by sending its own `X-Forwarded-For`. If any clients have private
|
||||||
`remoteIP` field of the `http request` log line for a request that
|
addresses, or the network's addresses are outside the RFC 1918
|
||||||
came through the proxy shows it; the health check's own lines show
|
ranges, set it to the proxy's address there. The `remoteIP` field
|
||||||
`::1`. See [Trusted proxies](#trusted-proxies).
|
of the `http request` log line for a request that came through
|
||||||
|
the proxy shows it; the health check's own lines show `::1`. See
|
||||||
|
[Trusted proxies](#trusted-proxies).
|
||||||
- Leave `BIND_ADDRESS` and `DATA_DIR` unset: the image sets
|
- Leave `BIND_ADDRESS` and `DATA_DIR` unset: the image sets
|
||||||
`BIND_ADDRESS` to `0.0.0.0`, and `DATA_DIR` defaults to
|
`BIND_ADDRESS` to `0.0.0.0`, and `DATA_DIR` defaults to
|
||||||
`/var/lib/webhooker`.
|
`/var/lib/webhooker`.
|
||||||
@@ -843,8 +850,7 @@ reports.
|
|||||||
peer, which is the proxy on every request: all clients collapse into
|
peer, which is the proxy on every request: all clients collapse into
|
||||||
one global bucket per limit and the receiver's per-IP limits become
|
one global bucket per limit and the receiver's per-IP limits become
|
||||||
service-wide ceilings. See [Trusted proxies](#trusted-proxies). If
|
service-wide ceilings. See [Trusted proxies](#trusted-proxies). If
|
||||||
clients also connect from private addresses, list the proxy and
|
any clients have private addresses, list the proxy and nothing else.
|
||||||
nothing else.
|
|
||||||
4. **Send `Host` as `$http_host`, not `$host`.** `$host` strips the
|
4. **Send `Host` as `$http_host`, not `$host`.** `$host` strips the
|
||||||
port. webhooker's Origin/Referer check compares against the host it
|
port. webhooker's Origin/Referer check compares against the host it
|
||||||
was given, so on any port other than 443 `$host` makes every form
|
was given, so on any port other than 443 `$host` makes every form
|
||||||
@@ -2716,8 +2722,9 @@ re-fills both verification slots on its first two requests. The
|
|||||||
remedies are to block the source at the reverse proxy, or to
|
remedies are to block the source at the reverse proxy, or to
|
||||||
rate-limit `POST /pages/login` there — the one place a limit can be
|
rate-limit `POST /pages/login` there — the one place a limit can be
|
||||||
applied without reintroducing the lockout, because the proxy sees the
|
applied without reintroducing the lockout, because the proxy sees the
|
||||||
real client address. Setting `TRUSTED_PROXIES` does not stop the
|
real client address. `TRUSTED_PROXIES` does not stop the saturation,
|
||||||
saturation, but it makes the source visible in the failure logs.
|
but when it covers the proxy the source is visible in the failure logs,
|
||||||
|
and the default covers a proxy on a private network.
|
||||||
|
|
||||||
Finer-grained per-webhook rate limits (configured in the web UI and
|
Finer-grained per-webhook rate limits (configured in the web UI and
|
||||||
enforced in the webhook handler) can layer on top of this env-level
|
enforced in the webhook handler) can layer on top of this env-level
|
||||||
|
|||||||
@@ -180,10 +180,11 @@ type Config struct {
|
|||||||
// only forwarded header read. Unless TRUSTED_PROXIES is set it
|
// only forwarded header read. Unless TRUSTED_PROXIES is set it
|
||||||
// is the RFC 1918 private ranges (defaultTrustedProxies).
|
// is the RFC 1918 private ranges (defaultTrustedProxies).
|
||||||
// Other peers' forwarded headers are ignored and they are
|
// Other peers' forwarded headers are ignored and they are
|
||||||
// identified by the connection's own address. Members can
|
// identified by the connection's own address. Under the
|
||||||
// choose their own rate-limit key, so where clients also
|
// default any client with a private address, directly or
|
||||||
// connect from private addresses this must be set to the
|
// through a proxy, can choose its own rate-limit key, so
|
||||||
// proxy hosts alone.
|
// where any clients have private addresses this must be set
|
||||||
|
// to the proxy hosts alone.
|
||||||
TrustedProxies []netip.Prefix
|
TrustedProxies []netip.Prefix
|
||||||
|
|
||||||
// AllowedEgressCIDRs is the set of networks a delivery target
|
// AllowedEgressCIDRs is the set of networks a delivery target
|
||||||
|
|||||||
Reference in New Issue
Block a user