我试图在python中创建HTTPS代理服务器,我创建了以下适用于HTTP的脚本。
#!/usr/bin/env python3
# coding=utf-8
import socket
from threading import Thread
class Proxy:
def __init__(self, port=3000):
self.port = port
self.proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.proxy.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.buffer_size = 4096
def run(self):
self.proxy.bind(("0.0.0.0", self.port))
self.proxy.listen(100)
print(" * Proxy server is running on port {}".format(self.port))
while True:
client, addr = self.proxy.accept()
print(" => {}:{}".format(addr[0], addr[1]))
Thread(target=self.handle_request, args=(client,)).start()
def handle_request(self, client):
head = self.parse_head(client.recv(self.buffer_size))
headers = head["headers"]
request = "{}\r\n".format(head["meta"])
for key, value in headers.items():
request += "{}: {}\r\n".format(key, value)
request += "\r\n"
if "content-length" in headers:
while len(head["chunk"]) < int(headers["content-length"]):
head["chunk"] += client.recv(self.buffer_size)
request = request.encode() + head["chunk"]
port = 80
try:
tmp = head["meta"].split(" ")[1].split("://")[1].split("/")[0]
except IndexError:
client.close()
return
if tmp.find(":") > -1:
port = int(tmp.split(":")[1])
response = self.send_to_server(headers["host"], port, request)
client.sendall(response)
client.close()
def send_to_server(self, host, port, data):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect((socket.gethostbyname(host), port))
server.sendall(data)
head = self.parse_head(server.recv(4096))
headers = head["headers"]
response = "{}\r\n".format(head["meta"])
for key, value in headers.items():
response += "{}: {}\r\n".format(key, value)
response += "\r\n"
if "content-length" in headers:
while len(head["chunk"]) < int(headers["content-length"]):
head["chunk"] += server.recv(self.buffer_size)
response = response.encode() + head["chunk"]
server.close()
return response
def parse_head(self, head_request):
nodes = head_request.split(b"\r\n\r\n")
heads = nodes[0].split(b"\r\n")
meta = heads.pop(0).decode("utf-8")
data = {
"meta": meta,
"headers": {},
"chunk": b""
}
if len(nodes) >= 2:
data["chunk"] = nodes[1]
for head in heads:
pieces = head.split(b": ")
key = pieces.pop(0).decode("utf-8")
if key.startswith("Connection: "):
data["headers"][key.lower()] = "close"
else:
data["headers"][key.lower()] = b": ".join(pieces).decode("utf-8")
return data
if __name__ == "__main__":
proxy = Proxy(3001)
proxy.run()
我从未在Python中使用过SSL内容,因此我使用了ssl
模块来创建HTTPS套接字。
#!/usr/bin/env python3
# coding=utf-8
import socket
import ssl
from threading import Thread
class Proxy:
def __init__(self, port=3000):
self.port = port
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.proxy = ssl.wrap_socket(self.s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers="ADH-AES256-SHA")
self.buffer_size = 4096
def run(self):
self.proxy.bind(("0.0.0.0", self.port))
self.proxy.listen(100)
print(" * Proxy server is running on port {}".format(self.port))
while True:
client, addr = self.proxy.accept()
print(" => {}:{}".format(addr[0], addr[1]))
Thread(target=self.handle_request, args=(client,)).start()
def handle_request(self, client):
head = self.parse_head(client.recv(self.buffer_size))
headers = head["headers"]
request = "{}\r\n".format(head["meta"])
for key, value in headers.items():
request += "{}: {}\r\n".format(key, value)
request += "\r\n"
if "content-length" in headers:
while len(head["chunk"]) < int(headers["content-length"]):
head["chunk"] += client.recv(self.buffer_size)
request = request.encode() + head["chunk"]
port = 80
try:
tmp = head["meta"].split(" ")[1].split("://")[1].split("/")[0]
except IndexError:
client.close()
return
if tmp.find(":") > -1:
port = int(tmp.split(":")[1])
response = self.send_to_server(headers["host"], port, request)
client.sendall(response)
client.close()
def send_to_server(self, host, port, data):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect((socket.gethostbyname(host), port))
server.sendall(data)
head = self.parse_head(server.recv(4096))
headers = head["headers"]
response = "{}\r\n".format(head["meta"])
for key, value in headers.items():
response += "{}: {}\r\n".format(key, value)
response += "\r\n"
if "content-length" in headers:
while len(head["chunk"]) < int(headers["content-length"]):
head["chunk"] += server.recv(self.buffer_size)
response = response.encode() + head["chunk"]
server.close()
return response
def parse_head(self, head_request):
nodes = head_request.split(b"\r\n\r\n")
heads = nodes[0].split(b"\r\n")
meta = heads.pop(0).decode("utf-8")
data = {
"meta": meta,
"headers": {},
"chunk": b""
}
if len(nodes) >= 2:
data["chunk"] = nodes[1]
for head in heads:
pieces = head.split(b": ")
key = pieces.pop(0).decode("utf-8")
if key.startswith("Connection: "):
data["headers"][key.lower()] = "close"
else:
data["headers"][key.lower()] = b": ".join(pieces).decode("utf-8")
return data
if __name__ == "__main__":
proxy = Proxy(3001)
proxy.run()
但是出现以下错误。
* Proxy server is running on port 3001
Traceback (most recent call last):
File ".\proxy.py", line 98, in <module>
proxy.run()
File ".\proxy.py", line 22, in run
client, addr = self.proxy.accept()
File "C:\Users\anyms\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 1355, in accept
newsock = self.context.wrap_socket(newsock,
File "C:\Users\anyms\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "C:\Users\anyms\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 1040, in _create
self.do_handshake()
File "C:\Users\anyms\AppData\Local\Programs\Python\Python38-32\lib\ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: HTTPS_PROXY_REQUEST] https proxy request (_ssl.c:1108)
答案 0 :(得分:1)
该问题实际上与SSL根本无关,而是由对HTTPS的HTTP代理的工作原理的误解引起的。这样的代理完全不执行SSL。相反,它仅用于创建通往最终服务器的隧道,然后客户端通过该隧道创建HTTPS连接,以这种方式保持端到端加密。
使用HTTP CONNECT method创建隧道本身。这正是您通过SSL套接字获取的信息:
ssl.SSLError: [SSL: HTTPS_PROXY_REQUEST] https proxy request (_ssl.c:1108)
^^^^^^^^^^^^^^^^^^^