From 6bfa3e9a47ad99fbd933ed203fa4a74ef461de70 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Fri, 7 Jan 2022 12:33:43 -0700 Subject: [PATCH] Only use X-Forwarded-For if not behind proxy Since you can't trust it when it comes directly from clients. --- boringproxy.go | 3 ++- client.go | 19 +++++++++++-------- cmd/boringproxy/main.go | 16 +++++++++------- http_proxy.go | 15 ++++++++------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/boringproxy.go b/boringproxy.go index 4cb94e2..993f2ce 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -52,6 +52,7 @@ func Listen() { httpsPort := flagSet.Int("https-port", 443, "HTTPS (secure) port") allowHttp := flagSet.Bool("allow-http", false, "Allow unencrypted (HTTP) requests") publicIp := flagSet.String("public-ip", "", "Public IP") + behindProxy := flagSet.Bool("behind-proxy", false, "Whether we're running behind another reverse proxy") err := flagSet.Parse(os.Args[2:]) if err != nil { fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err) @@ -273,7 +274,7 @@ func Listen() { return } - proxyRequest(w, r, tunnel, httpClient, tunnel.TunnelPort) + proxyRequest(w, r, tunnel, httpClient, tunnel.TunnelPort, *behindProxy) } }) diff --git a/client.go b/client.go index fbdb8ed..0a5903a 100644 --- a/client.go +++ b/client.go @@ -30,16 +30,18 @@ type Client struct { cancelFuncs map[string]context.CancelFunc cancelFuncsMutex *sync.Mutex certConfig *certmagic.Config + behindProxy bool } type ClientConfig struct { - ServerAddr string `json:"serverAddr,omitempty"` - Token string `json:"token,omitempty"` - ClientName string `json:"clientName,omitempty"` - User string `json:"user,omitempty"` - CertDir string `json:"certDir,omitempty"` - AcmeEmail string `json:"acmeEmail,omitempty"` - DnsServer string `json:"dnsServer,omitempty"` + ServerAddr string `json:"serverAddr,omitempty"` + Token string `json:"token,omitempty"` + ClientName string `json:"clientName,omitempty"` + User string `json:"user,omitempty"` + CertDir string `json:"certDir,omitempty"` + AcmeEmail string `json:"acmeEmail,omitempty"` + DnsServer string `json:"dnsServer,omitempty"` + BehindProxy bool `json:"behindProxy,omitempty"` } func NewClient(config *ClientConfig) (*Client, error) { @@ -102,6 +104,7 @@ func NewClient(config *ClientConfig) (*Client, error) { cancelFuncs: cancelFuncs, cancelFuncsMutex: cancelFuncsMutex, certConfig: certConfig, + behindProxy: config.BehindProxy, }, nil } @@ -294,7 +297,7 @@ func (c *Client) BoreTunnel(ctx context.Context, tunnel Tunnel) error { httpMux := http.NewServeMux() httpMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - proxyRequest(w, r, tunnel, c.httpClient, tunnel.ClientPort) + proxyRequest(w, r, tunnel, c.httpClient, tunnel.ClientPort, c.behindProxy) }) httpServer := &http.Server{ diff --git a/cmd/boringproxy/main.go b/cmd/boringproxy/main.go index 558d910..12f9fef 100644 --- a/cmd/boringproxy/main.go +++ b/cmd/boringproxy/main.go @@ -46,6 +46,7 @@ func main() { certDir := flagSet.String("cert-dir", "", "TLS cert directory") acmeEmail := flagSet.String("acme-email", "", "Email for ACME (ie Let's Encrypt)") dnsServer := flagSet.String("dns-server", "", "Custom DNS server") + behindProxy := flagSet.Bool("behind-proxy", false, "Whether we're running behind another reverse proxy") err := flagSet.Parse(os.Args[2:]) if err != nil { @@ -65,13 +66,14 @@ func main() { } config := &boringproxy.ClientConfig{ - ServerAddr: *server, - Token: *token, - ClientName: *name, - User: *user, - CertDir: *certDir, - AcmeEmail: *acmeEmail, - DnsServer: *dnsServer, + ServerAddr: *server, + Token: *token, + ClientName: *name, + User: *user, + CertDir: *certDir, + AcmeEmail: *acmeEmail, + DnsServer: *dnsServer, + BehindProxy: *behindProxy, } ctx := context.Background() diff --git a/http_proxy.go b/http_proxy.go index 0b4566e..dd77709 100644 --- a/http_proxy.go +++ b/http_proxy.go @@ -8,7 +8,7 @@ import ( "time" ) -func proxyRequest(w http.ResponseWriter, r *http.Request, tunnel Tunnel, httpClient *http.Client, port int) { +func proxyRequest(w http.ResponseWriter, r *http.Request, tunnel Tunnel, httpClient *http.Client, port int, behindProxy bool) { if tunnel.AuthUsername != "" || tunnel.AuthPassword != "" { username, password, ok := r.BasicAuth() @@ -54,15 +54,16 @@ func proxyRequest(w http.ResponseWriter, r *http.Request, tunnel Tunnel, httpCli // TODO: Handle IPv6 addresses addrParts := strings.Split(r.RemoteAddr, ":") remoteIp := addrParts[0] + xForwardedFor := remoteIp - xForwardedFor := downstreamReqHeaders.Get("X-Forwarded-For") - if xForwardedFor == "" { - xForwardedFor = remoteIp - } else { - xForwardedFor = xForwardedFor + ", " + remoteIp + if behindProxy { + xForwardedFor := downstreamReqHeaders.Get("X-Forwarded-For") + if xForwardedFor != "" { + xForwardedFor = xForwardedFor + ", " + remoteIp + } } - upstreamReq.Header.Set("X-Forwarded-For", xForwardedFor) + upstreamReq.Header.Set("X-Forwarded-For", xForwardedFor) upstreamReq.Header.Set("Forwarded", fmt.Sprintf("for=%s", remoteIp)) upstreamReq.Host = fmt.Sprintf("%s:%d", tunnel.ClientAddress, tunnel.ClientPort)