由淺入深寫代理(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 的小站

推薦閱讀:

動態埠轉發:安裝帶有 SSH 的 SOCKS 伺服器
由淺入深寫代理(10)-內網穿透

TAG:socks代理 | Python | 计算机网络 |