Error check_hostname de pip darrere d’un proxy: pip o el túnel?
Dos errors imprimeixen el mateix missatge de nom d’amfitrió de pip darrere d’un proxy. Distingiu un client antiquat d’un proxy que re-signa el trànsit i repareu la capa correcta.
Dos errors diferents imprimeixen el mateix rastre de pip, i la reparació que va bé a un empitjora l’altre. Un client massa antic per anomenar un amfitrió tunelitzat necessita una actualització. Un proxy que re-signa el trànsit necessita un certificat arrel de confiança, no una baixada de versió. Esbrineu quin dels dos teniu abans d’editar una variable de proxy, perquè els camins van en direccions oposades.
Llegiu els últims marcs abans de tocar la configuració
On acaba el rastre us diu quina capa s’ha rendit. Si els marcs finals seuen dins del codi TLS d’urllib3 inclòs amb pip i el text es queixa d’un nom d’amfitrió, la biblioteca client no va poder acabar un pas de verificació, i això és un problema de versió molt més sovint que un problema de certificat. Si el text en canvi informa d’una connexió rebutjada, d’un nom de proxy no resolt o d’un HTTP 407, el punt final del túnel és el culpable i cap actualització ho canviarà.
Captureu la versió de pip i les variables de proxy al mateix shell que falla. Un shell obert abans que el túnel pugés porta valors diferents d’un obert després, i la diferència entre ells sovint és tot el diagnòstic.
python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'
Quan el client és més antic que el túnel
Les versions antigues de pip portaven una pila HTTPS que perdia el nom d’amfitrió de destinació quan el socket quedava embolcallat per un túnel. El missatge check_hostname és el que aquesta pila emet quan arriba a la verificació sense cap nom amb què comparar. Una actualització elimina la fallada perquè el client més nou conserva el nom durant l’encaixada de mans, i el canvi és prou barat per provar-lo primer sempre que els marcs finals apuntin a codi TLS inclòs.
Si no es pot arribar a l’índex des de la màquina que falla, baixeu una wheel actual en un amfitrió que sí que pugui i instal·leu-la des del fitxer. Feu servir el nom de fitxer que heu baixat de debò, no una versió copiada d’una entrada de blog.
python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl
Quan el proxy re-signa el trànsit
Un proxy que acaba el TLS i reemet certificats sota una arrel corporativa produeix un altre error: certificate verify failed, no una queixa de nom d’amfitrió. Aquesta diferència és la pista, perquè el client va arribar a un servidor i després va rebutjar la identitat que se li va mostrar. La reparació és confiar en aquesta arrel explícitament, ja sigui per a una ordre o mitjançant la variable PIP_CERT, perquè el client pugui construir una cadena fins al que el proxy presenta. Afegir l’arrel a l’emmagatzematge de confiança del sistema també funciona, però canvia la confiança de tots els programes de la màquina, i això és una decisió més gran que arreglar una instal·lació de paquet.
Manteniu --trusted-host com a diagnòstic, mai com a estat permanent. Desactiva la comprovació que volíeu conservar, així que un certificat realment incorrecte sembla sa després. Si l’heu fet servir per instal·lar un paquet, traieu-lo i repareu la cadena abans de la següent versió.
El vostre propi codi Python ignora del tot la configuració de pip. Una crida de requests necessita el proxy i el paquet passats on aquella sessió els pugui veure, i per això el bloc de sota posa tots dos a l’objecte de sessió.
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)
Quan el punt final o el port són incorrectes
Un client de túnel sovint reescriu el proxy del sistema mentre es connecta, i això pot deixar pip apuntant a un amfitrió que no respon mai en aquell port. Proveu el punt final amb un client que no sigui pip abans de canviar cap paràmetre de pip. Si curl falla amb el mateix argument de proxy, la fallada és per sobre de pip i cap configuració dins de pip no ajudarà.
El flag de l’ordre i les variables d’entorn diuen el mateix a àmbits diferents: el flag s’aplica a una invocació, les variables a cada procés iniciat després. Afegiu NO_PROXY per a un índex intern perquè el trànsit privat de paquets s’estalviï la volta pel túnel.
curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests
Persistiu el paràmetre i demostreu que el camí funciona
Emmagatzemeu el proxy a la configuració pròpia de pip quan hagi de sobreviure al shell actual, i després llegiu què farà servir realment pip. La sortida de debug anomena el fitxer i la variable darrere de cada valor, cosa que resol les discussions sobre precedència més de pressa que llegir la documentació.
La verificació fa servir dos clients a propòsit. La petició de la biblioteca estàndard demostra la ruta i la cadena de confiança, mentre que la baixada demostra que la configuració pròpia de pip hi està d’acord. Quan la primera té èxit i la segona falla, la diferència és dins de pip, no a la xarxa.
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 |