VPN працює, внутрішня панель відкривається в браузері, а скрипт Python усе одно видає помилку проксі. У цій картині з тунелем усе гаразд: інтерпретатор читає адресу проксі з власного середовища й надсилає запит туди. Цей посібник читає середовище, яке процес справді бачить, застосовує найвужче виключення і лише потім розглядає явну політику сеансу. Кожен крок завершується командою, вивід якої вирішує, чи продовжувати.

Прочитайте середовище, яке процес справді бачить

Налаштування проксі на робочому столі, експорти в оболонці та рядки Environment= модуля systemd — це три різні джерела, і Requests читає лише останнє, яке успадковує. Запустіть діагностику нижче в тій самій оболонці, контейнері чи модулі, що запускає збійний скрипт, а не у своєму інтерактивному терміналі. Змінна, експортована в оболонці входу, невидима для процесу в контейнері, і ця прогалина пояснює багато повідомлень про проксі, що з'являється нізвідки. Обидві команди друкують одні й ті самі дані з різним рівнем деталізації.

env | grep -i -E 'proxy|requests_ca_bundle|curl_ca_bundle'
python3 -c "import os;[print(k,'=',v) for k,v in sorted(os.environ.items()) if 'proxy' in k.lower()]"

Читаються обидва написання кожної змінної, а дублікати застосовуються в тому порядку, у якому процес їх отримав, тож застарілий HTTP_PROXY може перекрити щойно експортоване значення. Змінні пакета CA тут теж важливі, бо вони змінюють, у що розв'язується verify, не з'являючись ніде в коді. Якщо вивід порожній, середовище не ваша проблема, і цей розділ можна не читати. Якщо в ньому перелічено проксі, якого ви не знаєте, знайдіть файл або модуль, що його задає, перш ніж щось змінювати.

Запитайте в Requests, що він зробить із конкретним URL. Цей виклик показує об'єднані значення проксі, verify і cert для того запиту, не надсилаючи пакет.

python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"

Непорожній запис proxies для приватного хоста і є ваша відповідь, а надруковане значення verify каже, якому пакету CA запит довіряв би. Якщо обидва виглядають правильно, збій далі в стеку, і вам варто перейти до розділу перевірки. Не вгадуйте з коду: об'єднання відбувається для кожного запиту, тому один сеанс може поводитися по-різному для двох хостів.

Виключіть приватний хост, перш ніж щось вимикати

Коли проксі справді потрібен для інших призначень, вузьке виправлення — виключення для цього хоста. Додавайте до наявного списку, а не замінюйте його, бо стирання NO_PROXY ламає кожне інше внутрішнє призначення, яке на нього покладалося. Команди нижче додають запис і потім питають у Requests, чи діє обхід.

export NO_PROXY="${NO_PROXY:+$NO_PROXY,}api.corp.example,.corp.example"
python3 -c "import requests;print(requests.utils.should_bypass_proxies('https://api.corp.example/status',None))"

Зіставлення йде за суфіксом хоста, тож .corp.example покриває весь домен, а api.corp.example — одне ім'я. Гола зірочка вимикає проксі для кожного хоста і майже ніколи не те, чого хоче виробниче завдання. Чи буде враховано запис CIDR, залежить від версій Requests і urllib3 в образі, тому перевіряйте точний запис, а не припускайте, що він працює. Перевірте результат should_bypass_proxies для справжнього URL, а не для імені хоста, набраного з пам'яті.

Тримайте два шари окремо в голові. Обхід проксі HTTP не обходить VPN, бо рішення про проксі ухвалюється в бібліотеці, а рішення про тунель — у таблиці маршрутизації ядра.

Вимикайте trust_env лише як усвідомлену політику сеансу

Якщо все завдання має ігнорувати конфігурацію оточення, побудуйте сеанс явно і зафіксуйте рішення в коді. Це політика, а не обхідний шлях, і її місце в diff, який бачить рецензент. Приклад нижче зберігає тайм-аут, явний шлях до CA і перевірку статусу.

import requests

with requests.Session() as session:
    session.trust_env = False
    response = session.get(
        "https://api.corp.example/status",
        timeout=(5, 20),
        verify="/etc/ssl/certs/corp-ca.pem",
    )
    response.raise_for_status()

Вимкнення trust_env змінює три поведінки одразу, і лише одна з них стосується проксі. Requests перестає читати облікові дані .netrc, а змінні REQUESTS_CA_BUNDLE і CURL_CA_BUNDLE перестають впливати на verify, який тоді повертається до вбудованого сховища сертифікатів. Якщо ваша організація завершує TLS власним CA, це повернення спричиняє помилку перевірки, що виглядає не пов'язаною з щойно зробленою зміною. Саме явна передача verify тримає два ефекти окремо.

Чого робити не варто — це ставити verify=False, щоб заглушити отриману помилку. Так неправильна конфігурація проксі обмінюється на неперевірене з'єднання, і приховується проблема сертифіката, яку виключення мало виявити.

Перевірте збійний шар і збережіть можливість відкату

Три збої виглядають у журналі однаково і не мають нічого спільного: проксі, що не досягає призначення, кидає ProxyError або повертає 502, проблема довіри кидає SSLError, а відмова застосунку повертає 401 або 403. Відтворіть запит поза Requests, щоб побачити, який у вас. Команди нижче прибирають проксі, перевіряють ланцюг сертифікатів і потім повторюють виклик через бібліотеку.

curl -sv --noproxy '*' https://api.corp.example/status -o /dev/null
openssl s_client -connect api.corp.example:443 -servername api.corp.example </dev/null
python3 -c "import requests;r=requests.get('https://api.corp.example/status',timeout=10);print(r.status_code)"

Якщо виклик curl успішний, а виклик Python невдалий, різниця все ще в середовищі. Якщо обидва збоять на етапі TLS, проксі ніколи не був проблемою, і проблема в ланцюгу сертифікатів. Якщо обидва повертають 401, запит дійшов до застосунку, і залишок роботи — автентифікація. Запис того, який із трьох ви спостерігали, економить наступній людині годину.

Відкат — це один рядок в обидва боки: приберіть виключення або поверніть trust_env назад. Збережіть попереднє значення NO_PROXY, перш ніж щось додавати, і віддавайте перевагу скрипту-обгортці або запису Environment= на рівні модуля замість експорту, що живе лише в історії вашого термінала. Обидві зміни видно в середовищі процесу, тож перезапуск зазвичай повертає вас до старої поведінки.

Завершіть, підтвердивши чотири речі: об'єднані налаштування для приватного URL не показують проксі, сертифікат перевіряється щодо потрібного CA, запит повертає очікуваний статус, а зміну зафіксовано там, де її можна відтворити. Зелений скрипт із непоясненим середовищем — це виправлення, яке знову зламається на наступній машині. Команди з цього посібника — ті, що слід вставити в тікет.

Схожі статті