407 Proxy Authentication Required: Każda przyczyna i jak to naprawić

HTTP 407 ma dokładnie jedno znaczenie: proxy przed tobą odrzuciło twoje dane uwierzytelniające. Ten jeden fakt eliminuje większość błędnych kroków — oto reszta mapy.

HTTP 407 Proxy Authentication Required ma dokładnie jedno znaczenie, i jest węższe niż większość ludzi zakłada: proxy siedzące między tobą a internetem odrzuciło żądanie, ponieważ brakuje mu ważnych danych uwierzytelniających dla samego proxy. Docelowa strona nigdy nie została skontaktowana. Nigdy nie zobaczyła twojego żądania, nigdy nie podjęła decyzji i nie może być przyczyną. Naprawienie 407 zawsze oznacza naprawienie konfiguracji proxy — a lista rzeczy, które mogą być z tym nie tak, jest krótka i całkowicie wyliczalna. Ten przewodnik przechodzi przez całą listę, z poprawkami specyficznymi dla narzędzi, które najczęściej sprawiają problemy.

Najpierw przeczytaj nagłówek Proxy-Authenticate

Zgodnie ze specyfikacją HTTP (RFC 9110), 407 musi być towarzyszone przez nagłówek Proxy-Authenticate opisujący, jak się uwierzytelnić — zazwyczaj coś w stylu Proxy-Authenticate: Basic realm="Access to internal site". Twój klient powinien następnie powtórzyć żądanie z nagłówkiem Proxy-Authorization. Ta para jest warta zapamiętania, ponieważ to ona odróżnia 407 od jego sąsiada: 401 pochodzi z serwera źródłowego i paruje WWW-Authenticate z Authorization, podczas gdy 407 pochodzi z pośrednika i używa wersji z prefiksem Proxy-. Jeśli patrzysz na nagłówek WWW-Authenticate, debugujesz niewłaściwy krok.

# See exactly which hop is refusing you, and what scheme it wants
curl -v -x http://USER:PASS@gate.quantumproxies.io:8000 https://httpbin.org/ip

# Response you are looking for on failure:
#   HTTP/1.1 407 Proxy Authentication Required
#   Proxy-Authenticate: Basic realm="..."
#
# Response you want on success: your exit IP, not your own
#   {"origin": "203.0.113.45"}

Jeśli curl -x z danymi uwierzytelniającymi zwraca twój wyjściowy IP, proxy i dane uwierzytelniające są w porządku — a każdy 407, który nadal widzisz w aplikacji, to własna konfiguracja tej aplikacji, a nie proxy. Ten jeden test dzieli problem na pół w około dziesięć sekund.

Przyczyna 1: brakujące, błędne lub w złym miejscu dane uwierzytelniające

Najczęstszą przyczyną jest również najnudniejsza. Dane uwierzytelniające należą do URL proxy, przed hostem, w formie user:pass@host:port — a biblioteka klienta buduje z nich nagłówek Proxy-Authorization. Skopiowanie punktu końcowego z pulpitu nawigacyjnego bez danych uwierzytelniających lub wklejenie hasła do konta zamiast hasła do proxy (zazwyczaj są różne) powoduje natychmiastowe, trwałe 407 przy każdym żądaniu.

import requests

proxy = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=15)
print(r.status_code, r.json())   # 200 and the exit IP = auth is correct

Sprawdź również port. Dostawcy udostępniają różne porty dla rotacyjnych i stałych punktów końcowych oraz dla HTTP w porównaniu do SOCKS5; trafienie w niewłaściwy z ważnymi danymi uwierzytelniającymi może nadal zwrócić 407, ponieważ ten słuchacz oczekuje innego formatu tożsamości. Jeśli nie jesteś pewien, na którym protokole jesteś, nasz wyjaśniacz na temat różnic między SOCKS5 a HTTP proxy wyjaśnia różnice.

Przyczyna 2: specjalne znaki, które nigdy nie zostały zakodowane procentowo

To kosztuje ludzi całe popołudnia. URL proxy to URL, więc każdy zarezerwowany znak w twojej nazwie użytkownika lub haśle musi być zakodowany procentowo, w przeciwnym razie parser podzieli ciąg w niewłaściwym miejscu. Hasło zawierające @ kończy sekcję userinfo wcześniej, a twój klient próbuje połączyć się z hostem, który nie istnieje; : dzieli nazwę użytkownika od hasła w niewłaściwym miejscu.

from urllib.parse import quote

user = quote("team@example.com", safe="")   # team%40example.com
pwd  = quote("p@ss:w#rd", safe="")          # p%40ss%3Aw%23rd

proxy = f"http://{user}:{pwd}@gate.quantumproxies.io:8000"
Lista kontrolna mapująca objawy 407 proxy authentication required na ich rzeczywiste przyczyny, w tym awarie tuneli, zmiany białych list i ustawienia proxy dla poszczególnych narzędzi
Ten sam kod statusu, sześć różnych błędów. Dopasuj objaw po lewej stronie, zanim cokolwiek zmienisz.

Przyczyna 3: uwierzytelnianie białej listy i IP, które się zmieniło

Większość dostawców obsługuje dwa tryby uwierzytelniania: dane uwierzytelniające w URL lub białe listy IP, gdzie autoryzujesz publiczny adres swojego serwera w pulpicie nawigacyjnym i nie wysyłasz żadnych danych uwierzytelniających. QuantumProxies obsługuje oba. Tryb awarii jest specyficzny i bardzo rozpoznawalny: wszystko działało przez tygodnie, a potem każde żądanie zaczęło zwracać 407 bez zmiany kodu. To jest zmiana twojego publicznego IP — odnowienie dzierżawy DHCP w biurze, nowa brama NAT po ponownym wdrożeniu w chmurze, mobilne połączenie tetheringowe lub runner CI, który otrzymuje nowy adres przy każdym zadaniu.

Potwierdź to, zanim zaczniesz debugować cokolwiek innego: pobierz swój aktualny publiczny adres za pomocą curl -sS https://api.ipify.org, porównaj go z białą listą i dodaj ponownie, jeśli się różni. Jeśli twój egress IP nie jest stabilny — runnery CI i grupy autoskalujące rzadko są — przełącz to środowisko na uwierzytelnianie user:pass, które podróżuje z konfiguracją zamiast z siecią. Druga połowa tej pułapki to mieszanie trybów: niektóre bramy odrzucają dane uwierzytelniające na punkcie końcowym tylko z białą listą, więc wysyłanie obu może się nie powieść tam, gdzie wysyłanie żadnego się udaje.

Przyczyna 4: HTTPS przechodzi przez tunel CONNECT

407, który pojawia się tylko na URL https://, często jako błąd Python OSError: Tunnel connection failed: 407 Proxy Authentication Required, ma przyczynę strukturalną. Zwykłe żądania HTTP są przesyłane przez proxy, ale żądania HTTPS otwierają najpierw tunel za pomocą żądania CONNECT — a to CONNECT niesie własny nagłówek Proxy-Authorization. Jeśli twoja konfiguracja ustawiła tylko proxy HTTP lub ustawiła dane uwierzytelniające na jednym schemacie, a nie na drugim, tunel jest próbowany anonimowo i odrzucany, zanim TLS nawet się zacznie.

Zasada jest prosta: zawsze konfiguruj oba schematy z tymi samymi danymi uwierzytelniającymi. W Python oznacza to oba klucze w słowniku proxies; w powłoce oznacza to HTTP_PROXY i HTTPS_PROXY; w npm oznacza to proxy i https-proxy. Zauważ, że HTTPS_PROXY prawie zawsze przyjmuje schemat http:// — schemat opisuje, jak rozmawiasz z proxy, a nie co pobierasz przez nie.

// Node 18+ with undici: one dispatcher covers http and https targets
import { ProxyAgent, fetch } from "undici";

const dispatcher = new ProxyAgent(
  "http://USER:PASS@gate.quantumproxies.io:8000"
);

const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(res.status, await res.json());

Przyczyna 5: narzędzie ma własną konfigurację proxy

Zmienne środowiskowe nie są uniwersalne. Wiele narzędzi czyta własny plik konfiguracyjny i całkowicie ignoruje powłokę, co powoduje irytujący stan, w którym curl działa, a twoja kompilacja nie. Długotrwały problem GitHub Desktop jest podręcznikowym przykładem: deweloper za korporacyjnym proxy ustawił proxy w .gitconfig i w środowisku, a mimo to logowanie nadal nie powiodło się z 407 i net::ERR_TUNNEL_CONNECTION_FAILED — ponieważ konfiguracja git uwierzytelniała tylko git, podczas gdy osadzona przeglądarka wykonująca przepływ OAuth nie miała własnych danych uwierzytelniających proxy. Każdy podsystem potrzebuje osobnego poinformowania.

# shell-wide (respected by curl, wget, pip, most SDKs)
export HTTP_PROXY="http://USER:PASS@gate.quantumproxies.io:8000"
export HTTPS_PROXY="$HTTP_PROXY"
export NO_PROXY="localhost,127.0.0.1,.internal"

# npm - both keys, or https installs will 407
npm config set proxy       "$HTTP_PROXY"
npm config set https-proxy  "$HTTPS_PROXY"

# git
git config --global http.proxy  "$HTTP_PROXY"
git config --global https.proxy "$HTTPS_PROXY"

# apt - /etc/apt/apt.conf.d/95proxies
# Acquire::http::Proxy  "http://USER:PASS@gate.quantumproxies.io:8000";
# Acquire::https::Proxy "http://USER:PASS@gate.quantumproxies.io:8000";

Jedna uwaga dotycząca bezpieczeństwa podczas edytowania wszystkich tych plików: dane uwierzytelniające w globalnej konfiguracji git lub npm kończą się w postaci zwykłego tekstu, a URL proxy z osadzonymi hasłami wycieka do historii powłoki, logów CI i śladów błędów. Na maszynach ze stabilnym adresem, białe listy IP całkowicie unikają tajemnicy.

Porównanie uwierzytelniania proxy user:pass z uwierzytelnianiem białej listy IP, pokazujące kompromisy w zakresie przenośności i obsługi tajemnic
Dane uwierzytelniające podróżują z twoją konfiguracją; białe listy podróżują z twoją siecią. Wybierz dla każdego środowiska, nigdy oba naraz.

407 nigdy nie jest winą docelowej strony

Warto to powtórzyć, ponieważ oszczędza ci to pościgu za duchami. Jeśli otrzymujesz 407, żadna ilość rotacji agentów użytkownika, dodawania nagłówków ani zmiany krajów wyjściowych nie pomoże — żądanie nie opuściło jeszcze twojego proxy. Blokady pochodzące z celu wyglądają inaczej: 403 Forbidden oznacza, że strona cię odrzuciła, a 429 Too Many Requests oznacza, że poszedłeś za szybko. Zdiagnozuj, który z trzech faktycznie masz, zanim napiszesz jakikolwiek kod. A jeśli Python rzuca ProxyError lub SSLError zamiast czystego 407, nasz przewodnik po debugowaniu ProxyError w Requests obejmuje awarie na poziomie transportu.

Często zadawane pytania

Jak rozwiązać 407 Proxy Authentication Required?

Umieść ważne dane uwierzytelniające w URL proxy jako http://user:pass@host:port, kodując procentowo wszelkie zarezerwowane znaki, i skonfiguruj zarówno ustawienia proxy HTTP, jak i HTTPS. Jeśli twój dostawca używa białych list IP, autoryzuj swój obecny publiczny IP i nie wysyłaj żadnych danych uwierzytelniających. Zweryfikuj za pomocą curl -x przeciwko usłudze echa IP, zanim dotkniesz kodu aplikacji.

Co oznacza 407 Proxy Authentication Required?

Oznacza to, że pośrednie proxy odrzuciło żądanie z powodu braku ważnych danych uwierzytelniających proxy. Odpowiedź zawiera nagłówek Proxy-Authenticate nazwający schemat, a klient powinien ponowić próbę z Proxy-Authorization. Jest to odrębne od 401, które pochodzi z serwera docelowego, a nie z proxy pomiędzy.

Jak naprawić błąd npm 407?

Ustaw oba klucze: npm config set proxy i npm config set https-proxy, każdy z pełnym URL http://user:pass@host:port. Ruch rejestru jest HTTPS, więc ustawienie tylko HTTP zawodzi na tunelu CONNECT. Koduj procentowo specjalne znaki w haśle i sprawdź, czy projektowy .npmrc nie nadpisuje twojego globalnego.

Dlaczego Python zgłasza Tunnel connection failed: 407?

Ponieważ żądanie HTTPS otworzyło tunel CONNECT, który nie miał danych uwierzytelniających proxy. Ustaw oba klucze http i https w słowniku proxies na ten sam uwierzytelniony URL. Sprawdź również, czy HTTP_PROXY lub HTTPS_PROXY w środowisku nie nadpisuje twojego słownika — ustaw session.trust_env = False, aby to wykluczyć.

Jak ustawić uwierzytelnianie proxy w Postman?

Otwórz Ustawienia, przejdź do zakładki Proxy, włącz niestandardową konfigurację proxy, wprowadź hosta i port, następnie zaznacz pole uwierzytelniania proxy i dodaj nazwę użytkownika i hasło. Poleganie na przełączniku systemowego proxy to zwykły błąd — kieruje ruch przez proxy, ale nigdy nie dostarcza danych uwierzytelniających, więc każde żądanie zwraca 407.

Pięć przyczyn obejmuje zasadniczo każdy 407 w naturze: brakujące dane uwierzytelniające, niezakodowane specjalne znaki, zmieniony białolistny IP, nieautoryzowany tunel CONNECT i narzędzie z własną konfiguracją. Pracuj nad nimi w tej kolejności, a kod statusu zniknie — wtedy możesz zacząć martwić się o to, co docelowa strona o tobie myśli.

Zdobądź proxy rezydencjalne z uwierzytelnianiem user:pass lub białą listą IP