为何Golang反向代理遭Cloudflare拦截而Nginx可正常运行?
解决Golang反向代理访问Cloudflare保护站点返回403的问题
同一主机下Nginx反向代理可正常访问Cloudflare保护的https://icanhazip.com,但Golang实现的反向代理返回403 Forbidden,核心原因是Golang默认反向代理的请求头设置与Nginx不一致,触发了Cloudflare的安全拦截规则。
问题根源
- Nginx默认执行
proxy_pass时,会自动将Host头设置为目标服务器的主机名(即icanhazip.com),同时完整转发客户端的请求头(如User-Agent)。 - Golang的
httputil.NewSingleHostReverseProxy默认会清空未显式设置的User-Agent,且你之前的自定义逻辑错误地将Host头设为代理自身的地址(127.0.0.1:8082),这两个点共同导致Cloudflare判定请求异常。
可行解决方案
需要调整Golang反向代理的请求头设置,确保传递目标服务器的Host头,并保留/设置合法的User-Agent,以下是两种实现方式:
方式一:修改Director函数
package main import ( "fmt" "log" "net/http" "net/http/httputil" "net/url" ) func main() { testUrl, err := url.Parse("https://icanhazip.com") if err != nil { log.Fatal(err) } proxy := httputil.NewSingleHostReverseProxy(testUrl) originalDirector := proxy.Director proxy.Director = func(req *http.Request) { originalDirector(req) // 设置Host为目标服务器的主机名,与Nginx默认行为对齐 req.Header.Set("Host", testUrl.Host) // 保留客户端的User-Agent,若客户端未传递则设置通用浏览器UA if _, ok := req.Header["User-Agent"]; !ok { req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") } } server := http.Server{ Addr: fmt.Sprintf(":%d", 8082), Handler: http.HandlerFunc(proxy.ServeHTTP), } if err := server.ListenAndServe(); err != http.ErrServerClosed { log.Fatal(err) } }
方式二:使用Rewrite自定义代理逻辑
package main import ( "fmt" "log" "net/http" "net/http/httputil" "net/url" ) func main() { testUrl, err := url.Parse("https://icanhazip.com") if err != nil { log.Fatal(err) } proxy := &httputil.ReverseProxy{ Rewrite: func(r *httputil.ProxyRequest) { r.SetURL(testUrl) // 设置Host为目标服务器的主机名 r.Out.Host = testUrl.Host // 转发客户端的User-Agent,无UA时设置默认值 if ua := r.In.Header.Get("User-Agent"); ua != "" { r.Out.Header.Set("User-Agent", ua) } else { r.Out.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") } // 可选:设置X-Forwarded系列头,模拟Nginx的转发行为 r.SetXForwarded() }, } server := http.Server{ Addr: fmt.Sprintf(":%d", 8082), Handler: proxy, } if err := server.ListenAndServe(); err != http.ErrServerClosed { log.Fatal(err) } }
为什么之前的方案无效
你之前尝试的两种方案均错误地将Host头设置为代理自身的地址(r.In.Host即127.0.0.1:8082),这与Nginx默认传递目标服务器Host的行为不符,导致Cloudflare识别请求异常并返回403。
内容的提问来源于stack exchange,提问作者hellopeach
相关产品推荐
相关产品推荐

