회사 네트워크에서 개발하다 보면 이런 오류를 만납니다.
fetch failed
UNABLE_TO_VERIFY_LEAF_SIGNATURE
SELF_SIGNED_CERT_IN_CHAIN
CRYPT_E_NO_REVOCATION_CHECK
브라우저로는 같은 사이트가 멀쩡히 열리는데 npm install이나 wrangler deploy만 죽습니다. 왜 이런 차이가 나는지, 무엇을 건드려야 하고 무엇을 건드리면 안 되는지 정리했습니다.
왜 도구마다 다른가
많은 회사가 HTTPS 트래픽을 열어 보는 검사 장비를 씁니다. 원리는 중간에서 연결을 끊고 회사가 발급한 인증서로 다시 맺는 것입니다. 그래서 회사 루트 인증서를 신뢰하는 프로그램은 아무 문제가 없고, 자기만의 인증서 목록을 들고 다니는 프로그램은 전부 실패합니다.
윈도우에는 회사 인증서가 이미 설치돼 있는 경우가 많습니다. 그러면 이렇게 갈립니다.
| 도구 | 인증서 목록 | 회사망에서 |
|---|---|---|
| 브라우저, 파워셸, .NET | 윈도우 인증서 저장소 | 된다 |
Python requests | 상황에 따라 시스템 저장소 사용 | 대체로 된다 |
| Node.js (npm, wrangler, fetch) | 자체 번들 | 막힌다 |
| curl (schannel 아닌 빌드) | 자체 번들 | 막힌다 |
즉 "회사망이 막는다"가 아니라 "내 도구가 회사 인증서를 모른다"가 정확한 진단입니다.
정석은 인증서를 알려 주는 것입니다
Node라면 원래 이렇게 해결합니다.
$env:NODE_EXTRA_CA_CERTS="C:\path\to\corp-root.crt"
회사 루트 인증서를 파일로 받을 수 있다면 이게 정답입니다. 검증을 유지하면서 문제만 없앱니다. 먼저 IT에 인증서를 요청해 보시길 권합니다.
못 받으면, 그 명령에만 검증을 끕니다
인증서를 받을 수 없는 환경이라면 남는 선택지는 검증을 끄는 것뿐입니다. 다만 켜 두는 범위를 최소로 해야 합니다.
$env:NODE_TLS_REJECT_UNAUTHORIZED="0"; npx wrangler deploy
이렇게 그 명령을 실행하는 그 순간에만 켭니다. 하면 안 되는 것은 사용자 환경 변수로 영구 등록하는 것입니다. 그러면 그 PC의 모든 Node 프로그램이 앞으로 계속 인증서를 안 봅니다. 회사망 밖에서도, 회사와 무관한 프로젝트에서도요. 위조된 서버에 접속해도 알아챌 방법이 없어집니다.
git은 Node가 아니라 이 변수의 영향을 받지 않습니다. 윈도우에서 git이 폐기 검사에 걸리는 경우에는 더 약한 완화를 따로 씁니다.
git config --global http.schannelCheckRevoke false
이건 인증서 검증 자체를 끄는 게 아니라 폐기 여부 확인만 끄는 것이라 훨씬 좁습니다.
"인증서 문제"와 "차단"은 다릅니다
여기서 많이 헷갈립니다. 둘 다 연결이 안 되지만 원인이 정반대이고, 검증을 끄는 것이 도움이 되는 쪽은 하나뿐입니다.
구분하는 방법은 간단합니다. 검증을 끄고 한 번 더 해 보는 것입니다.
curl -sS -o /dev/null -w "%{http_code}\n" https://example.com/
curl -sS --insecure -o /dev/null -w "%{http_code}\n" https://example.com/
- 검증을 끄니 된다 → 인증서 문제입니다. 위의 방법으로 해결됩니다
- 검증을 꺼도 똑같이 안 된다 → 인증서와 무관하게 네트워크에서 막힌 것입니다. 이건 우회로 풀 수 없고 방화벽 담당에게 호스트 이름을 알려 줘야 합니다
실제로 저는 마이크로소프트 스토어가 아무 앱도 못 받는 문제를 이 방법으로 갈랐습니다. 카탈로그 서버는 응답하는데 다운로드 서버만 죽고 있었고, 검증을 꺼도 똑같았습니다. 인증서가 아니라 차단이었던 겁니다.
| 호스트 | 검증함 | 검증 생략 | 판정 |
|---|---|---|---|
| 카탈로그 서버 | 응답(404) | — | 정상 |
| 로그인 서버 | 응답(404) | — | 정상 |
| 다운로드 CDN | 연결 취소 | 연결 취소 | 차단 |
여기까지 재고 나서야 "TLS를 우회하면 되지 않을까"라는 방향이 애초에 답이 아니라는 것이 분명해졌습니다. 연결이 맺히지도 않는데 인증서를 검사할 일이 없으니까요.
AI 크롤러 차단과도 헷갈립니다
한 가지 더. 외부에서 사이트를 가져올 때 403이 떨어지면 사이트가 막힌 줄 알기 쉽습니다. 그런데 Cloudflare 같은 곳에는 AI 크롤러만 골라 막는 설정이 있습니다. 사용자 에이전트를 바꿔 가며 재 보면 갈립니다.
| 사용자 에이전트 | 응답 |
|---|---|
| ClaudeBot · GPTBot · Bytespider | 403 |
| AdsBot-Google | 200 |
| 일반 브라우저 · curl | 200 |
이렇게 나오면 사이트가 죽은 게 아니라 AI 크롤러 차단이 켜져 있는 것이고, 검색 엔진이나 광고 크롤러와는 상관이 없습니다.
요약
- 오류 메시지가 인증서 이야기를 하면 → IT에 회사 루트 인증서부터 요청
- 못 받으면 → 그 명령에만 검증을 끄고, 영구 설정은 하지 않는다
- 검증을 꺼도 안 되면 → 인증서가 아니라 차단이다. 호스트 이름을 들고 방화벽 담당에게
- 외부에서 403이 나오면 → 사용자 에이전트를 바꿔 가며 재 보고 AI 크롤러 차단인지 확인
이어서 읽을 것
회사망에서 막히는 일은 배포 쪽에서도 똑같이 나옵니다. 수집기가 실제로 도는 곳은 제 PC가 아니었습니다가 그 예입니다.