Due guasti diversi stampano la stessa traccia di pip, e la riparazione che si addice a uno peggiora l’altro. Un client troppo vecchio per nominare un host incapsulato in un tunnel richiede un aggiornamento. Un proxy che ri-firma il traffico richiede un certificato radice affidabile, non un downgrade. Stabilite quale dei due avete prima di modificare una variabile proxy, perché i percorsi portano in direzioni opposte.

Leggete gli ultimi frame prima di toccare le impostazioni

Dove termina la traccia vi dice quale livello ha ceduto. Se i frame finali si trovano nel codice TLS di urllib3 incluso con pip e il testo si lamenta di un nome host, la libreria client non è riuscita a completare un passo di verifica, e questo è un problema di versione molto più spesso che un problema di certificato. Se il testo segnala invece una connessione rifiutata, un nome proxy non risolto o un HTTP 407, il punto terminale del tunnel è in colpa e nessun aggiornamento lo cambierà.

Raccogliete la versione di pip e le variabili proxy nella stessa shell che fallisce. Una shell aperta prima che il tunnel salisse porta valori diversi da una aperta dopo, e la differenza tra le due è spesso tutta la diagnosi.

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

Quando il client è più vecchio del tunnel

Le versioni precedenti di pip includevano uno stack HTTPS che perdeva il nome host di destinazione quando il socket veniva avvolto da un tunnel. Il messaggio check_hostname è ciò che quello stack emette quando arriva alla verifica senza un nome con cui confrontare. Un aggiornamento elimina il guasto perché il client più recente conserva il nome durante la stretta di mano, e il cambiamento è abbastanza economico da tentarlo per primo ogni volta che i frame finali puntano a codice TLS incluso.

Se l’indice non è raggiungibile dalla macchina che fallisce, scaricate una wheel aggiornata su un host che può farlo e installate dal file. Usate il nome file che avete davvero scaricato, non una versione copiata da un post di blog.

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

Quando il proxy ri-firma il traffico

Un proxy che termina TLS e riemette certificati sotto una radice aziendale produce un errore diverso: certificate verify failed, non una lamentela sul nome host. Questa differenza è l’indizio, perché il client ha raggiunto un server e poi ha rifiutato l’identità che gli è stata mostrata. La riparazione è fidarsi esplicitamente di quella radice, che sia per un comando o tramite la variabile PIP_CERT, così che il client possa costruire una catena verso ciò che il proxy presenta. Aggiungere la radice all’archivio di fiducia del sistema funziona anch’esso, ma cambia la fiducia per ogni programma della macchina, ed è una decisione più grande che riparare una singola installazione di pacchetto.

Tenete --trusted-host come diagnostica, mai come stato permanente. Disattiva il controllo che cercavate di conservare, così un certificato davvero sbagliato sembra sano dopo. Se lo avete usato per installare un pacchetto, rimuovetelo e riparate la catena prima della versione successiva.

Il vostro codice Python ignora del tutto la configurazione di pip. Una chiamata requests ha bisogno del proxy e del bundle passati dove quella sessione può vederli, ed è per questo che il blocco qui sotto imposta entrambi sull’oggetto sessione.

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 il punto terminale o la porta sono sbagliati

Un client tunnel riscrive spesso il proxy di sistema mentre si connette, il che può lasciare pip puntato a un host che non risponde mai su quella porta. Provate il punto terminale con un client che non sia pip prima di cambiare qualsiasi impostazione di pip. Se curl fallisce con lo stesso argomento proxy, il guasto sta sopra pip e nessuna configurazione dentro pip aiuterà.

Il flag del comando e le variabili d’ambiente dicono la stessa cosa a ambiti diversi: il flag vale per una singola invocazione, le variabili per ogni processo avviato dopo. Aggiungete NO_PROXY per un indice interno, così il traffico privato dei pacchetti evita il giro attraverso il tunnel.

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

Rendete persistente l’impostazione e dimostrate che il percorso funziona

Mettete il proxy nella configurazione propria di pip quando deve sopravvivere alla shell corrente, poi rileggete ciò che pip userà davvero. L’output di debug nomina il file e la variabile dietro ogni valore, il che risolve le discussioni sulla precedenza più in fretta della lettura della documentazione.

La verifica usa due client di proposito. La richiesta della libreria standard dimostra la rotta e la catena di fiducia, mentre il download dimostra che la configurazione propria di pip è d’accordo con esse. Quando la prima riesce e il secondo fallisce, la differenza è dentro pip e non nella rete.

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

Articoli correlati