如何使用 httputil.ReverseProxy 设置 X-Forwarded-For

我为什么要这样做

我已经两次遇到这个问题。


第一次是使用位于仅 IPv6 服务器网络内的反向代理。客户端请求通过 NAT46 传入。请求的源 IP 变为 [固定的 96 位前缀] + [32 位客户端 IPv4 地址]。这意味着反向代理始终可以识别真实的客户端 IP。不过,我找不到将X-Forwarded-For标头设置为该地址的方法。我通过修改后端服务器解决了这个问题。


这次我有一个将在 Google App Engine 上运行的反向代理。请求首先到达 Google 的负载均衡器,它添加X-Forwarded-For标头并将请求转发到我的应用程序。我想稍微修改一下请求,然后将其传递给后端服务器,我无法修改。后端需要原始客户端IP,并且可以通过X-Forwarded-For(已通过身份验证,不用担心)接受它。在这种情况下,我想X-Forwarded-For通过未修改的方式传递来自 Google 负载均衡器的标头。


问题

似乎无法设置X-Forwarded-For为我在使用时选择的值httputil.ReverseProxy。如果我设置它(下面的选项 1),将附加来自 TCP 连接的客户端地址。如果我将它设置为nil(下面的选项 2),它会像文档中建议的那样被省略,但这也不是我想要的。


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,

    })

}

选项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"

}

选项 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"

}


守候你守候我
浏览 186回答 1
1回答

杨魅力

我相信你有两个选择。1.实施http.RoundTripper您实现自己的RoundTripper并在那里重新设置X-Forwarded-For。(示范)type MyRoundTripper struct{}func (t *MyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {    req.Header["X-Forwarded-For"] = []string{"1.2.3.4"}    return http.DefaultTransport.RoundTrip(req)}func main() {    http.ListenAndServe(":80", &httputil.ReverseProxy{        Director: director,        Transport: &MyRoundTripper{},    })}当Transport未设置该字段时,httputil.ReverseProxy它会回退到http.DefaultTransport,因此您也可以在自定义代码后回退到它。2.取消设置req.RemoteAddrRemoteAddr在调用反向代理之前重置原始请求的字段。该字段由 HTTP 服务器设置,如果存在,将触发X-Forwarded-For反向代理实现中的替换。(示范)func main() {    http.ListenAndServe(":80", func(w http.ResponseWriter, r *http.Request) {        r.RemoteAddr = ""        proxy := &httputil.ReverseProxy{ Director: director }         proxy.ServeHTTP(w, r)        })}但是,此行为依赖于实现细节,将来可能会或可能不会更改。我建议改用选项 1。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go