mirror of
https://github.com/gin-gonic/gin.git
synced 2026-04-29 23:23:18 +08:00
fix: Non-standard X-Forwarded-For header content is not supported
This commit is contained in:
parent
3e44fdc4d1
commit
4b7063bb38
26
gin.go
26
gin.go
@ -483,9 +483,33 @@ func (engine *Engine) validateHeader(header string) (clientIP string, valid bool
|
||||
if header == "" {
|
||||
return "", false
|
||||
}
|
||||
var ipStr string
|
||||
items := strings.Split(header, ",")
|
||||
for i := len(items) - 1; i >= 0; i-- {
|
||||
ipStr := strings.TrimSpace(items[i])
|
||||
item := strings.TrimSpace(items[i])
|
||||
// [IPv6] or [IPv6]:port
|
||||
if strings.HasPrefix(item, "[") {
|
||||
if idx := strings.IndexByte(item, ']'); idx > 0 {
|
||||
ipPart := item[1:idx]
|
||||
if ip := net.ParseIP(ipPart); ip != nil {
|
||||
if idx == len(item)-1 || (idx+1 < len(item) && item[idx+1] == ':') {
|
||||
ipStr = ipPart
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ip := net.ParseIP(item); ip != nil {
|
||||
// plain IPv4 or IPv6
|
||||
ipStr = item
|
||||
} else if idx := strings.LastIndexByte(item, ':'); idx > 0 {
|
||||
// IPv4:port
|
||||
ipPart := item[:idx]
|
||||
if ip := net.ParseIP(ipPart); ip != nil {
|
||||
ipStr = ipPart
|
||||
}
|
||||
}
|
||||
if ipStr == "" {
|
||||
break
|
||||
}
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip == nil {
|
||||
break
|
||||
|
||||
102
gin_test.go
102
gin_test.go
@ -1084,3 +1084,105 @@ func TestUpdateRouteTreesCalledOnce(t *testing.T) {
|
||||
assert.Equal(t, "ok", w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateHeader_IssueCases(t *testing.T) {
|
||||
r := New()
|
||||
|
||||
err := r.SetTrustedProxies([]string{"0.0.0.0/0", "::/0"})
|
||||
if err != nil {
|
||||
t.Fatalf("SetTrustedProxies failed: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
header string
|
||||
wantIP string
|
||||
wantValid bool
|
||||
}{
|
||||
{
|
||||
name: "IPv4 plain",
|
||||
header: "127.0.0.1",
|
||||
wantIP: "127.0.0.1",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "IPv4 with port (ARR/IIS)",
|
||||
header: "127.0.0.1:38792",
|
||||
wantIP: "127.0.0.1",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "IPv6 plain",
|
||||
header: "240e:318:2f4a:de56::240",
|
||||
wantIP: "240e:318:2f4a:de56::240",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "IPv6 with brackets (IIS style)",
|
||||
header: "[240e:318:2f4a:de56::240]",
|
||||
wantIP: "240e:318:2f4a:de56::240",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "IPv6 with brackets + port (ARR/IIS or cloud LB)",
|
||||
header: "[240e:318:2f4a:de56::240]:38792",
|
||||
wantIP: "240e:318:2f4a:de56::240",
|
||||
wantValid: true,
|
||||
}, {
|
||||
name: "invalid ip",
|
||||
header: "abc",
|
||||
wantIP: "",
|
||||
wantValid: false,
|
||||
},
|
||||
{
|
||||
name: "ipv6 missing closing bracket",
|
||||
header: "[240e:318:2f4a:de56::240",
|
||||
wantIP: "",
|
||||
wantValid: false,
|
||||
},
|
||||
{
|
||||
name: "ipv6 bracket invalid suffix",
|
||||
header: "[240e:318:2f4a:de56::240]abc",
|
||||
wantIP: "",
|
||||
wantValid: false,
|
||||
},
|
||||
{
|
||||
name: "multiple ipv4",
|
||||
header: "1.1.1.1, 127.0.0.1",
|
||||
wantIP: "1.1.1.1",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "multiple ipv6",
|
||||
header: "240e:318:2f4a:de56::111, 240e:318:2f4a:de56::240",
|
||||
wantIP: "240e:318:2f4a:de56::111",
|
||||
wantValid: true,
|
||||
},
|
||||
{
|
||||
name: "full",
|
||||
header: "1.1.1.1, 127.0.0.1, 192.168.3.1:5050, 240e:318:2f4a:de56::1111, [240e:318:2f4a:de56::2222], [240e:318:2f4a:de56::3333]:7080",
|
||||
wantIP: "1.1.1.1",
|
||||
wantValid: true,
|
||||
},
|
||||
// ---------- empty / whitespace ----------
|
||||
{
|
||||
name: "empty header",
|
||||
header: "",
|
||||
wantIP: "",
|
||||
wantValid: false,
|
||||
},
|
||||
{
|
||||
name: "whitespace header",
|
||||
header: " ",
|
||||
wantIP: "",
|
||||
wantValid: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ip, valid := r.validateHeader(tt.header)
|
||||
assert.Equal(t, tt.wantIP, ip)
|
||||
assert.Equal(t, tt.wantValid, valid)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user