1
0
mirror of https://github.com/labstack/echo.git synced 2025-04-21 12:17:04 +02:00

Fix Real IP logic ()

* 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

@ -228,15 +228,21 @@ func extractIP(req *http.Request) string {
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor { func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
checker := newIPChecker(options) checker := newIPChecker(options)
return func(req *http.Request) string { return func(req *http.Request) string {
directIP := extractIP(req)
realIP := req.Header.Get(HeaderXRealIP) realIP := req.Header.Get(HeaderXRealIP)
if realIP != "" { if realIP == "" {
return directIP
}
if checker.trust(net.ParseIP(directIP)) {
realIP = strings.TrimPrefix(realIP, "[") realIP = strings.TrimPrefix(realIP, "[")
realIP = strings.TrimSuffix(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 realIP
} }
} }
return extractIP(req)
return directIP
} }
} }

@ -4,10 +4,11 @@
package echo package echo
import ( import (
"github.com/stretchr/testify/assert"
"net" "net"
"net/http" "net/http"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func mustParseCIDR(s string) *net.IPNet { func mustParseCIDR(s string) *net.IPNet {
@ -461,7 +462,7 @@ func TestExtractIPDirect(t *testing.T) {
} }
func TestExtractIPFromRealIPHeader(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") _, ipv6ForRemoteAddrExternalRange, _ := net.ParseCIDR("2001:db8::/64")
var testCases = []struct { 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", 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" givenTrustOptions: []TrustOption{ // case for "trust direct-facing proxy"
TrustIPRange(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.199/24" TrustIPRange(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.199/24"
}, },
@ -516,9 +497,35 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
Header: http.Header{ Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"}, 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", 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", 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{ whenRequest: http.Request{
Header: http.Header{ Header: http.Header{
HeaderXRealIP: []string{"[2001:db8::113:199]"}, HeaderXRealIP: []string{"[fe64:db8::113:199]"},
}, },
RemoteAddr: "[2001:db8::113:1]:8080", 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", 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{ whenRequest: http.Request{
Header: http.Header{ Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"}, HeaderXRealIP: []string{"8.8.8.8"},
HeaderXForwardedFor: []string{"203.0.113.198, 203.0.113.197"}, // <-- should not affect anything HeaderXForwardedFor: []string{"1.1.1.1 ,8.8.8.8"}, // <-- should not affect anything
}, },
RemoteAddr: "203.0.113.1:8080", 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", 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{ whenRequest: http.Request{
Header: http.Header{ Header: http.Header{
HeaderXRealIP: []string{"[2001:db8::113:199]"}, HeaderXRealIP: []string{"[fe64:db8::113:199]"},
HeaderXForwardedFor: []string{"[2001:db8::113:198], [2001:db8::113:197]"}, // <-- should not affect anything HeaderXForwardedFor: []string{"[feab:cde9::113:198], [fe64:db8::113:199]"}, // <-- should not affect anything
}, },
RemoteAddr: "[2001:db8::113:1]:8080", RemoteAddr: "[2001:db8::113:1]:8080",
}, },
expectIP: "2001:db8::113:199", expectIP: "fe64:db8::113:199",
}, },
} }