Why would I want to do this
I have run in to this issue twice.
The first time was with a reverse proxy that lived inside an IPv6 only server network. Client requests come in through NAT46. The source-IP of the request becomes [fixed 96-bit prefix] + [32-bit client IPv4 address]. This means that the reverse proxy could always identify the real client IP. I couldn't find a way to set the X-Forwarded-For header to that address though. I got around it by modifying the backend server.
This time I have a reverse proxy which will run on Google App Engine. Requests hit Google's load balancer first, which adds the X-Forwarded-For header and forwards the request to my app. I want to modify the request a bit and then pass it to a backend server, which I cannot modify. The back-end needs the original client IP, and can accept it via X-Forwarded-For (it's authenticated, don't worry). In this case I want to pass the X-Forwarded-For header from Google's load balencer through unmodified.
The Problem
It seems like there is no way to set X-Forwarded-For to a value that I chose when using httputil.ReverseProxy. If I set it (option 1 below) the client address from the TCP connection will be appended. If if I set it to nil (option 2 below), it is omitted like the documentation suggests, but that's not what I want either.
package main
import (
"log"
"net/http"
"net/http/httputil"
)
func director(req *http.Request) {
// currently running a PHP script that just records headers
host := "bsweb02.bentonvillek12.org"
// who we dial
req.URL.Scheme = "https"
req.URL.Host = host
// host header
req.Host = host
// proof that most headers can be passed through fine
req.Header["Foo"] = []string{"Bar"}
req.Header["X-Forwarded-For"] = []string{"1.2.3.4"} // option 1
//req.Header["X-Forwarded-For"] = nil // option 2
}
func main() {
http.ListenAndServe(":80", &httputil.ReverseProxy{
Director: director,
})
}
Option 1
array(9) {
["Content-Type"]=>
string(0) ""
["Content-Length"]=>
string(1) "0"
["Foo"]=>
string(3) "Bar"
["X-Forwarded-For"]=>
string(18) "1.2.3.4, 127.0.0.1"
["User-Agent"]=>
string(11) "curl/7.81.0"
["Host"]=>
string(26) "bsweb02.bentonvillek12.org"
["Accept-Encoding"]=>
string(4) "gzip"
["Accept"]=>
string(3) "*/*"
["Connection"]=>
string(5) "close"
}
Option 2
array(8) {
["Content-Type"]=>
string(0) ""
["Content-Length"]=>
string(1) "0"
["Foo"]=>
string(3) "Bar"
["User-Agent"]=>
string(11) "curl/7.81.0"
["Host"]=>
string(26) "bsweb02.bentonvillek12.org"
["Accept-Encoding"]=>
string(4) "gzip"
["Accept"]=>
string(3) "*/*"
["Connection"]=>
string(5) "close"
}