diff options
| author | Chris Lu <chrislusf@users.noreply.github.com> | 2025-10-30 21:06:00 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-30 21:06:00 -0700 |
| commit | 9f07bca9cc9a6bd26a29e567ed8bd9b2ffc8aea0 (patch) | |
| tree | da92978317b69b476eed43900a43968fc371d80a | |
| parent | 5810aba763cc269440483d12dcc6e026ec010fe6 (diff) | |
| download | seaweedfs-9f07bca9cc9a6bd26a29e567ed8bd9b2ffc8aea0.tar.xz seaweedfs-9f07bca9cc9a6bd26a29e567ed8bd9b2ffc8aea0.zip | |
Fix IPv6 host header formatting to match AWS SDK behavior (#7414)
* Add nginx reverse proxy documentation for S3 API
Fixes #7407
Add comprehensive documentation and example configuration for using
nginx as a reverse proxy with SeaweedFS S3 API while maintaining AWS
Signature V4 authentication compatibility.
Changes:
- Add docker/nginx/README.md with detailed setup guide
- Add docker/nginx/s3-example.conf with working configuration
- Update docker/nginx/proxy.conf with important S3 notes
The documentation covers:
- Critical requirements for AWS Signature V4 authentication
- Common mistakes and why they break S3 authentication
- Complete working nginx configurations
- Debugging tips and troubleshooting
- Performance tuning recommendations
* Fix IPv6 host header formatting to match AWS SDK behavior
Follow-up to PR #7403
When a default port (80 for HTTP, 443 for HTTPS) is stripped from an
IPv6 address, the square brackets should also be removed to match AWS
SDK behavior for S3 signature calculation.
Reference: https://github.com/aws/aws-sdk-go-v2/blob/main/aws/signer/internal/v4/host.go
The AWS SDK's stripPort function explicitly removes brackets when
returning an IPv6 address without a port.
Changes:
- Update extractHostHeader to strip brackets from IPv6 addresses when
no port or default port is used
- Update test expectations to match AWS SDK behavior
- Add detailed comments explaining the AWS SDK compatibility requirement
This ensures S3 signature validation works correctly with IPv6 addresses
behind reverse proxies, matching AWS S3 canonical request format.
Fixes the issue raised in PR #7403 comment:
https://github.com/seaweedfs/seaweedfs/pull/7403#issuecomment-3471105438
* Update docker/nginx/README.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Add nginx reverse proxy documentation for S3 API
Fixes #7407
Add comprehensive documentation and example configuration for using
nginx as a reverse proxy with SeaweedFS S3 API while maintaining AWS
Signature V4 authentication compatibility.
Changes:
- Add docker/nginx/README.md with detailed setup guide
- Add docker/nginx/s3-example.conf with working configuration
- Update docker/nginx/proxy.conf with important S3 notes
The documentation covers:
- Critical requirements for AWS Signature V4 authentication
- Common mistakes and why they break S3 authentication
- Complete working nginx configurations
- Debugging tips and troubleshooting
- Performance tuning recommendations
Fix IPv6 host header formatting to match AWS SDK behavior
Follow-up to PR #7403
When a default port (80 for HTTP, 443 for HTTPS) is stripped from an
IPv6 address, the square brackets should also be removed to match AWS
SDK behavior for S3 signature calculation.
Reference: https://github.com/aws/aws-sdk-go-v2/blob/main/aws/signer/internal/v4/host.go
The AWS SDK's stripPort function explicitly removes brackets when
returning an IPv6 address without a port.
Changes:
- Update extractHostHeader to strip brackets from IPv6 addresses when
no port or default port is used
- Update test expectations to match AWS SDK behavior
- Add detailed comments explaining the AWS SDK compatibility requirement
This ensures S3 signature validation works correctly with IPv6 addresses
behind reverse proxies, matching AWS S3 canonical request format.
Fixes the issue raised in PR #7403 comment:
https://github.com/seaweedfs/seaweedfs/pull/7403#issuecomment-3471105438
* Revert "Merge branch 'fix-ipv6-brackets-default-port' of https://github.com/seaweedfs/seaweedfs into fix-ipv6-brackets-default-port"
This reverts commit cca3f3985ff5263698d4be27a919cf52bbc5739f, reversing
changes made to 2b8f9de78ebaa285f43f38eec5e0be88a4e56715.
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
| -rw-r--r-- | weed/s3api/auth_signature_v4.go | 11 | ||||
| -rw-r--r-- | weed/s3api/auth_signature_v4_test.go | 12 | ||||
| -rw-r--r-- | weed/s3api/auto_signature_v4_test.go | 12 |
3 files changed, 20 insertions, 15 deletions
diff --git a/weed/s3api/auth_signature_v4.go b/weed/s3api/auth_signature_v4.go index 4d273de6a..b77540255 100644 --- a/weed/s3api/auth_signature_v4.go +++ b/weed/s3api/auth_signature_v4.go @@ -648,9 +648,14 @@ func extractHostHeader(r *http.Request) string { return net.JoinHostPort(host, port) } - // No port or default port, just ensure host is correctly formatted (IPv6 brackets). - if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { - return "[" + host + "]" + // No port or default port was stripped. According to AWS SDK behavior (aws-sdk-go-v2), + // when a default port is removed from an IPv6 address, the brackets should also be removed. + // This matches AWS S3 signature calculation requirements. + // Reference: https://github.com/aws/aws-sdk-go-v2/blob/main/aws/signer/internal/v4/host.go + // The stripPort function returns IPv6 without brackets when port is stripped. + if strings.Contains(host, ":") { + // This is an IPv6 address. Strip brackets to match AWS SDK behavior. + return strings.Trim(host, "[]") } return host } diff --git a/weed/s3api/auth_signature_v4_test.go b/weed/s3api/auth_signature_v4_test.go index 6850e9d2b..9ec4f232e 100644 --- a/weed/s3api/auth_signature_v4_test.go +++ b/weed/s3api/auth_signature_v4_test.go @@ -192,20 +192,20 @@ func TestExtractHostHeader(t *testing.T) { expected: "[::1]:8080", }, { - name: "IPv6 address without brackets and standard port, should return bracketed IPv6", + name: "IPv6 address without brackets and standard port, should strip brackets per AWS SDK", hostHeader: "backend:8333", forwardedHost: "::1", forwardedPort: "80", forwardedProto: "http", - expected: "[::1]", + expected: "::1", }, { - name: "IPv6 address without brackets and standard HTTPS port, should return bracketed IPv6", + name: "IPv6 address without brackets and standard HTTPS port, should strip brackets per AWS SDK", hostHeader: "backend:8333", forwardedHost: "2001:db8::1", forwardedPort: "443", forwardedProto: "https", - expected: "[2001:db8::1]", + expected: "2001:db8::1", }, { name: "IPv6 address with brackets but no port, should add port", @@ -216,12 +216,12 @@ func TestExtractHostHeader(t *testing.T) { expected: "[2001:db8::1]:8080", }, { - name: "IPv6 full address with brackets and default port (should strip port)", + name: "IPv6 full address with brackets and default port (should strip port and brackets)", hostHeader: "backend:8333", forwardedHost: "[2001:db8:85a3::8a2e:370:7334]:443", forwardedPort: "443", forwardedProto: "https", - expected: "[2001:db8:85a3::8a2e:370:7334]", + expected: "2001:db8:85a3::8a2e:370:7334", }, { name: "IPv4-mapped IPv6 address without brackets, should add brackets with port", diff --git a/weed/s3api/auto_signature_v4_test.go b/weed/s3api/auto_signature_v4_test.go index 6039081a1..47c55e077 100644 --- a/weed/s3api/auto_signature_v4_test.go +++ b/weed/s3api/auto_signature_v4_test.go @@ -451,25 +451,25 @@ func TestSignatureV4WithoutProxy(t *testing.T) { name: "IPv6 HTTP with standard port", host: "[::1]:80", proto: "http", - expectedHost: "[::1]", + expectedHost: "::1", }, { name: "IPv6 HTTPS with standard port", host: "[::1]:443", proto: "https", - expectedHost: "[::1]", + expectedHost: "::1", }, { name: "IPv6 HTTP without port", host: "::1", proto: "http", - expectedHost: "[::1]", + expectedHost: "::1", }, { name: "IPv6 HTTPS without port", host: "::1", proto: "https", - expectedHost: "[::1]", + expectedHost: "::1", }, } @@ -608,7 +608,7 @@ func TestSignatureV4WithForwardedPort(t *testing.T) { forwardedHost: "[::1]:443", forwardedPort: "443", forwardedProto: "https", - expectedHost: "[::1]", + expectedHost: "::1", }, { name: "IPv6 X-Forwarded-Host with standard http port already included (Traefik/HAProxy style)", @@ -616,7 +616,7 @@ func TestSignatureV4WithForwardedPort(t *testing.T) { forwardedHost: "[::1]:80", forwardedPort: "80", forwardedProto: "http", - expectedHost: "[::1]", + expectedHost: "::1", }, { name: "IPv6 with port in brackets", |
