How to do proxy and TLS in golang

一笑奈何 提交于 2021-02-10 14:43:41

问题


I am trying to route my requests through a proxy and also sending cert.pem in TLS config. Below code is throwing this error - proxyconnect tcp: tls: first record does not look like a TLS handshake. When I change the proxy URL from https to HTTP, the same code works. However proxy URL with https works in python. Below is my code so far

certs := x509.NewCertPool()
pemFile, err := ioutil.ReadFile("cert.pem")
if err != nil {
    return
}
certs.AppendCertsFromPEM(pemFile)
tlsConfig := &tls.Config{
    RootCAs: certs,
}

proxyUrl, err := url.Parse("https://someproxyurlhere.com:8080")
if err != nil {
    return
}

t := &http.Transport{
    TLSClientConfig: tlsConfig,
    Proxy:           http.ProxyURL(proxyUrl),
}

client := http.Client{
    Transport: t,
}

reqBody := "some JSON body here"

buff, err := json.Marshal(reqBody)
if err != nil {
    return
}

req, err := http.NewRequest(http.MethodPost, "https://someurlhere.com", bytes.NewBuffer(buff))
if err != nil {
    return
}

res, err := client.Do(req)
if err != nil {
    // Error here - proxyconnect tcp: tls: first record does not look like a TLS handshake
    return
}
defer res.Body.Close()

Python code

import requests
os.environ['HTTPS_PROXY'] = 'https://someproxyurlhere.com:8080'
response = requests.post("https://someurlhere.com",
                           json={'key': 'value'},
                           verify='cert.pem')
print(str(response.content))

回答1:


When I change the proxy URL from https to HTTP, the same code works.

This is because you are using a HTTP proxy which need to be accessed by HTTP and not HTTPS even for https://.. URLs. This is how HTTPS proxying usually works. Note that while in theory a proxy could sniff if it gets a plain or a TLS connection in practice proxies (and servers) use different ports for HTTP and HTTPS - thus if it works on one port with HTTP it will very likely not work on the same port with HTTPS.

proxyconnect tcp: tls: first record does not look like a TLS handshake.

This is because the proxy answers with an plain HTTP error to the strange HTTP request (which is actually the start of the TLS handshake).

However proxy URL with https works in python.

While it looks that it works it actually doesn't. Python requests will still use plain HTTP to the proxy even if https:// was given as URL.

You can try to do a simple TLS connection to the proxy itself, for example with Python or with openssl s_client. It will very likely fail with some handshake error because the proxy isn't actually expecting TLS.



来源:https://stackoverflow.com/questions/61401128/how-to-do-proxy-and-tls-in-golang

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!