s3: keep verifying the request host when externalUrl is set (#10970)

* s3: keep verifying the request host when externalUrl is set

externalUrl was the only host candidate once set, so a client that dialed
the gateway directly instead of through the proxy always got
SignatureDoesNotMatch. Make it lead the candidate walk instead: every
candidate still needs a valid signature, and the request-derived hosts are
already trusted when the flag is unset, so a mixed proxy plus in-cluster
topology can now advertise a public endpoint and verify both planes.

* s3: cover virtual-hosted addressing behind externalUrl

The old pin also rejected an external client that signed
bucket.api.example.com, since only the bare externalUrl host was ever
tried. The candidate walk covers it; pin the case down.
This commit is contained in:
Chris Lu authored and GitHub committed 2026-08-26 10:09:05 -07:00
1 parent 3431bdcb74
commit f5f1dcbd8c
10 files changed
+46 -17

No files matched your search

+5 -5
View File
@@ -26,16 +26,16 @@ nginx (:9000)
v
SeaweedFS S3 (:8333, -s3.externalUrl=http://localhost:9000)
| externalHost = "localhost:9000" (parsed at startup)
| extractHostHeader() returns "localhost:9000"
| extractHostHeaderCandidates() tries "localhost:9000" first
| Matches what AWS CLI signed with
v
Signature verification succeeds
```
**Note:** When `-s3.externalUrl` is configured, direct access to the backend
port (8333) will fail signature verification because the client signs with a
different Host header than what `externalUrl` specifies. This is expected —
all S3 traffic should go through the proxy.
**Note:** `-s3.externalUrl` is tried first, not exclusively. A client that
dials the backend port (8333) directly still verifies against the host it
actually signed, so a mixed topology of proxied and in-cluster clients works
with the flag set.
## Prerequisites