mirror of
https://github.com/minio/minio.git
synced 2025-03-06 00:30:09 -05:00
Allow disabling of all X-Forwarded-For header processing (#20977)
This commit is contained in:
parent
f129fd48f2
commit
7cc0c69228
@ -26,6 +26,9 @@ import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/internal/config"
|
||||
"github.com/minio/pkg/v3/env"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -51,6 +54,9 @@ var (
|
||||
protoRegex = regexp.MustCompile(`(?i)^(;|,| )+(?:proto=)(https|http)`)
|
||||
)
|
||||
|
||||
// Used to disable all processing of the X-Forwarded-For header in source IP discovery.
|
||||
var enableXFFHeader = env.Get("_MINIO_API_XFF_HEADER", config.EnableOn) == config.EnableOn
|
||||
|
||||
// GetSourceScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
|
||||
// Forwarded headers (in that order).
|
||||
func GetSourceScheme(r *http.Request) string {
|
||||
@ -84,29 +90,35 @@ func GetSourceScheme(r *http.Request) string {
|
||||
func GetSourceIPFromHeaders(r *http.Request) string {
|
||||
var addr string
|
||||
|
||||
if fwd := r.Header.Get(xForwardedFor); fwd != "" {
|
||||
// Only grab the first (client) address. Note that '192.168.0.1,
|
||||
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
|
||||
// the first may represent forwarding proxies earlier in the chain.
|
||||
s := strings.Index(fwd, ", ")
|
||||
if s == -1 {
|
||||
s = len(fwd)
|
||||
if enableXFFHeader {
|
||||
if fwd := r.Header.Get(xForwardedFor); fwd != "" {
|
||||
// Only grab the first (client) address. Note that '192.168.0.1,
|
||||
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
|
||||
// the first may represent forwarding proxies earlier in the chain.
|
||||
s := strings.Index(fwd, ", ")
|
||||
if s == -1 {
|
||||
s = len(fwd)
|
||||
}
|
||||
addr = fwd[:s]
|
||||
}
|
||||
addr = fwd[:s]
|
||||
} else if fwd := r.Header.Get(xRealIP); fwd != "" {
|
||||
// X-Real-IP should only contain one IP address (the client making the
|
||||
// request).
|
||||
addr = fwd
|
||||
} else if fwd := r.Header.Get(forwarded); fwd != "" {
|
||||
// match should contain at least two elements if the protocol was
|
||||
// specified in the Forwarded header. The first element will always be
|
||||
// the 'for=' capture, which we ignore. In the case of multiple IP
|
||||
// addresses (for=8.8.8.8, 8.8.4.4, 172.16.1.20 is valid) we only
|
||||
// extract the first, which should be the client IP.
|
||||
if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
|
||||
// IPv6 addresses in Forwarded headers are quoted-strings. We strip
|
||||
// these quotes.
|
||||
addr = strings.Trim(match[1], `"`)
|
||||
}
|
||||
|
||||
if addr == "" {
|
||||
if fwd := r.Header.Get(xRealIP); fwd != "" {
|
||||
// X-Real-IP should only contain one IP address (the client making the
|
||||
// request).
|
||||
addr = fwd
|
||||
} else if fwd := r.Header.Get(forwarded); fwd != "" {
|
||||
// match should contain at least two elements if the protocol was
|
||||
// specified in the Forwarded header. The first element will always be
|
||||
// the 'for=' capture, which we ignore. In the case of multiple IP
|
||||
// addresses (for=8.8.8.8, 8.8.4.4, 172.16.1.20 is valid) we only
|
||||
// extract the first, which should be the client IP.
|
||||
if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
|
||||
// IPv6 addresses in Forwarded headers are quoted-strings. We strip
|
||||
// these quotes.
|
||||
addr = strings.Trim(match[1], `"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,3 +84,27 @@ func TestGetSourceIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestXFFDisabled(t *testing.T) {
|
||||
req := &http.Request{
|
||||
Header: http.Header{
|
||||
xForwardedFor: []string{"8.8.8.8"},
|
||||
xRealIP: []string{"1.1.1.1"},
|
||||
},
|
||||
}
|
||||
// When X-Forwarded-For and X-Real-IP headers are both present, X-Forwarded-For takes precedence.
|
||||
res := GetSourceIP(req)
|
||||
if res != "8.8.8.8" {
|
||||
t.Errorf("wrong header, xff takes precedence: got %s, want: 8.8.8.8", res)
|
||||
}
|
||||
|
||||
// When explicitly disabled, the XFF header is ignored and X-Real-IP is used.
|
||||
enableXFFHeader = false
|
||||
defer func() {
|
||||
enableXFFHeader = true
|
||||
}()
|
||||
res = GetSourceIP(req)
|
||||
if res != "1.1.1.1" {
|
||||
t.Errorf("wrong header, xff is disabled: got %s, want: 1.1.1.1", res)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user