Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPS through proxy completely encrypted, including SSL CONNECT

I am trying to test a proxy that is expecting an SSL handshake immediately, even if the client is going to use an SSL CONNECT method. The problem is that my Golang and Python test code both seem to have the same flaw. They connect to the proxy in the clear, and then issue a CONNECT, but the proxy rejects this because it is expecting an SSL handshake.

Does anyone know how to force either technology to use SSL to the proxy using available standard libraries?

Thanks.

Sample code follows:

#!/usr/bin/python

try:
    import urllib2

    proxy = urllib2.ProxyHandler({'https': "myproxyip:6881"})
    opener = urllib2.build_opener(proxy)
    urllib2.install_opener(opener)
    print urllib2.urlopen('https://www.google.ca').read()

except Exception as err:
    print err


try:
    import httplib

    c = httplib.HTTPSConnection('myproxyip', 6881)
    c.set_tunnel('google.ca', 443)
    c.request('GET', '/')
    res = c.getresponse()
    print res.status, res.reason

except Exception as err:
    print err

and golang

// vim: ft=go ts=4 sw=4 et ai:
package main

import (
    "net/http"
    "log"
    "io/ioutil"
    "time"
    "crypto/tls"
    "net/url"
    )

var use_proxy = true
var proxy = "https://myproxyip:6881"
var req_url = "https://google.ca"
var n_seconds time.Duration = 15
var period = time.Second * n_seconds
var n_threads = 50
var thread_start_delay time.Duration = 1

func http_fetch(req_url string) {
    tr := http.Transport {
        TLSClientConfig: &tls.Config {
            InsecureSkipVerify: true,
        },
    }
    proxy_url, err := url.Parse(proxy)
    if err != nil {
        log.Fatal(err)
    }
    if use_proxy {
        tr.Proxy = http.ProxyURL(proxy_url)
    }
    client := &http.Client{}
    client.Transport = &tr

    req, err := http.NewRequest("GET", req_url, nil)
    if err != nil {
        log.Fatal(err)
    }
    req.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")

    res, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    body, err := ioutil.ReadAll(res.Body)
    defer res.Body.Close()
    document := string(body)
    print(document)
}


func main() {
    println("main: Starting", n_threads, "threads to hammer", req_url, "every", n_seconds, "seconds, ctrl-c to quit...")
    done := make(<-chan bool)
    for i:= 0; i < n_threads; i++ {
        go func(thread_id int) {
            println("thread", thread_id, ": starting periodic_hammer")
            for {
                println("thread", thread_id, ": fetching", req_url)
                http_fetch(req_url)
                println("thread", thread_id, ": done, sleeping for", n_seconds, "seconds")
                time.Sleep(period)
            }
        }(i+1)
        println("main: delaying", thread_start_delay, "seconds before starting next thread")
        time.Sleep(thread_start_delay * time.Second)
    }
    <-done
}
like image 957
Michael Soulier Avatar asked Jul 11 '17 14:07

Michael Soulier


1 Answers

Using https proxies is only supported starting with Go 1.10. From the draft release notes:

On the client side, an HTTP proxy (most commonly configured by ProxyFromEnvironment) can now be specified as an https:// URL, meaning that the client connects to the proxy over HTTPS before issuing a standard, proxied HTTP request. (Previously, HTTP proxy URLs were required to begin with http:// or socks5://.)

like image 188
jch Avatar answered Sep 29 '22 13:09

jch