在 python 中加密到我的 HTTP 代理的连接
Encrypting connection to my HTTP Proxy in python
基本上,我正在尝试使用 python 中的套接字设置加密代理。目前我可以通过从客户端向代理服务器发送 HTTP CONNECT 并接收 'CODE 200 OK' 来建立连接
回复。代理服务器充当从客户端到所需 domain/Ip 的隧道并且工作得很好。
问题是:如何加密整个连接?第一个 HTTP 连接未加密,可以轻松嗅探和查看。
服务器代码如下:
import socket, threading
MAX_BUFFER = 64 * 512
class ClientThread(threading.Thread):
def __init__(self, clientAddress, clientsocket):
threading.Thread.__init__(self)
self.browser = clientsocket
def run(self):
while True:
request = self.browser.recv(MAX_BUFFER)
# parse the first line
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
webserver, port = self.get_domain_port(request)
if 'CONNECT' in request:
# Connect to port 443
print request
try:
# If successful, send 200 code response
client.connect(( webserver, port ))
reply = "HTTP/1.0 200 Connection established\r\n"
reply += "Proxy-agent: FIMA\r\n"
reply += "\r\n"
self.browser.sendall( reply.encode() )
except socket.error as err:
# If the connection could not be established, exit
# Should properly handle the exit with http error code here
break
# Indiscriminately forward bytes
self.browser.setblocking(0)
client.setblocking(0)
while True:
try:
request = self.browser.recv(MAX_BUFFER)
client.sendall( request )
except socket.error as err:
pass
try:
reply = client.recv(MAX_BUFFER)
self.browser.sendall( reply )
except socket.error as err:
pass
print ("Client at ", self.ssl_browser , " disconnected...")
def get_domain_port(self, request):
first_line = request.split('\n')[0]
# get url
url = first_line.split(' ')[1]
http_pos = url.find("://") # find pos of ://
if (http_pos==-1):
temp = url
else:
temp = url[(http_pos+3):] # get the rest of url
port_pos = temp.find(":") # find the port pos (if any)
# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if (port_pos==-1 or webserver_pos < port_pos):
# default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
webserver = temp[:port_pos]
return webserver, port
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('192.168.1.107', 80))
sock.listen(5)
while True:
conn, addr = sock.accept()
newthread = ClientThread(addr, conn)
newthread.daemon = True
newthread.start()
sock.shutdown(socket.SHUT_RDWR)
sock.close()
if __name__ == "__main__":
main()
通常的方法是使用 HTTP 代理并使用普通的 CONNECT 方法创建隧道。然后,此隧道用于客户端和服务器之间的端到端加密 HTTPS。
虽然也可以加密客户端和代理之间的连接,但对于 HTTPS 隧道,这会在客户端和服务器之间的加密之上导致客户端和代理之间的加密。为此,您需要创建的不是普通套接字,而是带有证书等的 SSL 套接字 - 有关如何执行此操作的 lots of documentation and examples。
请注意,此设置并未得到普遍支持。某些浏览器(如 Firefox)支持此功能,而其他浏览器则不支持。非浏览器客户端通常不支持这样的设置。
基本上,我正在尝试使用 python 中的套接字设置加密代理。目前我可以通过从客户端向代理服务器发送 HTTP CONNECT 并接收 'CODE 200 OK' 来建立连接 回复。代理服务器充当从客户端到所需 domain/Ip 的隧道并且工作得很好。
问题是:如何加密整个连接?第一个 HTTP 连接未加密,可以轻松嗅探和查看。
服务器代码如下:
import socket, threading
MAX_BUFFER = 64 * 512
class ClientThread(threading.Thread):
def __init__(self, clientAddress, clientsocket):
threading.Thread.__init__(self)
self.browser = clientsocket
def run(self):
while True:
request = self.browser.recv(MAX_BUFFER)
# parse the first line
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
webserver, port = self.get_domain_port(request)
if 'CONNECT' in request:
# Connect to port 443
print request
try:
# If successful, send 200 code response
client.connect(( webserver, port ))
reply = "HTTP/1.0 200 Connection established\r\n"
reply += "Proxy-agent: FIMA\r\n"
reply += "\r\n"
self.browser.sendall( reply.encode() )
except socket.error as err:
# If the connection could not be established, exit
# Should properly handle the exit with http error code here
break
# Indiscriminately forward bytes
self.browser.setblocking(0)
client.setblocking(0)
while True:
try:
request = self.browser.recv(MAX_BUFFER)
client.sendall( request )
except socket.error as err:
pass
try:
reply = client.recv(MAX_BUFFER)
self.browser.sendall( reply )
except socket.error as err:
pass
print ("Client at ", self.ssl_browser , " disconnected...")
def get_domain_port(self, request):
first_line = request.split('\n')[0]
# get url
url = first_line.split(' ')[1]
http_pos = url.find("://") # find pos of ://
if (http_pos==-1):
temp = url
else:
temp = url[(http_pos+3):] # get the rest of url
port_pos = temp.find(":") # find the port pos (if any)
# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if (port_pos==-1 or webserver_pos < port_pos):
# default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
webserver = temp[:port_pos]
return webserver, port
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('192.168.1.107', 80))
sock.listen(5)
while True:
conn, addr = sock.accept()
newthread = ClientThread(addr, conn)
newthread.daemon = True
newthread.start()
sock.shutdown(socket.SHUT_RDWR)
sock.close()
if __name__ == "__main__":
main()
通常的方法是使用 HTTP 代理并使用普通的 CONNECT 方法创建隧道。然后,此隧道用于客户端和服务器之间的端到端加密 HTTPS。
虽然也可以加密客户端和代理之间的连接,但对于 HTTPS 隧道,这会在客户端和服务器之间的加密之上导致客户端和代理之间的加密。为此,您需要创建的不是普通套接字,而是带有证书等的 SSL 套接字 - 有关如何执行此操作的 lots of documentation and examples。
请注意,此设置并未得到普遍支持。某些浏览器(如 Firefox)支持此功能,而其他浏览器则不支持。非浏览器客户端通常不支持这样的设置。