使用Socket实现的HTTP代理无法访问HTTPS站点问题咨询
问题原因及修复方案
1. CONNECT响应格式不符合规范
你当前返回的200 Connection Established响应附带了多余的请求头,这违反了HTTP代理的标准规则:
正确的CONNECT成功响应仅需要返回状态行+两个空行,不需要携带任何额外请求头,格式如下:
HTTP/1.1 200 Connection Established
你把浏览器发的CONNECT请求头又原样塞进了响应里,火狐识别到非法的响应格式,会直接中断后续的TLS握手流程,自然无法加载页面。
2. 请求读取逻辑不完整
你代码中使用单次incomingIS.read(b)读取客户端请求,TCP是流式传输协议,单次read调用无法保证能读取到完整的请求头,存在概率截断请求的问题,HTTP请求头需要读取到连续的\r\n\r\n才代表读取结束。
3. 缺少双向流量转发逻辑
CONNECT请求完成后,浏览器和目标站点之间会走加密的TLS流量,这部分流量是双向传输的:
- 你当前的代码仅实现了「安卓代理→浏览器」的单向转发,没有实现「浏览器→安卓代理」的后续TLS数据转发
- TLS握手需要浏览器和服务端双向交互,缺少上行流量转发会导致握手直接失败
4. 次要代码缺陷
你打印响应内容时使用的是最初读取请求的len变量,而非每次读响应得到的length变量,会导致日志输出内容错误,不过这个问题不影响功能运行。
快速修复建议
- 先识别请求类型:如果是CONNECT请求,不要直接转发给安卓代理,先给浏览器返回标准的
200 Connection Established响应,再启动双向转发逻辑,把后续的所有流量直接转发给安卓代理 - 把单向的流读写改成双向独立的读写逻辑:分别处理客户端到代理、代理到客户端的流量,不要在同一个线程里串行处理
- 不要对HTTPS的二进制流量做String转换,避免编码错误导致数据篡改
内容的提问来源于stack exchange,提问作者fakeivchenko
相关产品推荐
相关产品推荐

