lib/httpserver: properly quote the returned address from GetQuotedRemoteAddr() for requests with X-Forwarded-For header

Make sure that the quoted address can be used as JSON string.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4676#issuecomment-1663203424

This is a follow up for 252643d100 and ac0b7e0421

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4676
This commit is contained in:
Aliaksandr Valialkin 2023-08-11 05:19:44 -07:00
parent ac0b7e0421
commit be5c4818f5
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
3 changed files with 41 additions and 3 deletions

View file

@ -47,6 +47,7 @@ The following `tip` changes can be tested by building VictoriaMetrics components
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): fix `vmalert_remotewrite_send_duration_seconds_total` value, before it didn't count in the real time spending on remote write requests. See [this pr](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4801) for details.
* BUGFIX: [vmbackupmanager](https://docs.victoriametrics.com/vmbackupmanager.html): fix panic when creating a backup to a local filesystem on Windows. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4704).
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): keep unmatched series when `remoteWrite.streamAggr.dropInput` is set to `false` to match intended behaviour introduced at [v1.92.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.92.0). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4804).
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): properly handle client address with `X-Forwarded-For` part. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4676#issuecomment-1663203424).
## [v1.92.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.92.1)

View file

@ -436,11 +436,12 @@ var (
// GetQuotedRemoteAddr returns quoted remote address.
func GetQuotedRemoteAddr(r *http.Request) string {
remoteAddr := strconv.Quote(r.RemoteAddr) // quote remoteAddr and X-Forwarded-For, since they may contain untrusted input
remoteAddr := r.RemoteAddr
if addr := r.Header.Get("X-Forwarded-For"); addr != "" {
remoteAddr += ", X-Forwarded-For: " + strconv.Quote(addr)
remoteAddr += ", X-Forwarded-For: " + addr
}
return remoteAddr
// quote remoteAddr and X-Forwarded-For, since they may contain untrusted input
return strconv.Quote(remoteAddr)
}
// Errorf writes formatted error message to w and to logger.

View file

@ -0,0 +1,36 @@
package httpserver
import (
"encoding/json"
"net/http"
"testing"
)
func TestGetQuotedRemoteAddr(t *testing.T) {
f := func(remoteAddr, xForwardedFor, expectedAddr string) {
t.Helper()
req := &http.Request{
RemoteAddr: remoteAddr,
}
if xForwardedFor != "" {
req.Header = map[string][]string{
"X-Forwarded-For": {xForwardedFor},
}
}
addr := GetQuotedRemoteAddr(req)
if addr != expectedAddr {
t.Fatalf("unexpected remote addr;\ngot\n%s\nwant\n%s", addr, expectedAddr)
}
// Verify that the addr can be unmarshaled as JSON string
var s string
if err := json.Unmarshal([]byte(addr), &s); err != nil {
t.Fatalf("cannot unmarshal addr: %s", err)
}
}
f("1.2.3.4", "", `"1.2.3.4"`)
f("1.2.3.4", "foo.bar", `"1.2.3.4, X-Forwarded-For: foo.bar"`)
f("1.2\n\"3.4", "foo\nb\"ar", `"1.2\n\"3.4, X-Forwarded-For: foo\nb\"ar"`)
}