gpt4 book ai didi

Go httputil.ReverseProxy 不覆盖 Host header

转载 作者:IT王子 更新时间:2023-10-29 01:25:40 31 4
gpt4 key购买 nike

我基本上是在尝试编写一个反向代理服务器,这样当我 curl localhost:8080/get 时,它会将请求代理到 https://nghttp2.org/httpbin/get

Note: the https://nghttp2.org/httpbin/get service listed above is http/2. But this behavior happens with http/1 as well, such as https://httpbin.org/get.

我正在使用 httputil.ReverseProxy为此,我正在重写 URL,同时自定义 Host header ,以免将 localhost:8080 泄漏到实际后端。

但是,无论我在 header 上设置了多少次,请求仍然会通过 Host: localhost:8080 到达后端。同样,我使用 mitmproxy 来监听请求,看起来 net/http.Client 将 :authority 伪 header 设置为 localhost:8080

这是我的源代码:

package main

import (
"log"
"net/http"
"net/http/httputil"
)

func main() {
proxy := &httputil.ReverseProxy{
Transport: roundTripper(rt),
Director: func(req *http.Request) {
req.URL.Scheme = "https"
req.URL.Host = "nghttp2.org"
req.URL.Path = "/httpbin" + req.URL.Path
req.Header.Set("Host", "nghttp2.org") // <--- I set it here first
},
}
log.Fatal(http.ListenAndServe(":8080", proxy))
}

func rt(req *http.Request) (*http.Response, error) {
log.Printf("request received. url=%s", req.URL)
req.Header.Set("Host", "nghttp2.org") // <--- I set it here as well
defer log.Printf("request complete. url=%s", req.URL)

return http.DefaultTransport.RoundTrip(req)
}


// roundTripper makes func signature a http.RoundTripper
type roundTripper func(*http.Request) (*http.Response, error)
func (f roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return f(req) }

当我查询 curl localhost:8080/get 时,请求被代理到 https://nghttp2.org/httpbin/get .回显的响应清楚地表明我的指令设置 Host header 没有做任何事情:

{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "localhost:8080",
"User-Agent": "curl/7.54.0"
},
"origin": "2601:602:9c02:16c2:fca3:aaab:3914:4a71",
"url": "https://localhost:8080/httpbin/get"
}

mitmproxy snooping 也清楚地表明请求是使用 :authority 伪 header 设置为 localhost:8080 发出的: mitmproxy output shows :authority pseudoheader set to localhost:8080

最佳答案

来自 http.Request docs :

        // For server requests, Host specifies the host on which the URL
// is sought. Per RFC 7230, section 5.4, this is either the value
// of the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port". For international domain
// names, Host may be in Punycode or Unicode form. Use
// golang.org/x/net/idna to convert it to either format if
// needed.
// To prevent DNS rebinding attacks, server Handlers should
// validate that the Host header has a value for which the
// Handler considers itself authoritative. The included
// ServeMux supports patterns registered to particular host
// names and thus protects its registered Handlers.
//
// For client requests, Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host. Host may contain an international
// domain name.
Host string

因此 URL.Host 的值仅在 request.Host 为空的情况下使用,但事实并非如此。设置 request.Host 应该可以解决问题:

req.Host = "nghttp2.org"

相关问题讨论here .

关于Go httputil.ReverseProxy 不覆盖 Host header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55426924/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com