pip check_hostname-Fehler hinter einem Proxy: pip oder der Tunnel?
Zwei Fehler drucken dieselbe pip-Hostnamen-Meldung hinter einem Proxy. Unterscheiden Sie einen veralteten Client von einem Proxy, der Traffic neu signiert, und reparieren Sie die richtige Schicht.
Zwei verschiedene Fehler drucken denselben pip-Traceback, und die Reparatur, die zum einen passt, macht den anderen schlimmer. Ein Client, der zu alt ist, um einen getunnelten Host zu benennen, braucht ein Upgrade. Ein Proxy, der Traffic neu signiert, braucht ein vertrauenswürdiges Wurzelzertifikat, kein Downgrade. Finden Sie heraus, welchen der beiden Sie haben, bevor Sie eine Proxy-Variable ändern, denn die Wege führen in entgegengesetzte Richtungen.
Lesen Sie die letzten Frames, bevor Sie Einstellungen anfassen
Wo der Traceback endet, sagt Ihnen, welche Schicht aufgegeben hat. Wenn die abschließenden Frames im mitgelieferten urllib3-TLS-Code von pip liegen und der Text sich über einen Hostnamen beschwert, konnte die Client-Bibliothek einen Verifikationsschritt nicht abschließen, und das ist weit häufiger ein Versionsproblem als ein Zertifikatsproblem. Wenn der Text stattdessen eine abgelehnte Verbindung, einen unaufgelösten Proxy-Namen oder einen HTTP 407 meldet, liegt der Fehler am Tunnelendpunkt, und kein Upgrade wird das ändern.
Erfassen Sie die pip-Version und die Proxy-Variablen in derselben Shell, die scheitert. Eine Shell, die geöffnet wurde, bevor der Tunnel hochkam, trägt andere Werte als eine, die danach geöffnet wurde, und der Unterschied zwischen beiden ist oft die gesamte Diagnose.
python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'
Wenn der Client älter ist als der Tunnel
Ältere pip-Versionen brachten einen HTTPS-Stack mit, der den Ziel-Hostnamen verlor, sobald der Socket von einem Tunnel umschlossen war. Die check_hostname-Meldung ist das, was dieser Stack ausgibt, wenn er die Verifikation ohne einen Namen zum Vergleichen erreicht. Ein Upgrade beseitigt den Fehler, weil der neuere Client den Namen über den Handshake hinweg behält, und die Änderung ist billig genug, um sie zuerst zu versuchen, wann immer die abschließenden Frames auf mitgelieferten TLS-Code deuten.
Wenn der Index von der scheiternden Maschine aus nicht erreichbar ist, holen Sie ein aktuelles Wheel auf einem Host, der es kann, und installieren Sie aus der Datei. Verwenden Sie den Dateinamen, den Sie tatsächlich heruntergeladen haben, statt einer aus einem Blogbeitrag kopierten Version.
python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl
Wenn der Proxy Traffic neu signiert
Ein Proxy, der TLS beendet und Zertifikate unter einer Unternehmenswurzel neu ausstellt, erzeugt einen anderen Fehler: certificate verify failed, keine Hostnamen-Beschwerde. Dieser Unterschied ist der Hinweis, denn der Client erreichte einen Server und lehnte dann die Identität ab, die ihm gezeigt wurde. Die Reparatur besteht darin, dieser Wurzel ausdrücklich zu vertrauen, sei es für einen Befehl oder über die Variable PIP_CERT, damit der Client eine Kette zu dem aufbauen kann, was der Proxy präsentiert. Die Wurzel in den System-Vertrauensspeicher aufzunehmen funktioniert ebenfalls, ändert aber das Vertrauen für jedes Programm auf der Maschine, und das ist eine größere Entscheidung als die Reparatur einer Paketinstallation.
Behalten Sie --trusted-host als Diagnosewerkzeug, niemals als Dauerzustand. Es schaltet die Prüfung ab, die Sie erhalten wollten, sodass ein wirklich falsches Zertifikat danach gesund aussieht. Wenn Sie es benutzt haben, um ein Paket zu installieren, entfernen Sie es und reparieren Sie die Kette vor dem nächsten Release.
Ihr eigener Python-Code ignoriert die pip-Konfiguration vollständig. Ein requests-Aufruf braucht den Proxy und das Bundle dort übergeben, wo diese Sitzung sie sehen kann, deshalb setzt der Block unten beides auf dem Sitzungsobjekt.
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)
Wenn der Endpunkt oder Port falsch ist
Ein Tunnel-Client schreibt oft den System-Proxy um, während er sich verbindet, was pip auf einen Host zeigen lassen kann, der auf diesem Port nie antwortet. Testen Sie den Endpunkt mit einem Client, der nicht pip ist, bevor Sie irgendeine pip-Einstellung ändern. Wenn curl mit demselben Proxy-Argument scheitert, sitzt der Fehler oberhalb von pip, und keine Konfiguration innerhalb von pip hilft.
Das Befehlsflag und die Umgebungsvariablen sagen dasselbe für verschiedene Bereiche: Das Flag gilt für einen Aufruf, die Variablen für jeden danach gestarteten Prozess. Fügen Sie NO_PROXY für einen internen Index hinzu, damit privater Paketverkehr den Umweg durch den Tunnel überspringt.
curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests
Speichern Sie die Einstellung und beweisen Sie, dass der Pfad funktioniert
Legen Sie den Proxy in der eigenen Konfiguration von pip ab, wenn er die aktuelle Shell überleben soll, und lesen Sie dann zurück, was pip wirklich verwenden wird. Die Debug-Ausgabe nennt die Datei und die Variable hinter jedem Wert, was Streitigkeiten über die Rangfolge schneller klärt als das Lesen der Dokumentation.
Die Verifikation nutzt bewusst zwei Clients. Die Anfrage aus der Standardbibliothek beweist die Route und die Vertrauenskette, während der Download beweist, dass die eigene Konfiguration von pip mit ihnen übereinstimmt. Wenn der erste gelingt und der zweite scheitert, liegt der Unterschied in pip und nicht im Netzwerk.
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 |