Python mitmproxy 隧道代理:中间人代理转发爬虫代理

mitmproxy upstream 模式转发到亿牛云爬虫代理,通过 addon 注入 Proxy-Tunnel 头实现 IP 固定。

亿牛云技术团队2026年5月31日2 分钟阅读

mitmproxy 的角色

mitmproxy 是一个中间人代理(Man-in-the-Middle Proxy),通常用于拦截、查看和修改 HTTP/HTTPS 流量。在采集场景中,可以将 mitmproxy 作为本地转发层,将所有流量转发到亿牛云爬虫代理。

架构

客户端 → mitmproxy (localhost:38080) → 亿牛云爬虫代理 (t.16yun.cn:31111) → 目标站

这种架构的好处是:客户端不需要配置代理认证,将所有代理逻辑集中在 mitmproxy 层。

启动命令

# upstream 模式启动,上游指向爬虫代理
mitmdump \
  --listen-host 127.0.0.1 \
  --listen-port 38080 \
  --mode upstream:http://t.16yun.cn:31111 \
  --upstream-auth username:password \
  -s addon.py

参数说明:

参数作用
--mode upstream:http://host:port将所有请求转发到上游代理
--upstream-auth user:pass上游代理的认证信息
-s addon.py加载 addon 脚本
--connection_strategy=lazy延迟建立连接

Addon 脚本

addon 可以在请求转发前注入自定义头,用于 Proxy-Tunnel:

# addon.py
import os
from mitmproxy import http

HOST = os.getenv("PROXY_HOST", "t.16yun.cn")
PORT = os.getenv("PROXY_PORT", "31111")
USER = os.getenv("PROXY_USERNAME") or os.getenv("PROXY_USER") or "username"
PASS = os.getenv("PROXY_PASSWORD") or os.getenv("PROXY_PASS") or "password"
SEED = os.getenv("PROXY_TUNNEL", "mitmproxy-demo-1")

class UpstreamProxy:
    def request(self, flow: http.HTTPFlow) -> None:
        # 注入 Proxy-Tunnel 头
        flow.request.headers.setdefault("Proxy-Tunnel", SEED)

addons = [UpstreamProxy()]

客户端通过 mitmproxy 访问

客户端只需要将代理指向本地 mitmproxy,不需要知道上游代理的认证信息:

import requests

session = requests.Session()
session.proxies = {
    "http": "http://127.0.0.1:38080",
    "https": "http://127.0.0.1:38080",
}

for i in range(3):
    resp = session.get("https://httpbin.org/ip", timeout=30)
    print(f"请求 {i+1}: {resp.json()['origin']}")

在代码中启动 mitmproxy

import subprocess
import atexit
import signal
import socket
import time

def start_mitmproxy():
    host = os.getenv("PROXY_HOST", "t.16yun.cn")
    port = os.getenv("PROXY_PORT", "31111")
    user = os.getenv("PROXY_USERNAME", "user")
    pwd = os.getenv("PROXY_PASSWORD", "password")
    listen_port = int(os.getenv("MITMPROXY_PORT", "38080"))

    cmd = [
        "mitmdump",
        "--listen-host", "127.0.0.1",
        "--listen-port", str(listen_port),
        "--mode", f"upstream:http://{host}:{port}",
        "--upstream-auth", f"{user}:{pwd}",
        "-s", "addon.py",
        "--set", "connection_strategy=lazy",
    ]

    proc = subprocess.Popen(cmd)

    def cleanup():
        if proc.poll() is None:
            proc.terminate()
            proc.wait(timeout=5)

    atexit.register(cleanup)

    # 等待端口就绪
    deadline = time.time() + 20
    while time.time() < deadline:
        try:
            socket.create_connection(("127.0.0.1", listen_port), timeout=1)
            return listen_port
        except OSError:
            time.sleep(0.5)

    raise RuntimeError("mitmproxy 启动超时")

四种场景在 mitmproxy 中的实现

场景mitmproxy 实现说明
A:强制切换客户端每次新建连接由客户端控制,mitmproxy 透传
B:保持 IP客户端复用连接mitmproxy 保持上游连接
C:Proxy-Tunnel HTTP/HTTPSaddon 注入 Proxy-Tunneladdon 自动为每个请求添加

mitmproxy 的优势在于:所有客户端的代理逻辑统一管理,不需要每个客户端单独配置代理认证。

错误排查

现象原因解决
mitmproxy 启动失败mitmdump 未安装pip install mitmproxy
上游认证失败--upstream-auth 凭据错误核对用户名密码
连接超时代理不可达验证 t.16yun.cn:31111 连通性

需要企业代理方案?

我们可根据目标站点、并发规模与稳定性目标提供定制方案。