Skip to content
Advanced / 10 min read

So routen Sie Dataimpulse-Proxys über mitmproxy auf macOS für Web Scraping

Ein einzelner lokaler mitmproxy-Listener leitet jeden Scraper, Browser und Emulator auf macOS über HTTP oder SOCKS5 an Dataimpulse-Residential- oder Mobile-Proxys weiter, wobei Rotation, Drosselung und optionale TLS-Inspektion unter Ihrer Kontrolle liegen.

macOS SOCKS5 Web Scraping Privatsphäre/Anonymität

Überblick

mitmproxy ist ein skriptbarer, quelloffener Intercepting-Proxy, der als normaler macOS-Prozess läuft. Im Upstream-Modus akzeptiert er Verbindungen von lokalen Clients an einem Port (127.0.0.1:8080) und leitet diesen Datenverkehr an einen zweiten Proxy weiter – in diesem Fall an Ihren Dataimpulse-Residential- oder Mobile-Endpunkt.

Der Vorteil ist die Zentralisierung: Sie konfigurieren den Proxy einmal, und danach kann jeder Browser, jedes CLI-Tool, jedes Python-Skript oder jeder mobile Emulator auf dem Rechner über Dataimpulse geleitet werden, ohne die eigenen Proxy-Einstellungen des Tools zu bearbeiten. Alles läuft durch einen einzigen Engpass, an dem Sie die Parallelität begrenzen, Fehler beobachten und bestätigen können, welche Exit-IP Sie tatsächlich verwenden.

Dataimpulse eignet sich gut für dieses Muster, weil es Residential- und Mobile-Endpunkte sowohl über HTTP als auch über SOCKS5 anbietet, mit Pay-as-you-go-Abrechnung und einem großen IP-Pool – nützlich für stoßweise Datenerfassung mit hohem Volumen, bei der eine monatliche Bindung nicht erforderlich ist. Sie können es mit anderen Proxy-Anbietern vergleichen, bevor Sie sich entscheiden.

Wann dieser Ansatz sinnvoll ist

Ansatz Was Sie konfigurieren Am besten für
mitmproxy-Upstream-Modus (diese Anleitung) Einen lokalen Port für alle Clients Mehrere Tools gleichzeitig, zentrale Drosselung und Protokollierung
Proxy-Flags pro Tool (curl -x, requests proxies=) Jedes Tool separat Ein einzelnes Skript mit minimalen beweglichen Teilen
Desktop-Proxy-Manager (zum Beispiel Proxifier) Regeln pro Anwendung GUI-Apps, die System-Proxy-Einstellungen ignorieren

Was Sie erstellen werden

  • Einen lokalen mitmproxy-Listener auf 127.0.0.1:8080
  • Eine Upstream-Verbindung zu Dataimpulse über HTTP oder SOCKS5
  • Optionale TLS-Interception für die spezifischen Hosts, die Sie untersuchen möchten
  • Ein Concurrency-Gate-Addon, das den Anfragedruck vorhersehbar hält
  • Funktionierende Beispiele für curl, requests, Playwright und einen Android-Emulator

Voraussetzungen

  • macOS 13 oder neuer mit installiertem Homebrew
  • Ein Dataimpulse-Konto sowie Benutzername, Passwort, Gateway-Host und die in Ihrem Dashboard angezeigten HTTP/SOCKS5-Ports
  • Python 3.9 oder neuer für die Client-Beispiele (python3 --version)
  • Vertrautheit mit dem Terminal und ein grundlegendes Verständnis von HTTP-Proxys und TLS

Wie das Setup funktioniert

  1. mitmproxy lauscht auf 127.0.0.1:8080.
  2. Ihr Client sendet seine Anfrage an mitmproxy statt direkt an die Zielseite.
  3. mitmproxy öffnet eine Verbindung zum Dataimpulse-Gateway.
  4. Dataimpulse weist eine Exit-IP aus seinem Pool zu.
  5. Die Antwort läuft durch mitmproxy zurück zu Ihrem Client.

Zwei Modi sind wichtig, und eine frühzeitige Entscheidung spart Zeit:

  • Pass-through (Tunneling): mitmproxy leitet TLS-Bytes weiter, ohne sie zu entschlüsseln. Es sind nirgendwo Zertifikatsänderungen erforderlich. Aktiviert mit --ignore-hosts '.*'.
  • Interception: mitmproxy beendet TLS, damit es Anfragen und Antworten lesen oder umschreiben kann. Erfordert, dass das mitmproxy-CA-Zertifikat unter macOS und in jeder Client-Laufzeitumgebung als vertrauenswürdig eingestuft wird.

Für Scraping, das nur eine andere Exit-IP benötigt, ist Pass-through einfacher und schneller und vermeidet Zertifikatsarbeit vollständig. Aktivieren Sie Interception nur für Hosts, die Sie wirklich untersuchen müssen.

Schritte

  1. Installieren Sie mitmproxy.

    brew install mitmproxy
    mitmdump --version
    
  2. Exportieren Sie Ihre Dataimpulse-Anmeldedaten als Umgebungsvariablen, damit sie nie in der Shell-Historie oder in committeten Dateien auftauchen.

    export DI_USER='your-dataimpulse-username'
    export DI_PASS='your-dataimpulse-password'
    export DI_HOST='gateway-host-from-your-dashboard'
    export DI_HTTP_PORT='http-port-from-your-dashboard'
    export DI_SOCKS_PORT='socks5-port-from-your-dashboard'
    export DI_SESSION='scrape-macos-01'
    

    Fügen Sie dieselben Zeilen zu ~/.zshrc hinzu, wenn sie in jeder neuen Shell verfügbar sein sollen, und bestätigen Sie Host und Port, ohne das Passwort auszugeben:

    echo "${DI_HOST}:${DI_HTTP_PORT}"
    
  3. Prozentkodieren Sie Anmeldedaten, die reservierte Zeichen enthalten. Zeichen wie @, :, / oder # in einem Passwort beschädigen die Upstream-URL. Kodieren Sie nur den Wert, den Sie in die URL einfügen.

    python3 -c "import os, urllib.parse; print(urllib.parse.quote(os.environ['DI_PASS'], safe=''))"
    
  4. Starten Sie mitmproxy im Pass-through-Upstream-Modus über HTTP. Im Pass-through-Modus tunnelt mitmproxy den Datenverkehr, ohne ihn zu entschlüsseln, sodass keine Client-Zertifikatsänderungen erforderlich sind.

    mitmdump \
      --mode "upstream:http://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_HTTP_PORT}" \
      --listen-port 8080 \
      --ignore-hosts '.*' \
      --set flow_detail=1
    
  5. Überprüfen Sie die Exit-IP. Lassen Sie mitmproxy in einem eigenen Terminalfenster laufen und testen Sie aus einem zweiten Fenster.

    curl -s -x http://127.0.0.1:8080 https://api.ipify.org
    echo
    curl -s https://api.ipify.org
    echo
    

    Die beiden Adressen sollten sich unterscheiden. Wenn sie übereinstimmen, erreicht die Anfrage Dataimpulse nicht – siehe Abschnitt zur Fehlerbehebung.

  6. Stellen Sie das Upstream auf SOCKS5 um, wenn der Proxy DNS remote auflösen soll, was für geo-sensitive Ziele oft vorzuziehen ist.

    mitmdump \
      --mode "upstream:socks5://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_SOCKS_PORT}" \
      --listen-port 8080 \
      --ignore-hosts '.*'
    
  7. Aktivieren Sie Interception nur für die Hosts, die Sie benötigen. --allow-hosts beschränkt die Entschlüsselung auf passende Hosts; alles andere bleibt getunnelt und unangetastet.

    mitmdump \
      --mode "upstream:http://${DI_USER}:${DI_PASS}@${DI_HOST}:${DI_HTTP_PORT}" \
      --listen-port 8080 \
      --allow-hosts 'example\.com' \
      -s ./gate.py
    
  8. Vertrauen Sie dem mitmproxy-CA-Zertifikat, bevor Sie HTTPS-Hosts per Interception scrapen. Die Zertifikatsdateien werden beim ersten Start von mitmproxy erstellt.

    # Der erste Lauf erzeugt ~/.mitmproxy/mitmproxy-ca-cert.pem
    mitmdump --listen-port 8081 &
    sleep 2
    kill %1
    
    sudo security add-trusted-cert -d -r trustRoot \
      -k /Library/Keychains/System.keychain \
      ~/.mitmproxy/mitmproxy-ca-cert.pem
    

    Kommandozeilen-Laufzeitumgebungen ignorieren oft den macOS-Schlüsselbund, daher sollten Sie sie auf ein explizites Bundle verweisen:

    cat "$(python3 -c 'import certifi; print(certifi.where())')" \
      ~/.mitmproxy/mitmproxy-ca-cert.pem > ~/.mitmproxy/ca-bundle.pem
    
    export REQUESTS_CA_BUNDLE=~/.mitmproxy/ca-bundle.pem
    export NODE_EXTRA_CA_CERTS=~/.mitmproxy/mitmproxy-ca-cert.pem
    
  9. Fügen Sie ein Concurrency-Gate-Addon hinzu, damit ein Burst von einem schnellen Scraper das Gateway nicht überflutet. Speichern Sie dies als gate.py neben dem Verzeichnis, aus dem Sie mitmproxy starten.

    # gate.py — begrenzt gleichzeitige Anfragen, die durch mitmproxy laufen
    import asyncio
    
    from mitmproxy import http
    
    
    class Gate:
        def __init__(self, limit: int = 8) -> None:
            self._limit = limit
            self._sem: asyncio.Semaphore | None = None
    
        def running(self) -> None:
            self._sem = asyncio.Semaphore(self._limit)
    
        async def request(self, flow: http.HTTPFlow) -> None:
            await self._sem.acquire()
            flow.metadata["gate_held"] = True
    
        def _release(self, flow: http.HTTPFlow) -> None:
            if flow.metadata.pop("gate_held", False):
                self._sem.release()
    
        def response(self, flow: http.HTTPFlow) -> None:
            self._release(flow)
    
        def error(self, flow: http.HTTPFlow) -> None:
            self._release(flow)
    
    
    addons = [Gate(limit=8)]
    

    Laden Sie es mit -s ./gate.py. Beachten Sie, dass Addons nur abgefangene Flows sehen: Wenn Sie mit --ignore-hosts '.*' ausführen, werden Verbindungen getunnelt und diese Hooks werden nie ausgelöst. Begrenzen Sie in diesem Fall stattdessen die Parallelität in Ihrem Scraper.

  10. Richten Sie Ihre Tools auf den lokalen Listener aus. Exportieren Sie für Shell-Tools die Standardvariablen in dem Terminal, von dem aus Sie scrapen – aber nicht in dem Terminal, in dem mitmproxy läuft, um eine Proxy-Schleife zu vermeiden.

    export HTTP_PROXY=http://127.0.0.1:8080
    export HTTPS_PROXY=http://127.0.0.1:8080
    export NO_PROXY=localhost,127.0.0.1
    curl -s https://httpbin.org/ip
    

    Für ein Python-Skript ist keine CA-Konfiguration erforderlich, solange Sie im Pass-through-Modus bleiben:

    import requests
    
    LOCAL_PROXY = "http://127.0.0.1:8080"
    proxies = {"http": LOCAL_PROXY, "https": LOCAL_PROXY}
    
    response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30)
    response.raise_for_status()
    print(response.json())
    

    Für einen Headless-Browser übergeben Sie denselben lokalen Proxy an den Browser-Kontext:

    from playwright.sync_api import sync_playwright
    
    LOCAL_PROXY = "http://127.0.0.1:8080"
    
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True, proxy={"server": LOCAL_PROXY})
        page = browser.new_page()
        page.goto("https://httpbin.org/ip", wait_until="domcontentloaded")
        print(page.inner_text("body"))
        browser.close()
    

    Wenn Sie außerdem einen Dienst scrapen müssen, der auf Ihrem eigenen Rechner läuft, umgeht Chromium standardmäßig Loopback-Adressen. Das Hinzufügen von args=["--proxy-bypass-list=<-loopback>"] zum Launch-Aufruf hebt diese Ausnahme auf.

  11. Emulator-Datenverkehr erfassen (optional). Dataimpulse-Mobile-Endpunkte liefern Exit-IPs in Carrier-Qualität; sie erfassen den Gerätedatenverkehr nicht selbst. Um einen Emulator durch diesen Pool zu leiten, richten Sie den Emulator auf den Host-Listener aus.

    # Android-Emulator: 10.0.2.2 ist der Host-Rechner
    adb shell settings put global http_proxy 10.0.2.2:8080
    adb shell settings get global http_proxy
    
    # Zurücksetzen, wenn fertig
    adb shell settings put global http_proxy :0
    

    Öffnen Sie für den iOS-Simulator Einstellungen, wählen Sie WLAN, dann Proxy konfigurieren, Manuell, und setzen Sie den Server auf 127.0.0.1 bei Port 8080. Der Simulator-Datenverkehr nutzt den Netzwerk-Stack des Macs, daher muss die CA auch im Simulator installiert sein, damit Interception funktioniert.

  12. Räumen Sie auf, wenn Sie fertig sind. Entfernen Sie das Interception-Zertifikat und setzen Sie alle Client-Einstellungen zurück, damit nicht zusammenhängender Datenverkehr nicht mehr durch mitmproxy fließt.

    sudo security delete-certificate -c mitmproxy /Library/Keychains/System.keychain
    unset HTTP_PROXY HTTPS_PROXY
    

Fehlerbehebung

407 Proxy Authentication Required

In der Upstream-URL fehlen Anmeldedaten, oder ein reserviertes Zeichen im Passwort hat die URL beschädigt. Führen Sie den Befehl zur Prozentkodierung aus Schritt 3 erneut aus und bauen Sie die --mode-Zeichenkette mit dem kodierten Wert neu auf.

SSLCertVerificationError, CERT_AUTHORITY_INVALID oder unable to get local issuer certificate

Sie haben Interception aktiviert, aber der Client vertraut der mitmproxy-CA nicht. Installieren Sie das Zertifikat wie in Schritt 8 gezeigt und setzen Sie dann die laufzeitspezifischen Bundle-Variablen (REQUESTS_CA_BUNDLE, NODE_EXTRA_CA_CERTS). Alternativ können Sie mit --ignore-hosts '.*' in den Pass-through-Modus zurückkehren, wenn Sie den Datenverkehr nicht lesen müssen.

Address already in use

Ein anderer Prozess belegt den Port bereits. Finden Sie ihn, und ändern Sie dann --listen-port, anstatt nicht zusammenhängende Dienste zu beenden.

lsof -nP -iTCP:8080 -sTCP:LISTEN

Alle Anfragen hängen oder laufen in ein Timeout

Sie befinden sich höchstwahrscheinlich in einer Proxy-Schleife: HTTP_PROXY ist in derselben Shell exportiert, die mitmproxy gestartet hat, sodass mitmproxys eigene Upstream-Verbindung an ihn selbst zurückgesendet wird. Starten Sie mitmproxy in einem sauberen Terminal oder führen Sie unset HTTP_PROXY HTTPS_PROXY aus, bevor Sie es starten.

Anfragen sind erfolgreich, aber die Exit-IP ändert sich nie

Der Pass-through-Modus rotiert nichts von allein. Das Rotationsverhalten wird durch den Sitzungstyp bestimmt, den Sie in Ihrem Dashboard konfiguriert haben, und dadurch, wie Ihr Client Verbindungen öffnet. Vergewissern Sie sich, dass Sie nicht eine einzelne Sticky-Session über den gesamten Lauf hinweg festhalten, und prüfen Sie die Exit-IP mit dem Befehl aus Schritt 5.

Der Emulator ignoriert den Proxy

Bei Android-Emulatoren bezieht sich 127.0.0.1 auf den Emulator selbst, nicht auf den Mac. Verwenden Sie 10.0.2.2 und bestätigen Sie den Wert mit adb shell settings get global http_proxy.

Ziele liefern 403 oder 429

Dies ist eine Ratenbegrenzung am Ziel, kein Proxy-Fehler. Reduzieren Sie das Gate-Limit in gate.py, fügen Sie Verzögerungen zwischen Anfragen hinzu und stellen Sie sicher, dass Ihr Scraping den Bedingungen der Website und robots.txt entspricht.

Zusammenfassung

Sie verfügen jetzt über einen einzelnen lokalen mitmproxy-Listener unter macOS, der jeden Client über HTTP oder SOCKS5 an Dataimpulse-Residential- oder Mobile-Proxys weiterleitet, mit Pass-through-Modus für einfache IP-Rotation und selektiver Interception für tiefergehende Untersuchungen. Anmeldedaten liegen in Umgebungsvariablen, die Parallelität wird durch ein Addon begrenzt, und das Zertifikatsvertrauen kann sauber hinzugefügt oder entfernt werden, wenn Sie verschlüsselten Datenverkehr nicht mehr lesen müssen.