由淺入深寫代理(7)-https-代理
本文主要實現隧道代理,讓 https 請求也能代理。
隧道代理的原理是:
HTTP 客戶端通過 CONNECT 方法請求隧道代理創建一條到達任意目的伺服器和埠的 TCP 連接,並對客戶端和伺服器之間的後繼數據進行盲轉發。
步驟如下
1. 客戶端發送一個 http CONNECT 請求
CONNECT baidu.com:443 HTTP/1.1n
2. 代理收到這樣的請求後,拿到目標伺服器域名及埠,與目標服務端建立 TCP 連接,並響應給瀏覽器這樣一個 HTTP 報文:
HTTP/1.1 200 Connection Establishedn
3. 建立完隧道以後,客戶端與目標伺服器照之前的方式發送請求,代理節點只是做轉發功能,無從知道轉發的流量具體是什麼
看代碼
import socketnimport selectnfrom http.server import BaseHTTPRequestHandler, HTTPServernnclass ProxyHandler(BaseHTTPRequestHandler):nn def send_data(self, sock, data):n print(data)n bytes_sent = 0n while True:n r = sock.send(data[bytes_sent:])n if r < 0:n return rn bytes_sent += rn if bytes_sent == len(data):n return bytes_sentnn def handle_tcp(self, sock, remote):n # 處理 client socket 和 remote socket 的數據流n try:n fdset = [sock, remote]n while True:n # 用 IO 多路復用 select 監聽套接字是否有數據流n r, w, e = select.select(fdset, [], [])n if sock in r:n data = sock.recv(4096)n if len(data) <= 0:n breakn result = self.send_data(remote, data)n if result < len(data):n raise Exception(failed to send all data)nn if remote in r:n data = remote.recv(4096)n if len(data) <= 0:n breakn result = self.send_data(sock, data)n if result < len(data):n raise Exception(failed to send all data)n except Exception as e:n raise(e)n finally:n sock.close()n remote.close()nn def do_CONNECT(self):nn # 解析出 host 和 portn uri = self.path.split(":")n host, port = uri[0], int(uri[1])n host_ip = socket.gethostbyname(host)nn remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)n remote_sock.connect((host_ip, port))n # 告訴客戶端 CONNECT 成功n self.wfile.write("{protocol_version} 200 Connection Establishedrnrn".format(protocol_version=self.protocol_version).encode())nn # 轉發請求n self.handle_tcp(self.connection, remote_sock)nndef main():n try:n server = HTTPServer((, 8888), ProxyHandler)n server.serve_forever()n except KeyboardInterrupt:n server.socket.close()nnif __name__ == __main__:n main()n
有一個 do_CONNECT 函數的處理,實現之前隧道的建立,然後 handle_tcp,代碼和之前 socks5 代理是一樣的。
github 地址: https_server.py
參考鏈接:
* HTTP 代理原理及實現(一) | JerryQu 的小站
推薦閱讀: