Błąd check_hostname w pip za proxy: pip czy tunel?
Dwa różne błędy drukują ten sam komunikat o nazwie hosta w pip za proxy. Odróżnij przestarzałego klienta od proxy, które ponownie podpisuje ruch, i napraw właściwą warstwę.
Dwa różne błędy drukują ten sam ślad pip, a naprawa odpowiednia dla jednego pogarsza drugi. Klient zbyt stary, by nazwać host tunelowany, wymaga aktualizacji. Proxy, które ponownie podpisuje ruch, wymaga zaufanego certyfikatu głównego, a nie obniżenia wersji. Ustal, który z dwóch masz, zanim zmienisz zmienną proxy, bo ścieżki prowadzą w przeciwnych kierunkach.
Przeczytaj ostatnie ramki, zanim dotkniesz ustawień
Miejsce, w którym kończy się ślad, mówi, która warstwa się poddała. Jeśli końcowe ramki znajdują się w dołączonym do pip kodzie TLS urllib3 i tekst skarży się na nazwę hosta, biblioteka klienta nie zdołała dokończyć kroku weryfikacji, a to jest problem wersji znacznie częściej niż problem certyfikatu. Jeśli tekst zamiast tego zgłasza odrzucone połączenie, nierozwiązaną nazwę proxy lub błąd HTTP 407, winny jest punkt końcowy tunelu i żadna aktualizacja tego nie zmieni.
Przechwyć wersję pip i zmienne proxy w tej samej powłoce, która zawodzi. Powłoka otwarta przed podniesieniem tunelu ma inne wartości niż otwarta po nim, a różnica między nimi często stanowi całą diagnozę.
python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'
Gdy klient jest starszy niż tunel
Starsze wydania pip zawierały stos HTTPS, który gubił nazwę hosta docelowego, gdy gniazdo zostało owinięte tunelem. Komunikat check_hostname to, co ten stos emituje, gdy dociera do weryfikacji bez nazwy do porównania. Aktualizacja usuwa błąd, ponieważ nowszy klient zachowuje nazwę przez uścisk dłoni, a zmiana jest wystarczająco tania, by wypróbować ją najpierw, gdy końcowe ramki wskazują dołączony kod TLS.
Jeśli indeks jest nieosiągalny z zawodnej maszyny, pobierz aktualne wheel na hoście, który może to zrobić, i zainstaluj z pliku. Użyj nazwy pliku, który naprawdę pobrałeś, a nie wersji skopiowanej z wpisu blogowego.
python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl
Gdy proxy ponownie podpisuje ruch
Proxy, które kończy TLS i ponownie wystawia certyfikaty pod korporacyjnym korzeniem, daje inny błąd: certificate verify failed, a nie skargę na nazwę hosta. Ta różnica jest wskazówką, ponieważ klient dotarł do serwera, a następnie odrzucił przedstawioną mu tożsamość. Naprawa polega na jawnym zaufaniu temu korzeniowi, albo dla jednego polecenia, albo przez zmienną PIP_CERT, aby klient mógł zbudować łańcuch do tego, co przedstawia proxy. Dodanie korzenia do systemowego magazynu zaufania też działa, ale zmienia zaufanie dla każdego programu na maszynie, a to większa decyzja niż naprawa jednej instalacji pakietu.
Traktuj --trusted-host jako diagnostykę, nigdy jako stan stały. Wyłącza sprawdzanie, które próbowałeś zachować, więc naprawdę błędny certyfikat wygląda potem zdrowo. Jeśli użyłeś go do zainstalowania jednego pakietu, usuń go i napraw łańcuch przed następnym wydaniem.
Twój własny kod Pythona całkowicie ignoruje konfigurację pip. Wywołanie requests wymaga przekazania proxy i pakietu tam, gdzie ta sesja może je zobaczyć, dlatego blok poniżej ustawia oba na obiekcie sesji.
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)
Gdy punkt końcowy lub port są błędne
Klient tunelu często przepisuje proxy systemowe podczas łączenia, co może pozostawić pip wskazujący na hosta, który nigdy nie odpowiada na tym porcie. Przetestuj punkt końcowy klientem, który nie jest pip, zanim zmienisz jakiekolwiek ustawienie pip. Jeśli curl zawiedzie z tym samym argumentem proxy, błąd jest nad pip i żadna konfiguracja wewnątrz pip nie pomoże.
Flaga polecenia i zmienne środowiskowe mówią to samo różnym zakresom: flaga dotyczy jednego wywołania, zmienne każdego procesu uruchomionego później. Dodaj NO_PROXY dla wewnętrznego indeksu, aby prywatny ruch pakietów omijał objazd przez tunel.
curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests
Utrwal ustawienie i udowodnij, że ścieżka działa
Zapisz proxy w konfiguracji pip, gdy ma przetrwać bieżącą powłokę, a potem odczytaj, czego pip naprawdę użyje. Wyjście debug nazywa plik i zmienną stojące za każdą wartością, co rozstrzyga spory o pierwszeństwo szybciej niż czytanie dokumentacji.
Weryfikacja celowo używa dwóch klientów. Żądanie z biblioteki standardowej dowodzi trasy i łańcucha zaufania, a pobranie dowodzi, że konfiguracja pip się z nimi zgadza. Gdy pierwsze się udaje, a drugie zawodzi, różnica jest w pip, a nie w sieci.
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 |