You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python HTTPS代理拦截请求用重定向替代HTTP403的实现方案

HTTPS代理拦截重定向实现方案

问题根因

HTTPS请求先发送CONNECT方法请求代理建立TCP隧道,浏览器默认只有收到200 Connection Established响应后,才会开始后续TLS握手流程。如果在CONNECT阶段直接返回403、3xx等状态码,浏览器不会解析响应内容,直接抛出隧道连接失败错误,这就是之前方案失效的核心原因。

可落地方案

方案一:无证书重定向(改动最小,适配当前代码结构)

不需要客户端安装任何证书,仅需调整拦截逻辑,利用现代浏览器的容错机制实现跳转:

  • 对普通HTTP请求,命中黑名单时直接返回307重定向响应,携带拦截提示页地址即可
  • 对HTTPS CONNECT请求,命中黑名单时不要连接目标服务器,先返回200 Connection Established假装隧道建立成功,等待浏览器发送TLS Client Hello包后,直接返回明文307重定向响应,浏览器会自动识别并跳转到拦截提示页,不会报隧道连接错误。

具体代码修改

  1. 首先改造原有response函数,支持自定义响应头:
def response(status, message, headers=None):
    reply = f"HTTP/1.1 {status} {message}\r\n"
    reply += "Proxy-agent: Sinktrap\r\n"
    if headers:
        for k, v in headers.items():
            reply += f"{k}: {v}\r\n"
    reply += "\r\n"
    browser_conn.sendall(reply.encode())
  1. 替换原有的黑名单拦截判断逻辑:
# 替换为自己的拦截提示页地址
BLOCK_PAGE = "自定义拦截提示页地址"

# Check if request is allowed or not
if not ishostAllowed(req['host']):
    csv_logger.info("blocked",extra=req)
    thread_logger.warn("Block REQUEST:{0}".format(raw_data),extra=req)
    
    if req['method'] == 'CONNECT':
        # HTTPS请求先伪装隧道建立成功
        response(200, "Connection established")
        # 短暂等待接收浏览器发送的Client Hello包,无需处理内容
        time.sleep(0.1)
        try:
            browser_conn.recv(config.max_request_len)
        except:
            pass
        # 发送重定向响应
        response(307, "Temporary Redirect", {
            "Location": BLOCK_PAGE,
            "Content-Length": "0"
        })
    else:
        # HTTP请求直接重定向
        response(307, "Temporary Redirect", {
            "Location": BLOCK_PAGE,
            "Content-Length": "0"
        })
    
    browser_conn.close()
    return

方案优缺点

  • 优点:代码改动量极小,不需要客户端预装证书,兼容Chrome、Edge、Firefox等所有主流现代浏览器,不会再出现隧道连接失败错误
  • 缺点:跳转后地址栏会显示拦截页域名,无法保留原被拦截站点域名;极个别老旧浏览器不兼容该逻辑

方案二:MITM中间人拦截(体验最优)

如果需要在原域名下直接展示拦截内容、不跳转第三方地址,就需要实现中间人代理逻辑:

  • 生成自签CA根证书,将证书安装到所有使用代理的客户端信任列表中
  • 拦截到HTTPS CONNECT请求时,动态签发对应域名的伪造证书,和浏览器完成TLS握手
  • 解密浏览器发送的HTTP请求,直接返回自定义拦截页内容即可
    该方案需要实现TLS握手、动态证书生成逻辑,不建议从零手写,可以直接基于成熟的中间人代理库二次开发,减少重复工作量。

原有代码问题说明

  • 之前尝试直接在CONNECT阶段返回307、或者手动修改host连接拦截页的逻辑不可行:浏览器在CONNECT阶段不会处理3xx状态码,且跨域名的TLS证书会被浏览器直接拦截报安全错误
  • 现有host解析正则对IPv6地址、无路径的CONNECT请求兼容性不足,建议单独对CONNECT方法做host、port解析逻辑

内容的提问来源于stack exchange,提问作者AzlanCoding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:36:24