VPN-ul este activ, panoul intern se deschide în browser, iar scriptul Python aruncă în continuare o eroare de proxy. În acea imagine nu e nimic în neregulă cu tunelul: interpretorul citește o adresă de proxy din propriul mediu și trimite cererea acolo. Acest ghid citește mediul pe care procesul îl vede cu adevărat, aplică cea mai îngustă excludere și abia apoi ia în calcul o politică explicită de sesiune. Fiecare pas se termină cu o comandă a cărei ieșire decide dacă continui.

Citește mediul pe care procesul îl vede cu adevărat

Setările de proxy ale desktopului, exporturile din shell și liniile Environment= ale unei unități systemd sunt trei surse diferite, iar Requests citește doar ultima pe care o moștenește. Rulează diagnosticul de mai jos în același shell, container sau unitate care rulează scriptul care eșuează, nu în terminalul tău interactiv. O variabilă exportată în shell-ul de autentificare este invizibilă pentru un proces din container, iar acel gol explică multe rapoarte despre un proxy care apare de nicăieri. Cele două comenzi tipăresc aceleași date la niveluri diferite de detaliu.

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()]"

Se citesc ambele grafii ale fiecărei variabile, iar intrările duplicate se aplică în ordinea în care procesul le-a primit, așa că un HTTP_PROXY învechit poate suprascrie valoarea pe care tocmai ai exportat-o. Variabilele pachetului CA contează și aici, pentru că schimbă în ce se rezolvă verify fără să apară nicăieri în cod. Dacă ieșirea este goală, mediul nu este problema ta și poți opri citirea acestei secțiuni. Dacă listează un proxy pe care nu îl recunoști, găsește fișierul sau unitatea care îl setează înainte de a schimba ceva.

Întreabă Requests ce ar face cu un URL anume. Acest apel arată valorile combinate de proxy, verify și cert pentru acea cerere fără a trimite un pachet.

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

O intrare proxies nevidă pentru gazda privată este răspunsul tău, iar valoarea verify tipărită îți spune în ce pachet CA ar avea încredere cererea. Dacă ambele par corecte, defecțiunea este mai departe în stivă și ar trebui să treci la secțiunea de verificare. Nu ghici din cod: îmbinarea se face pentru fiecare cerere, de aceea o singură sesiune se poate comporta diferit pentru două gazde.

Exclude gazda privată înainte de a dezactiva ceva

Când proxy-ul este cu adevărat necesar pentru alte destinații, corectura îngustă este o excludere pentru această gazdă. Adaugă la lista existentă în loc să o înlocuiești, pentru că ștergerea NO_PROXY rupe orice altă destinație internă care se baza pe el. Comenzile de mai jos adaugă intrarea și apoi întreabă Requests dacă ocolirea se aplică.

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))"

Potrivirea se face după sufixul gazdei, așa că .corp.example acoperă întregul domeniu, iar api.corp.example un singur nume. Un asterisc singur dezactivează proxy-ul pentru orice gazdă și aproape niciodată nu este ceea ce vrea un job de producție. Dacă o intrare CIDR este respectată depinde de versiunile Requests și urllib3 din imagine, așa că testează intrarea exactă în loc să presupui că funcționează. Verifică rezultatul should_bypass_proxies pentru URL-ul real, nu pentru un nume de gazdă tastat din memorie.

Ține cele două straturi separate în minte. Ocolirea proxy-ului HTTP nu ocolește VPN-ul, pentru că decizia privind proxy-ul se ia în bibliotecă, iar decizia privind tunelul în tabela de rutare a nucleului.

Dezactivează trust_env doar ca politică deliberată de sesiune

Dacă întregul job trebuie să ignore configurația ambientală, construiește sesiunea explicit și consemnează decizia în cod. Aceasta este o politică, nu o soluție ocolitoare, și îi aparține unui diff pe care un recenzent îl poate vedea. Exemplul de mai jos păstrează un timeout, o cale CA explicită și o verificare de stare.

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()

Dezactivarea trust_env schimbă trei comportamente deodată, iar doar unul dintre ele este despre proxy-uri. Requests nu mai citește acreditările .netrc, iar variabilele REQUESTS_CA_BUNDLE și CURL_CA_BUNDLE nu mai influențează verify, care atunci revine la depozitul de certificate inclus. Dacă organizația ta încheie TLS cu propriul CA, acea revenire produce o eroare de verificare care pare fără legătură cu modificarea pe care tocmai ai făcut-o. Trecerea explicită a verify este ceea ce ține cele două efecte separate.

Ce nu ar trebui să faci este să setezi verify=False pentru a potoli eroarea rezultată. Aceasta schimbă o configurație greșită de proxy pe o conexiune neverificată și ascunde problema de certificat pe care excluderea trebuia să o scoată la iveală.

Verifică stratul care eșuează și păstrează o posibilitate de revenire

Trei defecțiuni arată la fel într-un jurnal și nu au nimic în comun: un proxy care nu atinge destinația aruncă ProxyError sau returnează 502, o problemă de încredere aruncă SSLError, iar o respingere a aplicației returnează 401 sau 403. Reprodu cererea în afara Requests pentru a vedea care este cazul tău. Comenzile de mai jos elimină proxy-ul, testează lanțul de certificate și apoi repetă apelul prin bibliotecă.

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)"

Dacă apelul curl reușește și apelul Python eșuează, mediul este în continuare diferența. Dacă ambele eșuează în etapa TLS, proxy-ul nu a fost niciodată problema și lanțul de certificate este. Dacă ambele returnează 401, cererea a ajuns la aplicație și munca rămasă este autentificarea. Notarea careia dintre cele trei ai observat-o economisește o oră următoarei persoane.

Revenirea este o singură linie în ambele direcții: elimină excluderea sau readu trust_env la loc. Salvează valoarea anterioară a NO_PROXY înainte de a adăuga ceva, și preferă un script de împachetare sau o intrare Environment= la nivel de unitate în locul unui export care trăiește doar în istoricul terminalului tău. Ambele modificări sunt vizibile în mediul procesului, așa că o repornire te readuce de obicei la comportamentul vechi.

Încheie confirmând patru lucruri: setările combinate pentru URL-ul privat nu arată niciun proxy, certificatul se validează față de CA-ul dorit, cererea returnează starea pe care o aștepți, iar modificarea este comisă într-un loc care poate fi reprodus. Un script verde cu un mediu neexplicat este o corectură care se strică din nou pe mașina următoare. Comenzile din acest ghid sunt cele care trebuie lipite în tichet.

Articole similare