From e925fc1ab537c15b413fc5829db5a692548ea427 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sun, 8 Sep 2019 13:39:41 -0600
Subject: [PATCH] Support a config option for accepting the XFF header as-is

Useful in a limited number of scenarios.

Fixes https://github.com/turt2live/matrix-media-repo/issues/112
---
 api/webserver/route_handler.go | 12 +++++++++++-
 common/config/config.go        | 14 ++++++++------
 config.sample.yaml             |  5 +++++
 3 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/api/webserver/route_handler.go b/api/webserver/route_handler.go
index c1efdb60..8c5ff41d 100644
--- a/api/webserver/route_handler.go
+++ b/api/webserver/route_handler.go
@@ -17,6 +17,7 @@ import (
 	"github.com/turt2live/matrix-media-repo/api"
 	"github.com/turt2live/matrix-media-repo/api/r0"
 	"github.com/turt2live/matrix-media-repo/common"
+	"github.com/turt2live/matrix-media-repo/common/config"
 	"github.com/turt2live/matrix-media-repo/metrics"
 	"github.com/turt2live/matrix-media-repo/util"
 )
@@ -36,7 +37,16 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 	r.Host = strings.Split(r.Host, ":")[0]
 
-	raddr := xff.GetRemoteAddr(r)
+	var raddr string
+	if config.Get().General.TrustAnyForward {
+		raddr = r.Header.Get("X-Forwarded-For")
+	} else {
+		raddr = xff.GetRemoteAddr(r)
+	}
+	if raddr == "" {
+		raddr = r.RemoteAddr
+	}
+
 	host, _, err := net.SplitHostPort(raddr)
 	if err != nil {
 		logrus.Error(err)
diff --git a/common/config/config.go b/common/config/config.go
index 23b961da..8a4320eb 100644
--- a/common/config/config.go
+++ b/common/config/config.go
@@ -23,9 +23,10 @@ type HomeserverConfig struct {
 }
 
 type GeneralConfig struct {
-	BindAddress  string `yaml:"bindAddress"`
-	Port         int    `yaml:"port"`
-	LogDirectory string `yaml:"logDirectory"`
+	BindAddress     string `yaml:"bindAddress"`
+	Port            int    `yaml:"port"`
+	LogDirectory    string `yaml:"logDirectory"`
+	TrustAnyForward bool   `yaml:"trustAnyForwardedAddress"`
 }
 
 type DbPoolConfig struct {
@@ -218,9 +219,10 @@ func Get() *MediaRepoConfig {
 func NewDefaultConfig() *MediaRepoConfig {
 	return &MediaRepoConfig{
 		General: &GeneralConfig{
-			BindAddress:  "127.0.0.1",
-			Port:         8000,
-			LogDirectory: "logs",
+			BindAddress:     "127.0.0.1",
+			Port:            8000,
+			LogDirectory:    "logs",
+			TrustAnyForward: false,
 		},
 		Database: &DatabaseConfig{
 			Postgres: "postgres://your_username:your_password@localhost/database_name?sslmode=disable",
diff --git a/config.sample.yaml b/config.sample.yaml
index 413de268..45a1d5c6 100644
--- a/config.sample.yaml
+++ b/config.sample.yaml
@@ -7,6 +7,11 @@ repo:
   # rotated every day and held for 14 days. To disable the repo logging to files, set this to "-".
   logDirectory: logs
 
+  # If true, the media repo will accept any X-Forwarded-For header without validation. In most cases
+  # this option should be left as "false". Note that the media repo already expects an X-Forwarded-For
+  # header, but validates it to ensure the IP being given makes sense.
+  trustAnyForwardedAddress: false
+
 # The database configuration for the media repository
 database:
   # Currently only "postgres" is supported.
-- 
GitLab