파이썬 requests SSL 인증서 오류: verify=False 없이 CA와 프록시 점검하는 법

브라우저에서는 열리는데 Python requests에서 CERTIFICATE_VERIFY_FAILED가 나면 저는 verify=False부터 넣지 않아요. 서버 인증서 체인·호스트명, Python이 읽는 CA 번들, 환경변수, 회사 프록시가 제시하는 인증서는 서로 다른 층이라 한 번에 바꾸면 원인을 놓치기 쉽거든요. 먼저 오류 전문을 읽고 수정할 경계를 좁히는 편이 안전합니다.

오류 원인을 세 계층으로 나누기

requests는 HTTPS 인증서 검증을 기본 수행하며 verify에 CA 번들 파일 또는 디렉터리를 지정할 수 있습니다. 오류는 서버 인증서 체인·호스트명, 현재 Python 환경의 CA, 회사 프록시가 제시하는 인증서 중 하나에서 발생할 수 있습니다. 브라우저와 Python의 결과가 다른 것도 가능합니다. 운영체제·Python 배포판·OpenSSL 구성에 따라 신뢰 저장소가 달라질 수 있기 때문입니다.

오류 전문부터 읽고 원인을 나눠요

오류 전문과 대상 호스트를 먼저 확인해요

SSLCertVerificationError의 메시지에서 체인 검증 실패인지 호스트명 불일치인지 단서를 찾습니다. URL의 호스트명과 오류 전문을 함께 기록하고 타임아웃과 구분합니다.

검증할 CA 번들을 verify로 지정해요

신뢰할 CA 번들을 확보했다면 검증을 끄지 말고 경로를 전달합니다.

import requests

ca_bundle = "/path/to/company-ca-bundle.pem"
response = requests.get("https://api.example.com/data", verify=ca_bundle, timeout=10)
response.raise_for_status()
print(response.json())

경로는 예시이므로 실제 파일을 임의로 만들면 안 됩니다. 서버 운영자나 보안 담당자가 제공한 CA 번들이 대상 서버 또는 프록시에 필요한 인증서를 포함하는지 확인합니다.

환경변수와 프록시 설정을 같이 봐요

Requests는 REQUESTS_CA_BUNDLE을 사용하고 미설정 시 CURL_CA_BUNDLE을 대체 경로로 사용할 수 있습니다.

import os

for name in ("REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE", "HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY", "NO_PROXY"):
    print(f"{name}={os.environ.get(name)!r}")

오래된 CA 파일이나 다른 프록시가 환경변수에 남아 있으면 코드가 같아도 결과가 달라집니다. 회사 네트워크에서만 실패한다면 HTTPS 프록시가 제시하는 인증서의 발급자와 필요한 프록시 루트 CA 배포 여부를 확인합니다.

서버 체인과 호스트명도 확인해요

CA를 바꿔도 실패한다면 서버가 중간 인증서를 빠뜨렸는지, URL 호스트명과 인증서 이름이 맞는지 확인합니다. 이 문제는 클라이언트에 verify=False를 넣어 고칠 수 없고 서버 운영자가 체인을 수정해야 할 수도 있습니다.

urllib.request에서도 검증 유지

표준 라이브러리에서는 ssl.create_default_context()로 기본 검증 컨텍스트를 만들고 필요한 CA 파일만 지정합니다.

import ssl
from urllib.request import urlopen

context = ssl.create_default_context(cafile="/path/to/company-ca-bundle.pem")
with urlopen("https://api.example.com/data", context=context, timeout=10) as response:
    print(response.read()[:100])

SSLContext를 직접 만들 때 인증서 검증과 호스트명 검사가 꺼지지 않았는지 확인합니다. urllib.request도 환경변수 프록시를 사용할 수 있으므로 프록시 설정을 함께 점검해야 합니다.

운영에 남길 판단 기준

저는 오류 전문에서 호스트명과 체인 검증 실패를 먼저 구분하고, 실행 환경의 CA 경로와 프록시 환경변수를 그다음에 봅니다. 검증된 사내 CA를 받은 경우에만 verify나 REQUESTS_CA_BUNDLE에 그 경로를 지정하고, verify=False를 상시 설정으로 남기지 않는 게 안전해요.

패키지를 재설치하기 전에 이 경계를 나누면 인증서 문제를 타임아웃이나 API 자체 오류로 잘못 분류하지 않고, 어느 환경 설정을 수정할지 결정하기 쉬워집니다.

참고 자료

Leave a Comment