Python3通过Socket代理发GET请求报400错误,求可行请求格式
解决通过HTTP代理用Socket发送GET请求返回400 Bad Request的问题
你遇到的400错误核心原因是使用HTTP代理访问HTTPS站点时,请求格式完全不符合规范。HTTP代理处理HTTPS请求需要先建立CONNECT隧道,而不是直接发送完整的HTTPS GET请求;即便是访问HTTP站点,GET请求的路径也不能用完整URL,而是要配合Host头使用相对路径。
下面分两种场景给出正确的实现方案:
场景1:通过HTTP代理访问HTTPS站点(比如icanhazip.com)
因为目标站点是HTTPS协议(默认443端口),你需要先通过代理建立加密隧道,再完成SSL握手,最后发送HTTPS请求:
import socket import ssl # 代理服务器信息 proxy_host = "xx.xx.xx.xx" proxy_port = 80 # 目标站点信息 target_host = "icanhazip.com" target_port = 443 # 1. 先连接到HTTP代理 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((proxy_host, proxy_port)) # 2. 发送CONNECT请求,让代理帮忙建立到目标站点的隧道 connect_request = f"CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nConnection: close\r\n\r\n" s.sendall(connect_request.encode("utf-8")) # 3. 验证隧道是否建立成功 response = s.recv(4096) if b"200 Connection Established" not in response: print(f"隧道建立失败,代理响应:{response.decode('utf-8')}") s.close() exit() # 4. 在已建立的隧道上进行SSL握手,创建加密连接 ssl_sock = ssl.wrap_socket(s, server_hostname=target_host) # 5. 发送标准的HTTPS GET请求(此时路径用相对路径/即可) get_request = f"GET / HTTP/1.1\r\nHost: {target_host}\r\nConnection: close\r\n\r\n" ssl_sock.sendall(get_request.encode("utf-8")) # 6. 接收并打印响应内容 res = ssl_sock.recv(10000) while len(res) > 0: print(res.decode("utf-8")) res = ssl_sock.recv(10000) # 关闭连接 ssl_sock.close()
场景2:通过HTTP代理访问HTTP站点
如果目标是普通HTTP站点(比如http://example.com),不需要建立隧道,直接发送带Host头的相对路径请求即可:
import socket proxy_host = "xx.xx.xx.xx" proxy_port = 80 target_host = "example.com" s = socket.socket() s.connect((proxy_host, proxy_port)) # 正确的请求格式:GET + 相对路径 + 协议版本,加上Host头,最后用空行结束请求 get_request = f"GET / HTTP/1.1\r\nHost: {target_host}\r\nConnection: close\r\n\r\n" s.sendall(get_request.encode("utf-8")) # 接收并打印响应 res = s.recv(10000) while len(res) > 0: print(res.decode("utf-8")) res = s.recv(10000) s.close()
原代码报错的根本原因
你的原代码直接发送了GET https://icanhazip.com HTTP/1.0\r\n,这完全不符合HTTP代理的请求规则:
- 对于HTTP代理处理HTTP请求的场景,GET的参数应该是目标URL的路径部分(比如
/),必须通过Host头告诉代理目标主机是谁。 - 对于HTTPS请求,必须先通过
CONNECT请求让代理建立到目标服务器443端口的隧道,之后才能在隧道内进行HTTPS加密通信。
内容的提问来源于stack exchange,提问作者Hasyar
相关产品推荐
相关产品推荐

