使用ssl模块的HTTPS代理隧道 [英] HTTPS proxy tunneling with the ssl module

查看:218
本文介绍了使用ssl模块的HTTPS代理隧道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想手动(使用 socket

I'd like to manually (using the socket and ssl modules) make an HTTPS request through a proxy which itself uses HTTPS.

我可以很好地执行初始CONNECT交换:

I can perform the initial CONNECT exchange just fine:

import ssl, socket

PROXY_ADDR = ("proxy-addr", 443)
CONNECT = "CONNECT example.com:443 HTTP/1.1\r\n\r\n"

sock = socket.create_connection(PROXY_ADDR)
sock = ssl.wrap_socket(sock)
sock.sendall(CONNECT)
s = ""
while s[-4:] != "\r\n\r\n":
    s += sock.recv(1)
print repr(s)

上面的代码显示了HTTP/1.1 200 Connection established以及一些标题,这是我期望的.所以现在我应该准备好发出请求了,例如

The above code prints HTTP/1.1 200 Connection established plus some headers, which is what I expect. So now I should be ready to make the request, e.g.

sock.sendall("GET / HTTP/1.1\r\n\r\n")

但上面的代码返回

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
</body></html>

这也很有意义,因为我仍然需要与隧道连接到的example.com服务器进行SSL握手.但是,如果不是立即发送GET请求,我会说

This makes sense too, since I still need to do an SSL handshake with the example.com server to which I'm tunneling. However, if instead of immediately sending the GET request I say

sock = ssl.wrap_socket(sock)

与远程服务器进行握手,然后出现异常:

to do the handshake with the remote server, then I get an exception:

Traceback (most recent call last):
  File "so_test.py", line 18, in <module>
    ssl.wrap_socket(sock)
  File "/usr/lib/python2.6/ssl.py", line 350, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "/usr/lib/python2.6/ssl.py", line 118, in __init__
    self.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 293, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:480: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol

那么我该如何与远程example.com服务器进行SSL握手?

So how can I do the SSL handshake with the remote example.com server?

我很确定在我第二次调用wrap_socket之前没有可用的附加数据,因为调用sock.recv(1)会无限期地阻塞.

I'm pretty sure that no additional data is available before my second call to wrap_socket because calling sock.recv(1) blocks indefinitely.

推荐答案

如果按如下所示重写CONNECT字符串,则此方法应该起作用:

This should work if the CONNECT string is rewritten as follows:

CONNECT = "CONNECT %s:%s HTTP/1.0\r\nConnection: close\r\n\r\n" % (server, port)

不确定为什么会起作用,但可能与我使用的代理有关.这是一个示例代码:

Not sure why this works, but maybe it has something to do with the proxy I'm using. Here's an example code:

from OpenSSL import SSL
import socket

def verify_cb(conn, cert, errun, depth, ok):
        return True

server = 'mail.google.com'
port = 443
PROXY_ADDR = ("proxy.example.com", 3128)
CONNECT = "CONNECT %s:%s HTTP/1.0\r\nConnection: close\r\n\r\n" % (server, port)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(PROXY_ADDR)
s.send(CONNECT)
print s.recv(4096)      

ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_verify(SSL.VERIFY_PEER, verify_cb)
ss = SSL.Connection(ctx, s)

ss.set_connect_state()
ss.do_handshake()
cert = ss.get_peer_certificate()
print cert.get_subject()
ss.shutdown()
ss.close()

请注意如何首先打开套接字,然后再打开放置在SSL上下文中的套接字.然后,我手动初始化SSL握手.并输出:

Note how the socket is first opened and then open socket placed in SSL context. Then I manually initialize SSL handshake. And output:

HTTP/1.1 200连接已建立

HTTP/1.1 200 Connection established

< X509Name对象'/C = US/ST = California/L = Mountain View/O = Google Inc/CN = mail.google.com'>

<X509Name object '/C=US/ST=California/L=Mountain View/O=Google Inc/CN=mail.google.com'>

它基于pyOpenSSL,因为我也需要获取无效的证书,并且Python内置的ssl模块将始终尝试验证证书是否被接收.

It's based on pyOpenSSL because I needed to fetch invalid certificates too and Python built-in ssl module will always try to verify the certificate if it's received.

这篇关于使用ssl模块的HTTPS代理隧道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆