VPN je aktivan, interni panel se otvara u pregledniku, a Python skripta i dalje baca proxy grešku. Na toj slici s tunelom nije ništa pogrešno: interpreter čita proxy adresu iz vlastitog okruženja i šalje zahtjev tamo. Ovaj priručnik čita okruženje koje proces zaista vidi, primjenjuje najuže izuzeće i tek onda razmatra izričitu politiku sesije. Svaki korak završava naredbom čiji izlaz odlučuje da li nastavljate.

Pročitajte okruženje koje proces zaista vidi

Postavke proxyja na radnoj površini, exporti u ljusci i linije Environment= systemd unita tri su različita izvora, a Requests čita samo posljednji koji naslijedi. Pokrenite dijagnostiku ispod u istoj ljusci, kontejneru ili unitu koji pokreće neuspjelu skriptu, a ne u svom interaktivnom terminalu. Varijabla exportana u vašoj login ljusci nevidljiva je procesu u kontejneru, i taj jaz objašnjava mnoge prijave proxyja koji se pojavljuje niotkuda. Dvije naredbe ispisuju iste podatke na različitim razinama detalja.

env | grep -i -E 'proxy|requests_ca_bundle|curl_ca_bundle'
python3 -c "import os;[print(k,'=',v) for k,v in sorted(os.environ.items()) if 'proxy' in k.lower()]"

Čitaju se oba zapisa svake varijable, a duplikati se primjenjuju redoslijedom kojim ih je proces primio, pa zastarjeli HTTP_PROXY može nadjačati vrijednost koju ste upravo exportali. Varijable CA bundlea i ovdje su važne, jer mijenjaju u šta se razrješava verify a da se nigdje ne pojavljuju u kodu. Ako je izlaz prazan, okruženje nije vaš problem i možete prestati čitati ovaj odjeljak. Ako navodi proxy koji ne prepoznajete, pronađite datoteku ili unit koji ga postavlja prije nego što bilo šta promijenite.

Pitajte Requests šta bi uradio s određenim URL-om. Ovaj poziv prikazuje spojene proxy, verify i cert vrijednosti za taj zahtjev bez slanja paketa.

python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"

Neprazan unos proxies za privatni host je vaš odgovor, a ispisana vrijednost verify govori kojem CA bundleu bi zahtjev vjerovao. Ako oboje izgleda ispravno, kvar je kasnije u stogu i treba da pređete na odjeljak o verifikaciji. Ne nagađajte iz koda: spajanje se događa po zahtjevu, zato se jedna sesija može ponašati različito za dva hosta.

Isključite privatni host prije nego što bilo šta isključite

Kada je proxy zaista potreban za druge destinacije, usko rješenje je izuzeće za ovaj host. Dodajte na postojeću listu umjesto da je zamijenite, jer brisanje NO_PROXY kvari svaku drugu internu destinaciju koja se na njega oslanjala. Naredbe ispod dodaju unos i zatim pitaju Requests da li se zaobilaznica primjenjuje.

export NO_PROXY="${NO_PROXY:+$NO_PROXY,}api.corp.example,.corp.example"
python3 -c "import requests;print(requests.utils.should_bypass_proxies('https://api.corp.example/status',None))"

Podudaranje je po sufiksu hosta, pa .corp.example pokriva cijelu domenu, a api.corp.example jedno ime. Gola zvjezdica isključuje proxy za svaki host i gotovo nikada nije ono što produkcijski posao želi. Hoće li CIDR unos biti prihvaćen zavisi od verzija Requests i urllib3 u imidžu, pa testirajte tačan unos umjesto da pretpostavljate da radi. Provjerite rezultat should_bypass_proxies za stvarni URL, a ne za ime hosta koje ste otipkali po sjećanju.

Držite dva sloja odvojeno u glavi. Zaobilaženje HTTP proxyja ne zaobilazi VPN, jer se odluka o proxyju donosi u biblioteci, a odluka o tunelu u kernelovoj tabeli rutiranja.

Onemogućite trust_env samo kao svjesnu politiku sesije

Ako cijeli posao treba ignorisati ambijentalnu konfiguraciju, izgradite sesiju izričito i zabilježite odluku u kodu. To je politika, a ne zaobilazno rješenje, i pripada diffu koji recenzent može vidjeti. Primjer ispod zadržava timeout, izričitu CA putanju i provjeru statusa.

import requests

with requests.Session() as session:
    session.trust_env = False
    response = session.get(
        "https://api.corp.example/status",
        timeout=(5, 20),
        verify="/etc/ssl/certs/corp-ca.pem",
    )
    response.raise_for_status()

Isključivanje trust_env mijenja tri ponašanja odjednom, a samo jedno od njih tiče se proxyja. Requests prestaje čitati .netrc akreditive, a varijable REQUESTS_CA_BUNDLE i CURL_CA_BUNDLE prestaju uticati na verify, koji se tada vraća na ugrađeno spremište certifikata. Ako vaša organizacija završava TLS vlastitim CA, to vraćanje podiže grešku verifikacije koja izgleda nepovezano s promjenom koju ste upravo napravili. Izričito prosljeđivanje verify je ono što drži dva efekta odvojenima.

Ono što ne treba da radite je da postavite verify=False da ušutkate nastalu grešku. Time mijenjate pogrešnu proxy konfiguraciju za neverifikovanu vezu i skrivate problem s certifikatom koji je izuzeće trebalo da razotkrije.

Verifikujte neuspjeli sloj i zadržite mogućnost vraćanja

Tri kvara izgledaju isto u logu i nemaju ništa zajedničko: proxy koji ne može doći do destinacije podiže ProxyError ili vraća 502, problem s povjerenjem podiže SSLError, a odbijanje aplikacije vraća 401 ili 403. Reprodukujte zahtjev izvan Requestsa da vidite koji od tri imate. Naredbe ispod uklanjaju proxy, testiraju lanac certifikata i zatim ponavljaju poziv kroz biblioteku.

curl -sv --noproxy '*' https://api.corp.example/status -o /dev/null
openssl s_client -connect api.corp.example:443 -servername api.corp.example </dev/null
python3 -c "import requests;r=requests.get('https://api.corp.example/status',timeout=10);print(r.status_code)"

Ako curl poziv uspije, a Python poziv ne uspije, okruženje je i dalje razlika. Ako oba ne uspiju u TLS fazi, proxy nikada nije bio problem i problem je lanac certifikata. Ako oba vraćaju 401, zahtjev je stigao do aplikacije i preostali posao je autentifikacija. Zapisivanje koje od tri ste primijetili štedi sljedećoj osobi sat vremena.

Vraćanje je jedan red u oba smjera: uklonite izuzeće ili vratite trust_env nazad. Sačuvajte prethodnu vrijednost NO_PROXY prije nego što joj dodate, i radije koristite omotajuću skriptu ili unos Environment= na nivou unita nego export koji živi samo u historiji vašeg terminala. Obje promjene su vidljive u okruženju procesa, pa vas restart obično vraća na staro ponašanje.

Završite potvrđivanjem četiri stvari: spojene postavke za privatni URL ne pokazuju proxy, certifikat se validira prema predviđenom CA, zahtjev vraća status koji očekujete, a promjena je commitana na mjestu koje se može reproducirati. Zelena skripta s neobjašnjenim okruženjem je popravka koja se ponovo kvari na sljedećoj mašini. Naredbe iz ovog priručnika su one koje treba zalijepiti u tiket.

Povezani članci