Skip to content

Commit

Permalink
Fix inaccessible metrics endpoint when listening on Unix socket
Browse files Browse the repository at this point in the history
elomatreb authored and fguillot committed Dec 7, 2023
1 parent 9503941 commit 698bea4
Showing 3 changed files with 14 additions and 15 deletions.
11 changes: 2 additions & 9 deletions internal/http/request/client_ip.go
Original file line number Diff line number Diff line change
@@ -30,20 +30,13 @@ func FindClientIP(r *http.Request) string {
return FindRemoteIP(r)
}

// FindRemoteIP returns remote client IP address.
// FindRemoteIP returns remote client IP address without considering HTTP headers.
func FindRemoteIP(r *http.Request) string {
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 == "" {
remoteIP = "127.0.0.1"
}

return remoteIP
return dropIPv6zone(remoteIP)
}

func dropIPv6zone(address string) string {
10 changes: 5 additions & 5 deletions internal/http/request/client_ip_test.go
Original file line number Diff line number Diff line change
@@ -104,20 +104,20 @@ func TestClientIPWithBothHeaders(t *testing.T) {
}
}

func TestClientIPWithNoRemoteAddress(t *testing.T) {
r := &http.Request{}
func TestClientIPWithUnixSocketRemoteAddress(t *testing.T) {
r := &http.Request{RemoteAddr: "@"}

if ip := FindClientIP(r); ip != "127.0.0.1" {
if ip := FindClientIP(r); ip != "@" {
t.Fatalf(`Unexpected result, got: %q`, ip)
}
}

func TestClientIPWithoutRemoteAddrAndBothHeaders(t *testing.T) {
func TestClientIPWithUnixSocketRemoteAddrAndBothHeaders(t *testing.T) {
headers := http.Header{}
headers.Set("X-Forwarded-For", "203.0.113.195, 70.41.3.18, 150.172.238.178")
headers.Set("X-Real-Ip", "192.168.122.1")

r := &http.Request{RemoteAddr: "", Header: headers}
r := &http.Request{RemoteAddr: "@", Header: headers}

if ip := FindClientIP(r); ip != "203.0.113.195" {
t.Fatalf(`Unexpected result, got: %q`, ip)
8 changes: 7 additions & 1 deletion internal/http/server/httpd.go
Original file line number Diff line number Diff line change
@@ -268,6 +268,12 @@ func isAllowedToAccessMetricsEndpoint(r *http.Request) bool {
}
}

remoteIP := request.FindRemoteIP(r)
if remoteIP == "@" {
// This indicates a request sent via a Unix socket, always consider these trusted.
return true
}

for _, cidr := range config.Opts.MetricsAllowedNetworks() {
_, network, err := net.ParseCIDR(cidr)
if err != nil {
@@ -283,7 +289,7 @@ func isAllowedToAccessMetricsEndpoint(r *http.Request) bool {

// We use r.RemoteAddr in this case because HTTP headers like X-Forwarded-For can be easily spoofed.
// The recommendation is to use HTTP Basic authentication.
if network.Contains(net.ParseIP(request.FindRemoteIP(r))) {
if network.Contains(net.ParseIP(remoteIP)) {
return true
}
}

0 comments on commit 698bea4

Please sign in to comment.