如何使用代理进行 HTTPS 请求

huangapple go评论107阅读模式
英文:

How to do a https request with proxy

问题

我可以在不设置代理的情况下进行HTTP或HTTPS客户端请求。

tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

client := &http.Client{}
client.Transport = tr

request, err := http.NewRequest("HEAD", "http://www.???.com", nil)
request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")

resp, err := client.Do(request)

if err != nil {
    log.Fatalln(err)
    return
}
defer resp.Body.Close()

httpcode = resp.Status

这个脚本可以正常工作,当我请求HTTPS URL时,我会得到一个200 OK的响应。但是,如果我设置代理,脚本就会出现问题:

proxyString := "https://47.91.179.xxx:443"
proxyUrl, _ := url.Parse(proxyString)

tr := &http.Transport{
    Proxy:           http.ProxyURL(proxyUrl),
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

client := &http.Client{}
client.Transport = tr

// ...

我总是得到"Bad request"的响应。我阅读了文档:https://golang.org/pkg/net/http/:

从Go 1.6开始,当使用HTTPS时,http包对HTTP/2协议有透明的支持。必须禁用HTTP/2的程序可以通过将Transport.TLSNextProto(对于客户端)或Server.TLSNextProto(对于服务器)设置为非nil的空映射来实现。另外,目前支持以下GODEBUG环境变量:

因此,我尝试停止使用HTTP/2:

tr := &http.Transport{
    Proxy:           http.ProxyURL(proxyUrl),
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    TLSNextProto:    make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
}

仍然存在相同的问题,即"Bad request"。我尝试使用os.Setenv("HTTPS_PROXY", "47.91.???.???:443"),结果也是一样的。服务器日志中记录的是:

{S;}220.255.95.68{S;}-{S;}07/Mar/2017:17:01:47 +0800{S;}CONNECT www.panpacific.com:443 HTTP/1.1{S;}400{S;}173{S;}340{S;}-{S;}-{S;}-{S;}-{S;}-{S;}www.panpacific.com

那么,Golang是否支持通过代理进行HTTPS客户端请求?我该如何获得正确的结果?

英文:

I am able to do a http or https client request without setting up a proxy,

enter code here
tr := &http.Transport{
	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},		
}

client := &http.Client{}
client.Transport = tr

request, err := http.NewRequest("HEAD", "http://www.???.com", nil)
request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")

resp, err := client.Do(request)

if err != nil {
	log.Fatalln(err)
	return
}
defer resp.Body.Close()

httpcode = resp.Status

This script is working ok, I get a 200 ok when I request https url, but if I set up proxy , the script:

proxyString := "https://47.91.179.xxx:443"
proxyUrl, _ := url.Parse(proxyString)

tr := &http.Transport{
    Proxy: http.ProxyURL(proxyUrl),
	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},	
    
}

client := &http.Client{}
client.Transport = tr

....................

I always get "Bad request", I read docs: https://golang.org/pkg/net/http/:

...........
Starting with Go 1.6, the http package has transparent support for the HTTP/2 protocol when using HTTPS. Programs that must disable HTTP/2 can do so by setting Transport.TLSNextProto (for clients) or Server.TLSNextProto (for servers) to a non-nil, empty map. Alternatively, the following GODEBUG environment variables are currently supported:
..............

So, I tried to stop http2:

tr := &http.Transport{
	Proxy: http.ProxyURL(proxyUrl),
	//Proxy: http.ProxyFromEnvironment,
	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	TLSNextProto:    make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
}

same problem, "Bad request". I tried os.Setenv("HTTPS_PROXY", "47.91.???.???:443"), It is the same result.
This is logged in server:

{S;}220.255.95.68{S;}-{S;}07/Mar/2017:17:01:47 +0800{S;}CONNECT www.panpacific.com:443 HTTP/1.1{S;}400{S;}173{S;}340{S;}-{S;}-{S;}-{S;}-{S;}-{S;}www.panpacific.com

So, Does golang support https client request via proxy? How do I get correct results?

答案1

得分: 1

你的Client.Transport.Proxy配置看起来没有任何问题。两种尝试的方法(ProxyURLProxyFromEnvironment)都可以正常工作,用于指定正向代理

相关问题:https://stackoverflow.com/q/51845690/86967

需要注意的是,尽管可能性很小,但后续的客户端调用不能绕过WriteProxy的使用,而是直接调用Write -- 因为这将使代理规范失效。


根据提供的信息,“Bad Request”可能表示您已经连接到代理,但它作为通用的HTTP/HTTPS正向代理没有正常工作,这是Client.Transport.Proxy所指定的。也许这里可以增加一些清晰度:如何将Nginx用作HTTP/HTTPS代理服务器?。简而言之,NGINX通常不用作正向代理,所以也许这不是您想要做的事情。

如果您想将NGINX用作反向代理,则配置是服务器端的问题,您的客户端不需要特殊的代理配置--只需将请求URL更改为指向代理即可。


顺便提一下:如果没有另外指定,&http.Client{}将使用DefaultTransport,它自动包含ProxyFromEnvironment,因此只有在构建非默认Transport(如问题中所做的那样,以指定InsecureSkipVerify)或者您想要具有特定于应用程序的代理配置时,才需要额外的代理配置。重申一遍,只有在使用正向代理时才需要客户端的代理配置。

英文:

There doesn't appear to be anything wrong with your Client.Transport.Proxy configuration. Both attempted approaches (ProxyURL and ProxyFromEnvironment) should work fine to specify a forward proxy.

Relevant question: https://stackoverflow.com/q/51845690/86967

Something to look out for, however unlikely, is that subsequent client-side calls to not somehow bypass the use of WriteProxy and instead call Write directly -- since this would defeat the proxy specification.


Given the information provided here, "Bad Request" likely indicates that you are reaching the proxy, but that it is not working correctly as a generic HTTP/HTTPS forward proxy, which is what Client.Transport.Proxy would specify.

Maybe some clarity would be added here: How to use Nginx as a HTTP/HTTPS proxy server?. In summary, NGINX is not normally used as a forward proxy, so maybe this isn't what you are trying to do.

If you are trying to use NGINX as a reverse proxy, then configuration is a server-side concern and your clients do not need special proxy configuration -- just change your request URL to point to the proxy.


Side note: If not otherwise specified, &http.Client{} will use DefaultTransport which automatically includes ProxyFromEnvironment, so the extra proxy configuration is only required if you are constructing a non-default Transport (as is done in the question in order to specify InsecureSkipVerify) or you want to have an application-specific proxy confuration. And, to repeat, client-side proxy configuration is only needed when using a forward proxy.

huangapple
  • 本文由 发表于 2017年3月8日 11:20:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/42662369.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定