mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
caddyhttp: Accept XFF header values with ports, when parsing client IP (#6183)
This commit is contained in:
parent
e65b97f55b
commit
63d597c09d
2 changed files with 34 additions and 7 deletions
|
@ -902,9 +902,18 @@ func trustedRealClientIP(r *http.Request, headers []string, clientIP string) str
|
||||||
allValues := strings.Split(strings.Join(values, ","), ",")
|
allValues := strings.Split(strings.Join(values, ","), ",")
|
||||||
|
|
||||||
// Get first valid left-most IP address
|
// Get first valid left-most IP address
|
||||||
for _, ip := range allValues {
|
for _, part := range allValues {
|
||||||
ip, _, _ = strings.Cut(strings.TrimSpace(ip), "%")
|
// Some proxies may retain the port number, so split if possible
|
||||||
ipAddr, err := netip.ParseAddr(ip)
|
host, _, err := net.SplitHostPort(part)
|
||||||
|
if err != nil {
|
||||||
|
host = part
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any zone identifier from the IP address
|
||||||
|
host, _, _ = strings.Cut(strings.TrimSpace(host), "%")
|
||||||
|
|
||||||
|
// Parse the IP address
|
||||||
|
ipAddr, err := netip.ParseAddr(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -921,11 +930,20 @@ func trustedRealClientIP(r *http.Request, headers []string, clientIP string) str
|
||||||
// remote address is returned.
|
// remote address is returned.
|
||||||
func strictUntrustedClientIp(r *http.Request, headers []string, trusted []netip.Prefix, clientIP string) string {
|
func strictUntrustedClientIp(r *http.Request, headers []string, trusted []netip.Prefix, clientIP string) string {
|
||||||
for _, headerName := range headers {
|
for _, headerName := range headers {
|
||||||
ips := strings.Split(strings.Join(r.Header.Values(headerName), ","), ",")
|
parts := strings.Split(strings.Join(r.Header.Values(headerName), ","), ",")
|
||||||
|
|
||||||
for i := len(ips) - 1; i >= 0; i-- {
|
for i := len(parts) - 1; i >= 0; i-- {
|
||||||
ip, _, _ := strings.Cut(strings.TrimSpace(ips[i]), "%")
|
// Some proxies may retain the port number, so split if possible
|
||||||
ipAddr, err := netip.ParseAddr(ip)
|
host, _, err := net.SplitHostPort(parts[i])
|
||||||
|
if err != nil {
|
||||||
|
host = parts[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any zone identifier from the IP address
|
||||||
|
host, _, _ = strings.Cut(strings.TrimSpace(host), "%")
|
||||||
|
|
||||||
|
// Parse the IP address
|
||||||
|
ipAddr, err := netip.ParseAddr(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,15 @@ func TestServer_TrustedRealClientIP_OneTrustedHeaderValidArray(t *testing.T) {
|
||||||
assert.Equal(t, ip, "1.1.1.1")
|
assert.Equal(t, ip, "1.1.1.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServer_TrustedRealClientIP_IncludesPort(t *testing.T) {
|
||||||
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
|
req.RemoteAddr = "192.0.2.1:12345"
|
||||||
|
req.Header.Set("X-Forwarded-For", "1.1.1.1:1234")
|
||||||
|
ip := trustedRealClientIP(req, []string{"X-Forwarded-For"}, "192.0.2.1")
|
||||||
|
|
||||||
|
assert.Equal(t, ip, "1.1.1.1")
|
||||||
|
}
|
||||||
|
|
||||||
func TestServer_TrustedRealClientIP_SkipsInvalidIps(t *testing.T) {
|
func TestServer_TrustedRealClientIP_SkipsInvalidIps(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
req.RemoteAddr = "192.0.2.1:12345"
|
req.RemoteAddr = "192.0.2.1:12345"
|
||||||
|
|
Loading…
Reference in a new issue