fix(middlewares): failure to detect remote ip (#5339)
This fixes an edge case where the RemoteIP detection could safely fail with an error, and instead defaults to the TCP packet information. Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/5340/head
parent
c3cc4061b8
commit
34ec813370
|
@ -452,12 +452,13 @@ func (ctx *AutheliaCtx) SetJSONBody(value any) error {
|
||||||
|
|
||||||
// RemoteIP return the remote IP taking X-Forwarded-For header into account if provided.
|
// RemoteIP return the remote IP taking X-Forwarded-For header into account if provided.
|
||||||
func (ctx *AutheliaCtx) RemoteIP() net.IP {
|
func (ctx *AutheliaCtx) RemoteIP() net.IP {
|
||||||
XForwardedFor := ctx.Request.Header.PeekBytes(headerXForwardedFor)
|
if header := ctx.Request.Header.PeekBytes(headerXForwardedFor); len(header) != 0 {
|
||||||
if XForwardedFor != nil {
|
ips := strings.SplitN(string(header), ",", 2)
|
||||||
ips := strings.Split(string(XForwardedFor), ",")
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) != 0 {
|
||||||
return net.ParseIP(strings.Trim(ips[0], " "))
|
if ip := net.ParseIP(strings.Trim(ips[0], " ")); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package middlewares_test
|
package middlewares_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -17,6 +18,37 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestAutheliaCtx_RemoteIP(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
have []byte
|
||||||
|
expected net.IP
|
||||||
|
}{
|
||||||
|
{"ShouldDefaultToRemoteAddr", nil, net.ParseIP("127.0.0.127")},
|
||||||
|
{"ShouldParseProperlyFormattedXFFWithIPv4", []byte("192.168.1.1, 127.0.0.1"), net.ParseIP("192.168.1.1")},
|
||||||
|
{"ShouldParseProperlyFormattedXFFWithIPv6", []byte("2001:db8:85a3:8d3:1319:8a2e:370:7348, 127.0.0.1"), net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348")},
|
||||||
|
{"ShouldFallbackToRemoteAddrOnImproperlyFormattedXFFWithIPv6", []byte("[2001:db8:85a3:8d3:1319:8a2e:370:7348], 127.0.0.1"), net.ParseIP("127.0.0.127")},
|
||||||
|
{"ShouldFallbackToRemoteAddrOnBlankXFFHeader", []byte(""), net.ParseIP("127.0.0.127")},
|
||||||
|
{"ShouldFallbackToRemoteAddrOnBlankXFFEntry", []byte(", 127.0.0.1"), net.ParseIP("127.0.0.127")},
|
||||||
|
{"ShouldFallbackToRemoteAddrOnBadXFFEntry", []byte("abc, 127.0.0.1"), net.ParseIP("127.0.0.127")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
mock := mocks.NewMockAutheliaCtx(t)
|
||||||
|
defer mock.Close()
|
||||||
|
|
||||||
|
mock.Ctx.SetRemoteAddr(&net.TCPAddr{Port: 80, IP: net.ParseIP("127.0.0.127")})
|
||||||
|
|
||||||
|
if tc.have != nil {
|
||||||
|
mock.Ctx.RequestCtx.Request.Header.SetBytesV(fasthttp.HeaderXForwardedFor, tc.have)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expected, mock.Ctx.RemoteIP())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContentTypes(t *testing.T) {
|
func TestContentTypes(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
Loading…
Reference in New Issue