Erro check_hostname de pip detrás dun proxy: pip ou o túnel?
Dous fallos imprimen a mesma mensaxe de nome de host de pip detrás dun proxy. Distinga un cliente obsoleto dun proxy que volve asinar o tráfico e repare a capa correcta.
Dous fallos distintos imprimen o mesmo rastro de pip, e a reparación que serve para un empeora o outro. Un cliente demasiado antigo para nomear un host tunelizado necesita unha actualización. Un proxy que volve asinar o tráfico necesita un certificado raíz de confianza, non unha degradación. Determine cal dos dous ten antes de editar unha variable de proxy, porque os camiños van en direccións opostas.
Lea os últimos marcos antes de tocar a configuración
Onde remata o rastro dille que capa se rendeu. Se os marcos finais están dentro do código TLS de urllib3 incluído con pip e o texto se queixa dun nome de host, a biblioteca cliente non puido rematar un paso de verificación, e iso é un problema de versión moito máis a miúdo que un problema de certificado. Se o texto informa en cambio dunha conexión rexeitada, dun nome de proxy sen resolver ou de un HTTP 407, o punto final do túnel ten a culpa e ningunha actualización o cambiará.
Capture a versión de pip e as variables de proxy na mesma shell que falla. Unha shell aberta antes de que o túnel subise leva valores distintos dunha aberta despois, e a diferenza entre ambas adoita ser todo o diagnóstico.
python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'
Cando o cliente é máis antigo que o túnel
As versións antigas de pip incluían unha pila HTTPS que perdía o nome do host de destino cando o socket quedaba envolto por un túnel. A mensaxe check_hostname é o que esa pila emite cando chega á verificación sen un nome co que comparar. Unha actualización elimina o fallo porque o cliente máis novo conserva o nome durante o aperto de mans, e o cambio é abondo barato para probalo primeiro sempre que os marcos finais apunten a código TLS incluído.
Se non se pode chegar ao índice desde a máquina que falla, descargue unha wheel actual nun host que si poida e instálea desde o ficheiro. Use o nome de ficheiro que descargou de verdade, non unha versión copiada dunha entrada de blog.
python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl
Cando o proxy volve asinar o tráfico
Un proxy que remata TLS e reemite certificados baixo unha raíz corporativa produce outro erro: certificate verify failed, non unha queixa de nome de host. Esa diferenza é a pista, porque o cliente chegou a un servidor e logo rexeitou a identidade que se lle mostrou. A reparación é confiar nesa raíz de forma explícita, xa sexa para un comando ou mediante a variable PIP_CERT, para que o cliente poida construír unha cadea ata o que o proxy presenta. Engadir a raíz ao almacén de confianza do sistema tamén funciona, pero cambia a confianza de todos os programas da máquina, e iso é unha decisión maior que arranxar unha instalación de paquete.
Manteña --trusted-host como diagnóstico, nunca como estado permanente. Desactiva a comprobación que intentaba conservar, así que un certificado realmente incorrecto parece san despois. Se o usou para instalar un paquete, quíteno e repare a cadea antes da seguinte versión.
O seu propio código Python ignora por completo a configuración de pip. Unha chamada de requests necesita o proxy e o paquete pasados onde esa sesión poida velos, e por iso o bloque de abaixo pon ambos no obxecto de sesión.
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)
Cando o punto final ou o porto son incorrectos
Un cliente de túnel a miúdo reescribe o proxy do sistema mentres se conecta, o que pode deixar pip apuntando a un host que nunca responde nese porto. Probe o punto final cun cliente que non sexa pip antes de cambiar calquera axuste de pip. Se curl falla co mesmo argumento de proxy, o fallo está por riba de pip e ningunha configuración dentro de pip axudará.
A opción da orde e as variables de contorno din o mesmo a ámbitos distintos: a opción aplícase a unha invocación, as variables a cada proceso iniciado despois. Engada NO_PROXY para un índice interno, de xeito que o tráfico privado de paquetes evite o rodeo polo túnel.
curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests
Persista o axuste e demostre que o camiño funciona
Garde o proxy na configuración propia de pip cando deba sobrevivir á shell actual, e despois lea o que pip usará realmente. A saída de debug nomea o ficheiro e a variable detrás de cada valor, o que resolve as discusións sobre precedencia máis rápido que ler a documentación.
A verificación usa dous clientes a propósito. A petición da biblioteca estándar demostra a ruta e a cadea de confianza, mentres que a descarga demostra que a configuración propia de pip está de acordo con elas. Cando a primeira ten éxito e a segunda falla, a diferenza está dentro de pip e non na rede.
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 |