[MM-15639] Add config setting to explicitly define which IP headers are trusted (#10907)
* Add config setting to explicitly define which IP headers are trusted * fix variable shadowing * Optimize code flow; Add Ratelimit test for header set * Extend Ratelimit tests * Add additional unit tests * Structured logging
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e8af4872c6
Коммит
2d97f01781
@@ -8,8 +8,6 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
func StringInSlice(a string, slice []string) bool {
|
||||
@@ -68,19 +66,21 @@ func StringSliceDiff(a, b []string) []string {
|
||||
return result
|
||||
}
|
||||
|
||||
func GetIpAddress(r *http.Request) string {
|
||||
func GetIpAddress(r *http.Request, trustedProxyIPHeader []string) string {
|
||||
address := ""
|
||||
|
||||
header := r.Header.Get(model.HEADER_FORWARDED)
|
||||
if len(header) > 0 {
|
||||
addresses := strings.Fields(header)
|
||||
if len(addresses) > 0 {
|
||||
address = strings.TrimRight(addresses[0], ",")
|
||||
for _, proxyHeader := range trustedProxyIPHeader {
|
||||
header := r.Header.Get(proxyHeader)
|
||||
if len(header) > 0 {
|
||||
addresses := strings.Fields(header)
|
||||
if len(addresses) > 0 {
|
||||
address = strings.TrimRight(addresses[0], ",")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(address) == 0 {
|
||||
address = r.Header.Get(model.HEADER_REAL_IP)
|
||||
if len(address) > 0 {
|
||||
return address
|
||||
}
|
||||
}
|
||||
|
||||
if len(address) == 0 {
|
||||
|
||||
@@ -66,7 +66,7 @@ func TestGetIpAddress(t *testing.T) {
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.0.0.1", GetIpAddress(&httpRequest1))
|
||||
assert.Equal(t, "10.0.0.1", GetIpAddress(&httpRequest1, []string{"X-Forwarded-For"}))
|
||||
|
||||
// Test with multiple IPs in the X-Forwarded-For
|
||||
httpRequest2 := http.Request{
|
||||
@@ -77,7 +77,7 @@ func TestGetIpAddress(t *testing.T) {
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.0.0.1", GetIpAddress(&httpRequest2))
|
||||
assert.Equal(t, "10.0.0.1", GetIpAddress(&httpRequest2, []string{"X-Forwarded-For"}))
|
||||
|
||||
// Test with an empty X-Forwarded-For
|
||||
httpRequest3 := http.Request{
|
||||
@@ -88,7 +88,7 @@ func TestGetIpAddress(t *testing.T) {
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest3))
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest3, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
|
||||
// Test without an X-Fowarded-For
|
||||
httpRequest4 := http.Request{
|
||||
@@ -98,12 +98,65 @@ func TestGetIpAddress(t *testing.T) {
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest4))
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest4, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
|
||||
// Test without any headers
|
||||
httpRequest5 := http.Request{
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIpAddress(&httpRequest5))
|
||||
assert.Equal(t, "10.2.0.1", GetIpAddress(&httpRequest5, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
|
||||
// Test with both headers, but both untrusted
|
||||
httpRequest6 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIpAddress(&httpRequest6, nil))
|
||||
|
||||
// Test with both headers, but only X-Real-Ip trusted
|
||||
httpRequest7 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest7, []string{"X-Real-Ip"}))
|
||||
|
||||
// Test with X-Forwarded-For, comma separated, untrusted
|
||||
httpRequest8 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIpAddress(&httpRequest8, nil))
|
||||
|
||||
// Test with X-Forwarded-For, comma separated, untrusted
|
||||
httpRequest9 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.3.0.1", GetIpAddress(&httpRequest9, []string{"X-Forwarded-For"}))
|
||||
|
||||
// Test with both headers, both allowed, first one in trusted used
|
||||
httpRequest10 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIpAddress(&httpRequest10, []string{"X-Real-Ip", "X-Forwarded-For"}))
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user