返回介绍

https 代理

发布于 2024-09-21 14:54:08 字数 3356 浏览 0 评论 0 收藏 0

本文主要实现隧道代理,让 https 请求也能代理。

隧道代理的原理是: HTTP 客户端通过 CONNECT 方法请求隧道代理创建一条到达任意目的服务器和端口的 TCP 连接,并对客户端和服务器之间的后继数据进行盲转发。

步骤如下

  1. 客户端发送一个 http CONNECT 请求
    CONNECT baidu.com:443 HTTP/1.1
  2. 代理收到这样的请求后,拿到目标服务器域名及端口,与目标服务端建立 TCP 连接,并响应给浏览器这样一个 HTTP 报文:
    HTTP/1.1 200 Connection Established
  3. 建立完隧道以后,客户端与目标服务器照之前的方式发送请求,代理节点只是做转发功能,无从知道转发的流量具体是什么

看代码

import socket
import select
from http.server import BaseHTTPRequestHandler, HTTPServer


class ProxyHandler(BaseHTTPRequestHandler):

def send_data(self, sock, data):
print(data)
bytes_sent = 0
while True:
r = sock.send(data[bytes_sent:])
if r < 0:
return r
bytes_sent += r
if bytes_sent == len(data):
return bytes_sent

def handle_tcp(self, sock, remote):
# 处理 client socket 和 remote socket 的数据流
try:
fdset = [sock, remote]
while True:
# 用 IO 多路复用 select 监听套接字是否有数据流
r, w, e = select.select(fdset, [], [])
if sock in r:
data = sock.recv(4096)
if len(data) <= 0:
break
result = self.send_data(remote, data)
if result < len(data):
raise Exception('failed to send all data')

if remote in r:
data = remote.recv(4096)
if len(data) <= 0:
break
result = self.send_data(sock, data)
if result < len(data):
raise Exception('failed to send all data')
except Exception as e:
raise(e)
finally:
sock.close()
remote.close()

def do_CONNECT(self):

# 解析出 host 和 port
uri = self.path.split(":")
host, port = uri[0], int(uri[1])
host_ip = socket.gethostbyname(host)

remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_sock.connect((host_ip, port))
# 告诉客户端 CONNECT 成功
self.wfile.write("{protocol_version} 200 Connection Established\r\n\r\n".format(protocol_version=self.protocol_version).encode())

# 转发请求
self.handle_tcp(self.connection, remote_sock)


def main():
try:
server = HTTPServer(('', 8888), ProxyHandler)
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()


if __name__ == '__main__':
main()

有一个 do_CONNECT 函数的处理,实现之前隧道的建立,然后 handle_tcp ,代码和之前 socks5 代理是一样的。

参考链接:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文