HTTPS通过代理完全加密,包括SSL CONNECT

时间:2017-07-11 14:25:23

标签: python ssl go https proxy

我正在尝试立即测试期望SSL握手的代理,即使客户端将使用SSL CONNECT方法。问题是我的Golang和Python测试代码似乎都有相同的缺陷。它们以明文形式连接到代理,然后发出CONNECT,但代理拒绝这一点,因为它期待SSL握手。

有没有人知道如何使用可用的标准库强制任何一种技术将SSL用于代理?

感谢。

示例代码如下:

#!/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

和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
}

3 个答案:

答案 0 :(得分:0)

除了您拥有的ProxyHandler之外,还可以使用Python标准库来解决此问题:

import ssl, urllib2

# Set ciphers and ssl settings
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.set_ciphers('HIGH:!DH:!aNULL')

# Set proxy settings
proxy = urllib2.ProxyHandler({'https':'<https proxy host>:443', 'http':'<http proxy host>:8080'})
opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx), proxy)
urllib2.install_opener(opener)

答案 1 :(得分:0)

最后,我必须做自己的客户,基本上。

func http_fetch(req_host string) {
    buf := make([]byte, 1024)
    conf := &tls.Config {
        InsecureSkipVerify: true,
    }   

    conn, err := tls.Dial("tcp", proxy_host, conf)
    if err != nil {
        //panic(err)
        failure()
        return
    }   
    defer conn.Close()

    // SSL CONNECT
    if _, err = conn.Write([]byte("CONNECT " + req_host + " HTTP/1.0\r\n\r\n")); err != nil {
        // FIXME: need debug logger?
        //panic(err)
        failure()
        return
    }   

    // Read response
    if _, err = conn.Read(buf); err != nil {
        //panic(err)
        failure()
        return
    }   

    // Send http GET
    if _, err = conn.Write([]byte("GET / HTTP/1.0\r\n")); err != nil {
        //panic(err)
        failure()
        return
    }   
    if _, err = conn.Write([]byte("User-Agent: golang\r\n\r\n")); err != nil {
        //panic(err)
        failure()
        return
    }   

    // Read response
    if _, err = conn.Read(buf); err != nil {
        //panic(err)
        failure()
        return
    }   
    success()
}   

答案 2 :(得分:0)

仅从Go 1.10开始支持使用https代理。来自draft release notes

  

在客户端,HTTP代理(最常见的配置)   ProxyFromEnvironment现在可以指定为https:// URL,意思是   客户端在发出之前通过HTTPS连接到代理   标准的,代理的HTTP请求。 (以前,HTTP代理URL是   需要以http://或socks5://开始。)