pip check_hostname-fejl bag en proxy: pip eller tunnelen?
To forskellige fejl udskriver den samme pip-værtsnavnefejl bag en proxy. Skel mellem en forældet klient og en proxy, der gensignerer trafik, og reparer det rigtige lag.
To forskellige fejl udskriver den samme pip-traceback, og den reparation, der passer til den ene, gør den anden værre. En klient, der er for gammel til at navngive en tunneleret vært, har brug for en opgradering. En proxy, der gensignerer trafik, har brug for et betroet rodcertifikat, ikke en nedgradering. Find ud af, hvilken af de to du har, før du redigerer en proxyvariabel, fordi stierne fører i modsatte retninger.
Læs de sidste rammer, før du rører indstillingerne
Der, hvor tracebacken slutter, fortæller dig, hvilket lag der gav op. Hvis de afsluttende rammer ligger inde i pip's indbyggede urllib3-TLS-kode, og teksten klager over et værtsnavn, kunne klientbiblioteket ikke færdiggøre et verifikationstrin, og det er et versionsproblem langt oftere end et certifikatproblem. Hvis teksten i stedet rapporterer en afvist forbindelse, et uopklaret proxynavn eller en HTTP 407, er tunnelendepunktet skyld i det, og ingen opgradering ændrer det.
Fang pip-versionen og proxyvariablerne i samme shell, som fejler. En shell, der blev åbnet, før tunnelen kom op, bærer andre værdier end en, der blev åbnet bagefter, og forskellen mellem dem er ofte hele diagnosen.
python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'
Når klienten er ældre end tunnelen
Ældre pip-udgivelser medbragte en HTTPS-stak, der mistede destinationsværtsnavnet, når socket blev pakket ind af en tunnel. check_hostname-meddelelsen er det, den stak udsender, når den når verifikation uden et navn at sammenligne med. En opgradering fjerner fejlen, fordi den nyere klient beholder navnet gennem håndtrykket, og ændringen er billig nok til at prøve først, når de afsluttende rammer peger på indbygget TLS-kode.
Hvis indekset ikke kan nås fra den fejlende maskine, hent en aktuel wheel på en vært, der kan, og installer fra filen. Brug det filnavn, du faktisk hentede, i stedet for en version kopieret fra et blogindlæg.
python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl
Når proxyen gensignerer trafik
En proxy, der afslutter TLS og genudsteder certifikater under en virksomhedsrod, producerer en anden fejl: certificate verify failed, ikke en klage over værtsnavn. Den forskel er ledetråden, fordi klienten nåede en server og afviste derefter den identitet, den blev vist. Reparationen er at stole på den rod eksplicit, enten for én kommando eller via PIP_CERT-variablen, så klienten kan bygge en kæde til det, proxyen præsenterer. At føje roden til systemets tillidslager virker også, men det ændrer tilliden for hvert program på maskinen, og det er en større beslutning end at rette én pakkeinstallation.
Behold --trusted-host som en diagnose, aldrig som en varig tilstand. Det slår den kontrol fra, du forsøgte at beholde, så et virkelig forkert certifikat ser sundt ud bagefter. Hvis du brugte det til at få én pakke installeret, så fjern det og reparer kæden før næste udgivelse.
Din egen Python-kode ignorerer pip's konfiguration helt. Et requests-kald har brug for, at proxyen og bundtet gives videre der, hvor den session kan se dem, og derfor sætter blokken nedenfor begge på session-objektet.
pip install --cert /usr/local/share/ca-certificates/corp-root.crt requests
export PIP_CERT=/usr/local/share/ca-certificates/corp-root.crt
s = requests.Session()
s.proxies = {"https": "http://10.20.30.40:8080"}
s.verify = "/usr/local/share/ca-certificates/corp-root.crt"
s.get("https://pypi.org/simple/", timeout=15)
Når endepunktet eller porten er forkert
En tunnelklient omskriver ofte systemproxyen, mens den forbinder, hvilket kan efterlade pip pegende på en vært, der aldrig svarer på den port. Test endepunktet med en klient, der ikke er pip, før du ændrer nogen pip-indstilling. Hvis curl fejler med det samme proxyargument, sidder fejlen over pip, og ingen mængde konfiguration inde i pip hjælper.
Kommandofanebladet og miljøvariablerne siger det samme til forskellige områder: fanebladet gælder for én kald, variablerne for hver proces, der startes bagefter. Tilføj NO_PROXY for et internt indeks, så privat pakketrafik springer omvejen gennem tunnelen over.
curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests
Gem indstillingen og bevis, at stien virker
Gem proxyen i pip's egen konfiguration, når den skal overleve den aktuelle shell, og læs derefter tilbage, hvad pip virkelig vil bruge. Debug-outputtet navngiver filen og variablen bag hver værdi, hvilket afgør diskussioner om forrang hurtigere end at læse dokumentationen.
Verifikation bruger bevidst to klienter. Anmodningen fra standardbiblioteket beviser ruten og tillidskæden, mens downloadet beviser, at pip's egen konfiguration er enig med dem. Når den første lykkes, og den anden fejler, ligger forskellen inde i pip og ikke i netværket.
pip config set global.proxy http://proxy.corp.internal:8080
pip config debug
python3 -c "import urllib.request as r; print(r.urlopen('https://pypi.org/simple/').status)"
pip download --no-deps -d /tmp/wheelcheck requests
| What you see | First command | Repair |
|---|---|---|
| hostname message inside vendored TLS frames | python3 -m pip --version | upgrade the client |
| certificate verify failed after the tunnel | curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/ | trust the corporate root |
| connection refused or HTTP 407 | env | grep -i -E 'proxy|no_proxy' | correct host, port or credentials |