为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
守候你守候我 2022-11-28 10:15:24
我为什么要这样做我已经两次遇到这个问题。第一次是使用位于仅 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 mainimport (    "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,    })}选项1array(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"}选项 2array(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"}
查看完整描述

1 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

我相信你有两个选择。


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.RemoteAddr

RemoteAddr在调用反向代理之前重置原始请求的字段。该字段由 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。


查看完整回答
反对 回复 2022-11-28
  • 1 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号