先记住这个答案
客户端向代理发送CONNECT host:port HTTP/1.1,代理验证授权后主动连接目标主机,若TCP连接建立成功则返回200 Connection Established,随后立即在原TCP连接上双向转发后续所有字节。代理不参与TLS握手,只透传加密数据。CONNECT是逐跳方法,普通源服务器不支持,仅由代理链中的每一跳处理。
- CONNECT目标仅包含host和端口
- 2xx响应后代理进入盲转发模式
- 代理不参与TLS,只透传密文
隧道建立的协议语义
客户端发送CONNECT example.com:443 HTTP/1.1,请求行中不写路径,只有目标主机和端口。代理收到后检查自身策略和Proxy-Authorization头,然后代替客户端向example.com:443发起TCP连接。此时代理并不发送任何HTTP请求到目标服务器,只完成传输层连接。
当代理确认与目标服务器的TCP三次握手成功,它返回200 Connection Established给客户端。这个响应是告诉客户端:后续字节流都会被代理原样转发。客户端收到2xx后,便直接在现有连接上开始TLS握手,代理只会盲目地双向拷贝字节,不解析HTTP或TLS内容。
内网客户端经代理访问 HTTPS 站点
某内网只能通过认证代理出网,客户端浏览器配置代理为proxy.corp:8080。访问https://api.example.com时,浏览器看到URI scheme为https,自动发送CONNECT api.example.com:443 HTTP/1.1,并携带Proxy-Authorization: Basic ...。代理验证通过后,尝试连接目标443端口,成功则返回200。
此后浏览器在隧道中完成TLS证书校验和加密传输,代理只能看到密文,无法窃听应用数据。由于代理规则限制CONNECT仅允许目标端口443,因此风险面缩小;若允许任意端口,攻击者可能借用代理转发SMTP、SSH等非HTTP流量,这正是需要白名单的原因。
适用边界与失效条件
当代理无法连接目标(DNS解析失败、连接超时、TCP RST)时,不会返回2xx,而是返回502 Bad Gateway或504 Gateway Timeout,隧道不会建立。客户端收到非2xx后必须终止后续操作,不能把响应体当作隧道数据继续发送。
CONNECT是逐跳方法,普通源服务器收到CONNECT通常返回405 Method Not Allowed或直接关闭连接,所以它只能发给代理。若构建代理链,每一跳代理都必须明确支持并转发CONNECT才能串联成功;代理配置还需启用审计日志,记录谁在什么时间请求了哪些目标。
容易答错的地方
- 误区:代理会解密HTTPS内容
- CONNECT只创建TCP隧道,代理不参与TLS握手,也看不到明文内容。只有当代理主动做中间人并安装根证书时才能解密,那被称为TLS拦截,与CONNECT的默认行为不同。
- 误区:CONNECT请求可以带路径
- CONNECT的请求目标固定为
host:port形式,没有URI路径和查询字符串。规范要求必须显式包含端口,省略路径;违反此格式的请求应视为畸形,代理可能返回400 Bad Request。
面试官还会怎么问?
代理如何知道隧道建立是否成功?
代理主动向目标发起TCP连接,连接成功即可返回2xx,通常为200。若连接过程中发生失败,则返回5xx,且不会进入隧道状态,客户端无法继续发送应用数据。
CONNECT是否支持HTTP/2?
支持。HTTP/2的CONNECT方法语义一致,利用流在现有连接上创建隧道,但代理仍然保持透传模式,不读取上层数据。实际部署中向HTTP/1.1代理发送CONNECT最常见。
为什么源服务器通常不支持CONNECT?
CONNECT设计用途是代理转发,不针对具体资源。源服务器处理的是普通方法,收到CONNECT时无路径可对应,因此返回405 Method Not Allowed。只有代理会识别并执行这个语义。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。