HTTP 代理到底怎么工作:一次请求的完整旅程
刚接触代理那会儿,我以为它就是个"转发器"——地址填进去,请求就出去了。直到有次用 HTTP 代理去抓一个 https 站点,怎么都超时,抓包才发现自己压根没搞明白 CONNECT 隧道是怎么回事。这篇就把这一层讲透,后面排错会轻松很多。
代理服务器站在哪个位置
直连时链路是「客户端 → 目标服务器」。挂上代理就变成「客户端 → 代理服务器 → 目标服务器」,目标站看到的来源 IP 是代理的出口 IP,而不是你家宽带的 IP。"换 IP"的全部原理就这么回事。
这里没有魔法:代理只是替你发请求、再把响应原样带回来。它不改你的请求内容,也不负责加密。
转发请求的两种方式
1. 绝对 URL —— 只有 http 这么干
请求行里写的不是路径,而是完整地址:
GET http://example.com/index.html HTTP/1.1
Host: example.com
代理看到这种带主机名的完整地址,就知道该替你去哪台机器取。这也解释了另一个常见问题:自己手写 HTTP 客户端走代理时,path 里要填完整 URL,很多语言的原生库不会帮你补。
2. CONNECT 隧道 —— https 必须走这条路
https 的正文是加密的,代理看不懂、也没必要看懂。客户端先让代理开一条 TCP 通道:
CONNECT example.com:443 HTTP/1.1
Host: example.com:443
代理回一个 200 之后,客户端就在这条通道里直接跟目标站做 TLS 握手。从此代理只负责搬字节,证书校验和加密都是端到端的。所以用 HTTP 代理抓 https 会稍慢一点:多了一次 CONNECT 往返。
如果你是自己写 socket 客户端,忘发 CONNECT 是最容易犯的错——表现是代理直接回 400,或者请求一直挂着不动。
代理怎么确认你有权用它
代理是花钱买的资源,不可能谁都能白用。常见两种认证方式:
| 方式 | 怎么工作 | 适合什么场景 |
|---|---|---|
| IP 白名单 | 把调用方的出口 IP 加进白名单,代理放行 | 云主机上跑定时任务、出口 IP 固定 |
| 账号密码 | 请求头里带 Proxy-Authorization | 本地开发、出口 IP 经常变 |
白名单看着省事,但有个坑:出口 IP 是动态的就麻烦了。家庭宽带重播号会换 IP,部分云厂商的弹性 IP 也会漂。我碰到过好几次"昨天还跑得好好的,今天全员 403",查半天最后都是出口 IP 变了。
至于 407,它是代理层返回的 Proxy Authentication Required,含义非常明确:这条线路要账号密码。如果你是白名单模式却收到 407,说明这条线路跟你的白名单对不上,换一条就行,别去查目标站。
亲手验证一次
用 curl 最直观,参数全摆在明面上:
# 带账号密码,看出口 IP 变了没有
curl -x http://用户名:密码@代理IP:端口 https://httpbin.org/ip
# 白名单模式则不用带账号
curl -x http://代理IP:端口 https://httpbin.org/ip
换到 Python,注意把两件事分开:取 IP 的请求要直连,用 IP 访问目标站时才走代理。
import requests
session = requests.Session()
session.trust_env = False # 取 IP 这一步别走环境变量里的代理
resp = session.get("http://api.xydaili.net:2022/tools/ip.ashx",
params={"action": "GetIP", "OrderNumber": "订单号",
"protocol": 1, "qty": 1, "split": "json"},
timeout=25)
item = resp.json()["data"][0]
proxy = "http://%s:%s" % (item["ip"], item["port"])
r = requests.get("http://www.baidu.com",
proxies={"http": proxy, "https": proxy},
timeout=15)
print(r.status_code)
三个常见的误解
- 代理不是 VPN。VPN 在网络层接管全部流量,代理只作用于你显式配了代理的那个客户端,浏览器挂代理不影响系统里的其他程序。
- HTTP 代理不给流量加密。http 站点在代理这一跳是明文的,https 的安全性来自 TLS 本身,跟代理没关。
- 代理不等于匿踪。高匿代理只是不往目标站带你的真实 IP,目标站的访问日志照样记着出口 IP,该有的痕迹一个不少。
小结:记三句话就够了——http 走绝对 URL、https 走 CONNECT、认证失败先看 407 是代理层发的还是目标站发的。
我平时做采集用的是 星月代理,短效 IP 自动轮换,API 实时提取和白名单两种模式都支持,上面这些验证就是拿它的线路跑的。第一次接触的话,建议先领几个试用 IP,把链路跑通再谈优化。