docs: update Source IP Handling for trusted-proxy allowlist

Update S3-Policy-Conditions to reflect the current aws:SourceIp behavior
(direct TCP peer by default, forwarded headers ignored without an
allowlist) and document the new [s3.trusted_proxies] config. Add a
cross-reference from S3-Nginx-Proxy and include the section in
Security-Configuration.
Chris Lu committed 2026-09-14 11:38:18 -07:00
1 parent 6d2b1f5ae5
commit 068c89f496
3 files changed
+39 -7

No files matched your search

+13
@@ -5,6 +5,19 @@ For virtual-hosted style URL buckets, you'll need to add a [wildcard DNS record]
Make sure the config sets the `X-Forwarded-Host` and optionally the `X-Forwarded-Port` if you are using a non-standard port. SeaweedFS will automatically combine these headers to reconstruct the correct host information for signature verification.
## aws:SourceIp and Trusted Proxies
The `X-Forwarded-For` and `X-Real-IP` headers set by the proxy are also used for `aws:SourceIp` condition evaluation in S3 bucket policies and IAM policies — but **only** when the proxy's IP is in the configured trusted-proxy allowlist. Without an allowlist, SeaweedFS uses the direct TCP peer address for `aws:SourceIp` (matching AWS S3 semantics) to prevent spoofing.
To enable forwarded-header trust, add the proxy's IP or CIDR to `security.toml`:
```toml
[s3.trusted_proxies]
white_list = "10.10.10.0/24" # comma separated; bare IPs or CIDRs
```
See [S3 Policy Conditions — Source IP Handling](S3-Policy-Conditions#source-ip-handling) for the full resolution logic.
## Explicit External URL for Signature Verification
In scenarios where the reverse proxy cannot easily be configured to send the necessary headers, or in complex multi-hop environments, you can use the `-s3.externalUrl` flag to explicitly set the public-facing URL of the S3 service.
+17 -7
@@ -134,15 +134,25 @@ Prefix any string operator with `ForAnyValue:` or `ForAllValues:` for multi-valu
## Source IP Handling
When SeaweedFS runs behind a reverse proxy, the `aws:SourceIp` condition key is resolved using the following logic:
By default, the `aws:SourceIp` condition key is resolved from the **direct TCP peer address** (`RemoteAddr`), matching AWS S3 semantics. Forwarding headers (`X-Forwarded-For`, `X-Real-IP`) are intentionally ignored — without an explicit allowlist they are client-controlled and spoofable, which would let a caller behind a private-looking peer bypass any `IpAddress`/`NotIpAddress` restriction.
1. If the direct connection is from a **private/loopback IP** (RFC 1918, IPv6 ULA), forwarding headers are trusted:
- `X-Forwarded-For` is checked for the rightmost non-private IP
- `X-Real-IP` is used as a fallback
2. If the direct connection is from a **public IP**, forwarding headers are ignored to prevent spoofing
3. Final fallback is always `RemoteAddr`
### Trusted Proxy Allowlist
This ensures correct behavior whether SeaweedFS is accessed directly or through a load balancer.
When SeaweedFS runs behind a reverse proxy, configure a trusted-proxy allowlist in `security.toml` so that forwarded headers are honored only from known proxies:
```toml
[s3.trusted_proxies]
white_list = "10.10.10.0/24" # comma separated; bare IPs or CIDRs
```
Can also be set via the environment variable `WEED_S3_TRUSTED_PROXIES_WHITE_LIST`. Reloaded on `SIGHUP`.
When the direct TCP peer is in the allowlist:
1. `X-Forwarded-For` is walked right-to-left, skipping trusted hops, to find the first non-trusted (public) IP
2. If all hops are trusted, the leftmost valid IP is used
3. `X-Real-IP` is used as a fallback when `X-Forwarded-For` is absent or malformed
When the direct TCP peer is **not** in the allowlist (or no allowlist is configured), forwarded headers are ignored and the direct peer address is used.
## Examples
+9
@@ -164,6 +164,15 @@ key = ""
ca = ""
# disable_tls_verify_client_cert = true|false (default: false)
# Trusted reverse proxies allowed to set X-Forwarded-For / X-Real-Ip for
# aws:SourceIp condition evaluation in S3 bucket and IAM policies. When the
# direct TCP peer is in this list, forwarded headers are honored; otherwise
# the direct peer address is used (matching AWS S3 semantics). Leave empty to
# always use the direct peer, which is the safe default.
# Can also be set via env var: WEED_S3_TRUSTED_PROXIES_WHITE_LIST
[s3.trusted_proxies]
white_list = "" # comma separated; bare IPs or CIDRs, e.g. "10.10.10.0/24"
# white list. It's checking request ip address.
[guard]
white_list = ""