Browse Source

add support for ipv6 with zone index

y0ast 5 years ago
parent
commit
05fd83bd6f
2 changed files with 36 additions and 4 deletions
  1. 12 4
      http/request/client_ip.go
  2. 24 0
      http/request/client_ip_test.go

+ 12 - 4
http/request/client_ip.go

@@ -10,6 +10,14 @@ import (
 	"strings"
 )
 
+func dropIPv6zone(address string) string {
+	i := strings.IndexByte(address, '%')
+	if i != -1 {
+		address = address[:i]
+	}
+	return address
+}
+
 // FindClientIP returns client real IP address.
 func FindClientIP(r *http.Request) string {
 	headers := []string{"X-Forwarded-For", "X-Real-Ip"}
@@ -19,6 +27,7 @@ func FindClientIP(r *http.Request) string {
 		if value != "" {
 			addresses := strings.Split(value, ",")
 			address := strings.TrimSpace(addresses[0])
+			address = dropIPv6zone(address)
 
 			if net.ParseIP(address) != nil {
 				return address
@@ -27,12 +36,11 @@ func FindClientIP(r *http.Request) string {
 	}
 
 	// Fallback to TCP/IP source IP address.
-	var remoteIP string
-	if strings.ContainsRune(r.RemoteAddr, ':') {
-		remoteIP, _, _ = net.SplitHostPort(r.RemoteAddr)
-	} else {
+	remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
+	if err != nil {
 		remoteIP = r.RemoteAddr
 	}
+	remoteIP = dropIPv6zone(remoteIP)
 
 	// When listening on a Unix socket, RemoteAddr is empty.
 	if remoteIP == "" {

+ 24 - 0
http/request/client_ip_test.go

@@ -19,6 +19,21 @@ func TestFindClientIPWithoutHeaders(t *testing.T) {
 	if ip := FindClientIP(r); ip != "192.168.0.1" {
 		t.Fatalf(`Unexpected result, got: %q`, ip)
 	}
+
+	r = &http.Request{RemoteAddr: "fe80::14c2:f039:edc7:edc7"}
+	if ip := FindClientIP(r); ip != "fe80::14c2:f039:edc7:edc7" {
+		t.Fatalf(`Unexpected result, got: %q`, ip)
+	}
+
+	r = &http.Request{RemoteAddr: "fe80::14c2:f039:edc7:edc7%eth0"}
+	if ip := FindClientIP(r); ip != "fe80::14c2:f039:edc7:edc7" {
+		t.Fatalf(`Unexpected result, got: %q`, ip)
+	}
+
+	r = &http.Request{RemoteAddr: "[fe80::14c2:f039:edc7:edc7%eth0]:4242"}
+	if ip := FindClientIP(r); ip != "fe80::14c2:f039:edc7:edc7" {
+		t.Fatalf(`Unexpected result, got: %q`, ip)
+	}
 }
 
 func TestFindClientIPWithXFFHeader(t *testing.T) {
@@ -40,6 +55,15 @@ func TestFindClientIPWithXFFHeader(t *testing.T) {
 		t.Fatalf(`Unexpected result, got: %q`, ip)
 	}
 
+	// Test with single IPv6 address with zone
+	headers = http.Header{}
+	headers.Set("X-Forwarded-For", "fe80::14c2:f039:edc7:edc7%eth0")
+	r = &http.Request{RemoteAddr: "192.168.0.1:4242", Header: headers}
+
+	if ip := FindClientIP(r); ip != "fe80::14c2:f039:edc7:edc7" {
+		t.Fatalf(`Unexpected result, got: %q`, ip)
+	}
+
 	// Test with single IPv4 address.
 	headers = http.Header{}
 	headers.Set("X-Forwarded-For", "70.41.3.18")