Skip to content

Commit

Permalink
Fix Real IP logic (#2550)
Browse files Browse the repository at this point in the history
* Fix realIP logic
  • Loading branch information
cl-bvl authored Mar 10, 2024
1 parent 3598f29 commit a3b0ba2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 22 deletions.
12 changes: 9 additions & 3 deletions ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
45 changes: 26 additions & 19 deletions ip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -489,36 +490,42 @@ func TestExtractIPFromRealIPHeader(t *testing.T) {
},
{
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(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.199/24"
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"}, // <-- this is untrusted
HeaderXRealIP: []string{"203.0.113.199"},
},
RemoteAddr: "203.0.113.1:8080",
RemoteAddr: "8.8.8.8:8080", // <-- this is untrusted
},
expectIP: "203.0.113.1",
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{"[2001:db8::113:199]"}, // <-- this is untrusted
HeaderXRealIP: []string{"[bc01:1010::9090:1888]"},
},
RemoteAddr: "[2001:db8::113:1]:8080",
RemoteAddr: "[fe64:aa10::1]:8080", // <-- this is untrusted
},
expectIP: "2001:db8::113:1",
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.199/24"
TrustIPRange(ipForRemoteAddrExternalRange), // we trust external IP range "203.0.113.0/24"
},
whenRequest: http.Request{
Header: http.Header{
HeaderXRealIP: []string{"203.0.113.199"},
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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
},
}

Expand Down

0 comments on commit a3b0ba2

Please sign in to comment.