Duas falhas diferentes imprimem o mesmo rastreio do pip, e o reparo que serve a uma piora a outra. Um cliente antigo demais para nomear um host tunelizado precisa de uma atualização. Um proxy que re-assina o tráfego precisa de um certificado raiz confiável, não de um downgrade. Descubra qual dos dois você tem antes de editar uma variável de proxy, porque os caminhos seguem em direções opostas.

Leia os últimos quadros antes de tocar nas configurações

Onde o rastreio termina diz qual camada desistiu. Se os quadros finais estiverem dentro do código TLS do urllib3 incluído no pip e o texto reclamar de um nome de host, a biblioteca cliente não conseguiu concluir uma etapa de verificação, e isso é um problema de versão muito mais vezes do que um problema de certificado. Se o texto em vez disso relatar uma conexão recusada, um nome de proxy não resolvido ou um HTTP 407, o ponto final do túnel é o culpado e nenhuma atualização mudará isso.

Capture a versão do pip e as variáveis de proxy no mesmo shell que falha. Um shell aberto antes de o túnel subir carrega valores diferentes de um aberto depois, e a diferença entre eles costuma ser todo o diagnóstico.

python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'

Quando o cliente é mais antigo que o túnel

Versões mais antigas do pip incluíam uma pilha HTTPS que perdia o nome do host de destino quando o socket era envolvido por um túnel. A mensagem check_hostname é o que essa pilha emite quando chega à verificação sem um nome para comparar. Uma atualização remove a falha porque o cliente mais novo mantém o nome durante o aperto de mão, e a mudança é barata o bastante para tentar primeiro sempre que os quadros finais apontarem para código TLS incluído.

Se o índice não puder ser alcançado a partir da máquina que falha, obtenha uma wheel atual em um host que consiga e instale a partir do arquivo. Use o nome de arquivo que você realmente baixou, não uma versão copiada de um post de blog.

python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl

Quando o proxy re-assina o tráfego

Um proxy que encerra o TLS e reemite certificados sob uma raiz corporativa produz outro erro: certificate verify failed, não uma queixa de nome de host. Essa diferença é a pista, porque o cliente chegou a um servidor e depois rejeitou a identidade que lhe foi mostrada. O reparo é confiar nessa raiz explicitamente, seja para um único comando ou pela variável PIP_CERT, para que o cliente possa montar uma cadeia até o que o proxy apresenta. Adicionar a raiz ao armazenamento de confiança do sistema também funciona, mas muda a confiança de todos os programas da máquina, e isso é uma decisão maior do que consertar uma instalação de pacote.

Mantenha o --trusted-host como diagnóstico, nunca como estado permanente. Ele desliga a verificação que você tentava manter, então um certificado realmente errado parece saudável depois. Se você o usou para instalar um pacote, remova-o e repare a cadeia antes da próxima versão.

Seu próprio código Python ignora completamente a configuração do pip. Uma chamada de requests precisa do proxy e do bundle passados onde aquela sessão possa vê-los, e é por isso que o bloco abaixo coloca ambos no objeto de sessão.

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)

Quando o ponto final ou a porta estão errados

Um cliente de túnel costuma reescrever o proxy do sistema enquanto se conecta, o que pode deixar o pip apontando para um host que nunca responde naquela porta. Teste o ponto final com um cliente que não seja o pip antes de mudar qualquer configuração do pip. Se o curl falhar com o mesmo argumento de proxy, a falha está acima do pip e nenhuma configuração dentro do pip ajudará.

A flag do comando e as variáveis de ambiente dizem a mesma coisa a âmbitos diferentes: a flag vale para uma invocação, as variáveis para cada processo iniciado depois. Adicione NO_PROXY para um índice interno, para que o tráfego privado de pacotes pule o desvio pelo túnel.

curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests

Persista a configuração e prove que o caminho funciona

Guarde o proxy na configuração própria do pip quando ele precisar sobreviver ao shell atual, e depois leia de volta o que o pip realmente usará. A saída de debug nomeia o arquivo e a variável por trás de cada valor, o que resolve as discussões sobre precedência mais rápido do que ler a documentação.

A verificação usa dois clientes de propósito. A requisição da biblioteca padrão prova a rota e a cadeia de confiança, enquanto o download prova que a configuração própria do pip concorda com elas. Quando a primeira tem sucesso e o segundo falha, a diferença está dentro do pip e não 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 seeFirst commandRepair
hostname message inside vendored TLS framespython3 -m pip --versionupgrade the client
certificate verify failed after the tunnelcurl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/trust the corporate root
connection refused or HTTP 407env | grep -i -E 'proxy|no_proxy'correct host, port or credentials

Artigos relacionados