A VPN está activa, o panel interno ábrese no navegador e o script de Python segue lanzando un erro de proxy. Nesa imaxe non hai nada mal co túnel: o intérprete le un enderezo de proxy do seu propio ambiente e envía alí a petición. Este manual le a contorna que o proceso ve realmente, aplica a exclusión máis estreita e só despois considera unha política de sesión explícita. Cada paso remata cun comando cuxa saída decide se continúas.

Le a contorna que o proceso ve realmente

Os axustes de proxy do escritorio, as exportacións da shell e as liñas Environment= dunha unidade de systemd son tres fontes distintas, e Requests só le a última que herda. Executa o diagnóstico de abaixo na mesma shell, contedor ou unidade que executa o script fallido, non no teu terminal interactivo. Unha variable exportada na túa shell de inicio de sesión é invisible para un proceso de contedor, e esa fenda explica moitos informes dun proxy que aparece da nada. Os dous comandos imprimen os mesmos datos con distinto nivel de detalle.

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()]"

Lense as dúas grafías de cada variable, e as entradas duplicadas aplícanse na orde en que o proceso as recibiu, así que un HTTP_PROXY obsoleto pode anular o valor que acabas de exportar. As variables do paquete de CA tamén importan aquí, porque cambian a que resolve verify sen aparecer en ningún lugar do código. Se a saída está baleira, a contorna non é o teu problema e podes deixar de ler esta sección. Se enumera un proxy que non recoñeces, atopa o ficheiro ou a unidade que o define antes de cambiar nada.

Pregunta a Requests que faría cunha URL concreta. Esta chamada mostra os valores combinados de proxy, verify e cert para esa petición sen enviar un paquete.

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

Unha entrada proxies non baleira para o host privado é a túa resposta, e o valor verify impreso di en que paquete de CA confiaría a petición. Se ambos parecen correctos, o fallo está máis adiante na pila e deberías saltar á sección de verificación. Non adiviñes a partir do código: a fusión ocorre por petición, por iso unha sesión pode comportarse distinto para dous hosts.

Exclúe o host privado antes de desactivar nada

Cando o proxy é realmente necesario para outros destinos, a corrección estreita é unha exclusión para este host. Engade á lista existente en lugar de substituíla, porque borrar NO_PROXY rompe calquera outro destino interno que dependese del. Os comandos de abaixo engaden a entrada e logo preguntan a Requests se se aplica a omisión.

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))"

A coincidencia é por sufixo de host, así que .corp.example cobre todo o dominio mentres que api.corp.example cobre un só nome. Un asterisco só desactiva o proxy para todos os hosts e case nunca é o que quere unha tarefa de produción. Que se respecte unha entrada CIDR depende das versións de Requests e urllib3 da imaxe, así que proba a entrada exacta en lugar de supor que funciona. Comproba o resultado de should_bypass_proxies para a URL real, non para un nome de host que escribas de memoria.

Mantén as dúas capas separadas na cabeza. Evitar o proxy HTTP non evita a VPN, porque a decisión do proxy ocorre na biblioteca e a do túnel na táboa de enrutamento do núcleo.

Desactiva trust_env só como política de sesión deliberada

Se todo o traballo debe ignorar a configuración ambiental, constrúe a sesión explicitamente e rexistra a decisión no código. Iso é unha política, non un parche, e pertence a un diff que un revisor poida ver. O exemplo de abaixo mantén un tempo de espera, unha ruta de CA explícita e unha comprobación de estado.

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()

Desactivar trust_env cambia tres comportamentos á vez, e só un deles ten que ver con proxies. Requests deixa de ler credenciais de .netrc, e as variables REQUESTS_CA_BUNDLE e CURL_CA_BUNDLE deixan de afectar a verify, que entón recorre ao almacén de certificados incluído. Se a túa organización termina TLS coa súa propia CA, ese respaldo provoca un erro de verificación que parece non ter relación co cambio que acabas de facer. Pasar verify explicitamente é o que mantén separados os dous efectos.

O que non deberías facer é establecer verify=False para silenciar o erro resultante. Iso cambia unha configuración de proxy incorrecta por unha conexión non verificada, e oculta o problema de certificado que a exclusión debía revelar.

Verifica a capa que falla e mantén unha reversión

Tres fallos parécense nun rexistro e non teñen nada en común: un proxy que non alcanza o destino lanza ProxyError ou devolve 502, un problema de confianza lanza SSLError, e un rexeitamento da aplicación devolve 401 ou 403. Reproduce a petición fóra de Requests para ver cal tes. Os comandos de abaixo quitan o proxy, proban a cadea de certificados e logo repiten a chamada a través da biblioteca.

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)"

Se a chamada con curl ten éxito e a chamada de Python falla, a contorna segue sendo a diferenza. Se ambas fallan na etapa TLS, o proxy nunca foi o problema e éo a cadea de certificados. Se ambas devolven 401, a petición chegou á aplicación e o traballo restante é a autenticación. Anotar cal dos tres observaches aforra unha hora á seguinte persoa.

A reversión é unha liña en calquera dirección: quita a exclusión ou volve poñer trust_env. Garda o valor anterior de NO_PROXY antes de engadir algo, e prefire un script envoltorio ou unha entrada Environment= a nivel de unidade a unha exportación que só viva no historial do teu terminal. Ambos os cambios son visibles na contorna do proceso, así que un reinicio adoita devolverte ao comportamento antigo.

Remata confirmando catro cousas: a configuración combinada para a URL privada non mostra ningún proxy, o certificado valida contra a CA prevista, a petición devolve o estado que esperas e o cambio está confirmado nun lugar reproducible. Un script verde cunha contorna sen explicar é unha corrección que volve romper na seguinte máquina. Os comandos deste manual son os que hai que pegar no ticket.

Artigos relacionados