1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-24 08:22:21 +02:00

Fix Real IP logic (#2550)

* Fix realIP logic
This commit is contained in:
Vladimir Buyanov 2024-03-10 19:04:54 +02:00 committed by GitHub
parent 3598f295f9
commit a3b0ba24d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 34 deletions

12
ip.go
View File

@ -228,15 +228,21 @@ func extractIP(req *http.Request) string {
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
checker := newIPChecker(options)
return func(req *http.Request) string {
directIP := extractIP(req)
realIP := req.Header.Get(HeaderXRealIP)
if realIP != "" {
if realIP == "" {
return directIP
}
if checker.trust(net.ParseIP(directIP)) {
realIP = strings.TrimPrefix(realIP, "[")
realIP = strings.TrimSuffix(realIP, "]")
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
if rIP := net.ParseIP(realIP); rIP != nil {
return realIP
}
}
return extractIP(req)
return directIP
}
}

View File

@ -4,10 +4,11 @@
package echo
import (
"github.com/stretchr/testify/assert"
"net"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func mustParseCIDR(s string) *net.IPNet {
@ -461,7 +462,7 @@ func TestExtractIPDirect(t *testing.T) {
}
func TestExtractIPFromRealIPHeader(t *testing.T) {
_, ipForRemoteAddrExternalRange, _ := net.ParseCIDR("203.0.113.199/24")
_, ipForRemoteAddrExternalRange, _ := net.ParseCIDR("203.0.113.0/24")
_, ipv6ForRemoteAddrExternalRange, _ := net.ParseCIDR("2001:db8::/64")
var testCases = []struct {
@ -489,26 +490,6 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
},
{
name: "request is from external IP has valid + UNTRUSTED external X-Real-Ip header, extract IP from remote addr",
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"}, // <-- this is untrusted
},
RemoteAddr: "203.0.113.1:8080",
},
expectIP: "203.0.113.1",
},
{
name: "request is from external IP has valid + UNTRUSTED external X-Real-Ip header, extract IP from remote addr",
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"[2001:db8::113:199]"}, // <-- this is untrusted
},
RemoteAddr: "[2001:db8::113:1]:8080",
},
expectIP: "2001:db8::113:1",
},
{
name: "request is from external IP has valid + TRUSTED X-Real-Ip header, extract IP from X-Real-Ip header",
givenTrustOptions: []TrustOption{ // case for "trust direct-facing proxy"
TrustIPRange(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.199/24"
},
@ -516,9 +497,35 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"},
},
RemoteAddr: "8.8.8.8:8080", // <-- this is untrusted
},
expectIP: "8.8.8.8",
},
{
name: "request is from external IP has valid + UNTRUSTED external X-Real-Ip header, extract IP from remote addr",
givenTrustOptions: []TrustOption{ // case for "trust direct-facing proxy"
TrustIPRange(ipv6ForRemoteAddrExternalRange), // we trust external IP range "203.0.113.199/24"
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"[bc01:1010::9090:1888]"},
},
RemoteAddr: "[fe64:aa10::1]:8080", // <-- this is untrusted
},
expectIP: "fe64:aa10::1",
},
{
name: "request is from external IP has valid + TRUSTED X-Real-Ip header, extract IP from X-Real-Ip header",
givenTrustOptions: []TrustOption{ // case for "trust direct-facing proxy"
TrustIPRange(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.0/24"
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"8.8.8.8"},
},
RemoteAddr: "203.0.113.1:8080",
},
expectIP: "203.0.113.199",
expectIP: "8.8.8.8",
},
{
name: "request is from external IP has valid + TRUSTED X-Real-Ip header, extract IP from X-Real-Ip header",
@ -527,11 +534,11 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"[2001:db8::113:199]"},
HeaderXRealIP: []string{"[fe64:db8::113:199]"},
},
RemoteAddr: "[2001:db8::113:1]:8080",
},
expectIP: "2001:db8::113:199",
expectIP: "fe64:db8::113:199",
},
{
name: "request is from external IP has XFF and valid + TRUSTED X-Real-Ip header, extract IP from X-Real-Ip header",
@ -540,12 +547,12 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"},
HeaderXForwardedFor: []string{"203.0.113.198, 203.0.113.197"}, // <-- should not affect anything
HeaderXRealIP: []string{"8.8.8.8"},
HeaderXForwardedFor: []string{"1.1.1.1 ,8.8.8.8"}, // <-- should not affect anything
},
RemoteAddr: "203.0.113.1:8080",
},
expectIP: "203.0.113.199",
expectIP: "8.8.8.8",
},
{
name: "request is from external IP has XFF and valid + TRUSTED X-Real-Ip header, extract IP from X-Real-Ip header",
@ -554,12 +561,12 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"[2001:db8::113:199]"},
HeaderXForwardedFor: []string{"[2001:db8::113:198], [2001:db8::113:197]"}, // <-- should not affect anything
HeaderXRealIP: []string{"[fe64:db8::113:199]"},
HeaderXForwardedFor: []string{"[feab:cde9::113:198], [fe64:db8::113:199]"}, // <-- should not affect anything
},
RemoteAddr: "[2001:db8::113:1]:8080",
},
expectIP: "2001:db8::113:199",
expectIP: "fe64:db8::113:199",
},
}