526 에러가 뜻하는 것
Cloudflare를 앞에 두면 HTTPS 요청은 두 구간으로 나뉩니다. 방문자의 브라우저에서 Cloudflare까지, 그리고 Cloudflare에서 내 서버(원 서버, origin)까지입니다. 구간마다 인증서가 따로 있습니다.
526 에러 “Invalid SSL certificate”는 두 번째 구간의 문제이고, SSL/TLS 모드가 Full (strict)일 때만 납니다. Cloudflare가 원 서버에 연결했고 TLS 핸드셰이크도 끝났는데, 원 서버가 내민 인증서를 검사해 보니 받아 줄 수 없었다는 뜻입니다. strict 모드에서 원 서버 인증서는 다음을 만족해야 합니다.
- 만료되지 않았을 것
- 공인 CA나 Cloudflare Origin CA가 발급했을 것
- 호스트명에 맞을 것. 방문자가 요청한 호스트명이나, 프록시된 CNAME이라면 그 대상 호스트명입니다.
하나라도 어긋나면 Cloudflare는 요청을 넘기지 않고 526을 보여 줍니다. 사설 CA 인증서를 쓰는 원 서버를 위해 Cloudflare가 Custom Origin Trust Store라는 기능도 제공하지만, 기대기 전에 내 요금제에 포함돼 있는지 확인하세요.
방문자 쪽 구간은 영향이 없습니다. 브라우저와 Cloudflare의 연결은 Cloudflare 엣지 인증서를 쓰기 때문에, 방문자는 브라우저 인증서 경고가 아니라 Cloudflare 오류 화면을 봅니다.
방문자라면
내 쪽에서 할 수 있는 것은 없고, 이 오류가 나에게 사이트가 위험하다는 신호도 아닙니다. 거부된 인증서는 Cloudflare 뒤에 있는 사이트 서버의 것입니다. 잠시 후 다시 시도하거나, 운영자에게 오류가 난 시각과 오류 화면 아래쪽의 Ray ID를 알려 주세요.
526이 아니라 NET::ERR_CERT_AUTHORITY_INVALID나 “연결이 비공개로 설정되어 있지 않습니다” 같은 브라우저 경고가 보인다면 다른 문제입니다. ERR_CERT_AUTHORITY_INVALID를 보세요.
어떤 Cloudflare 에러인가
52x 코드는 Cloudflare와 원 서버의 연결이 어디까지 갔는지를 알려 줍니다.
| 코드 | 멈춘 곳 |
|---|---|
| 521 | 원 서버가 TCP 연결을 거부함(듣고 있는 프로그램이 없거나 방화벽이 거부) |
| 522 | TCP 연결 시간 초과(패킷이 버려지거나, 원 서버에 닿지 않거나, 과부하) |
| 525 | TCP 연결은 됐지만 TLS 핸드셰이크가 실패함 |
| 526 | 핸드셰이크는 끝났지만 Full (strict)에서 원 서버 인증서가 유효하지 않음 |
| 520 | 연결은 됐지만 원 서버의 응답이 비어 있거나 Cloudflare가 해석할 수 없음 |
오류 화면의 문장이 아니라 숫자를 보세요. 525와 526은 둘 다 원 서버와의 ‘SSL’ 문제로 설명되지만 고칠 곳이 다릅니다. 525라면 Cloudflare 525 에러를 보세요.
알아 두면 쓸모 있는 점이 하나 있습니다. Full과 Flexible은 원 서버 인증서를 검증하지 않으므로 526이 날 수 없습니다. 그래서 원 서버 인증서가 몇 달 전에 만료됐는데도, 누군가 존을 strict로 바꾼 날에야 발견하는 일이 흔합니다.
Cloudflare가 보는 인증서를 직접 보기
원 서버의 실제 IP가 필요합니다. Cloudflare DNS 대시보드의 A 또는 AAAA 레코드 값입니다. 프록시를 켠 레코드는 공개 DNS에서 Cloudflare 주소만 나옵니다.
그 IP에 연결하면서 Cloudflare처럼 SNI로 내 호스트명을 보내고, OpenSSL에게 검증을 맡깁니다.
openssl s_client -connect 203.0.113.10:443 -servername www.example.com \
-verify_hostname www.example.com </dev/null 2>/dev/null | grep -E 'subject=|issuer=|Verify return code'
subject=CN = www.example.com
issuer=C = US, O = Let's Encrypt, CN = R11
Verify return code: 10 (certificate has expired)
Verify return code: 0 (ok)는 일반적인 클라이언트가 그 이름으로 이 인증서를 받아 준다는 뜻입니다. 다른 값이면 실패 이유를 알려 줍니다.
| Verify return code | 뜻 | 아래 원인 |
|---|---|---|
| 10 (certificate has expired) | notAfter 날짜가 지남 | 1 |
| 18 (self-signed certificate) | 뒤에 CA가 없음 | 2 |
| 19 (self-signed certificate in certificate chain) | 아무도 신뢰하지 않는 루트로 체인이 끝남 | 2 |
| 20 (unable to get local issuer certificate) | 발급자를 모름. 중간 인증서 누락인 경우가 많음 | 4 |
| 21 (unable to verify the first certificate) | leaf에서 체인을 만들지 못함. 대개 중간 인증서 누락 | 4 |
| 62 (hostname mismatch) | 그 이름이 인증서에 없음 | 3 |
오래된 OpenSSL은 18, 19를 하이픈 없이 “self signed”로 표기합니다. 원 서버가 Cloudflare Origin CA 인증서를 쓴다면 내 컴퓨터는 그 CA를 모르므로 20이나 21을 냅니다. 정상입니다. Cloudflare 문서에서 Origin CA 루트 인증서(내 인증서에 맞춰 RSA 또는 ECC)를 내려받아 -CAfile로 넘기면 만료와 이름 문제만 남습니다.
날짜와 이름을 한 번에 보려면 이렇게 합니다.
openssl s_client -connect 203.0.113.10:443 -servername www.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
curl -v --resolve www.example.com:443:203.0.113.10 https://www.example.com/도 같은 검사를 하고, SSL certificate problem: certificate has expired처럼 읽기 쉬운 오류로 멈춥니다.
원 서버에 프록시를 거치지 않는(DNS 전용) 호스트명이 있다면 SSL 점검으로 바깥에서 그 인증서의 만료일과 체인을 볼 수 있습니다. 프록시된 호스트명에서는 Cloudflare 엣지 인증서가 나오는데, 그것은 526의 원인이 아닙니다.
흔한 원인
1. 인증서가 만료됨
526의 압도적인 1위입니다. 원 서버 인증서의 유효 기간이 끝났습니다. 대개 어느 시점에 자동 갱신이 깨졌는데 아무도 몰랐던 것입니다. Cloudflare 뒤에서는 세 가지 경로가 흔합니다.
- 갱신은 됐는데 서버를 리로드하지 않음. certbot은 디스크에 새 인증서를 썼지만 nginx는 메모리에 있는 옛 인증서를 계속 내놓습니다. 디스크의 날짜(
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -enddate)와 s_client에 나오는 날짜를 비교해 보세요. deploy hook으로 영구히 고칩니다.certbot renew --deploy-hook "systemctl reload nginx". - Cloudflare 때문에 갱신이 실패함. HTTP-01 검증 요청은 프록시를 거칩니다. “Always Use HTTPS”가 켜져 있고 원 서버 인증서가 이미 만료됐다면, 검증 요청은 엣지에서 HTTPS로 리다이렉트되고, Cloudflare는 strict 모드로 원 서버에서 그것을 가져오려다 526을 돌려줍니다. 인증서가 한 번 만료되면 갱신이 스스로 회복하지 못합니다. 원 서버를 거치지 않는 DNS-01 방식으로 바꾸세요(certbot에 Cloudflare DNS 플러그인이 있습니다).
- 타이머가 돌지 않음.
systemctl list-timers | grep -i certbot과sudo certbot renew --dry-run으로 확인하세요.
2. 자체 서명이거나 사설 CA 인증서
새로 만든 서버에서 흔합니다. Debian·Ubuntu가 만드는 snakeoil 인증서(/etc/ssl/certs/ssl-cert-snakeoil.pem), 호스팅 관리 화면의 기본 인증서, “일단 HTTPS가 되게” openssl req -x509로 만든 인증서, 회사 내부 CA가 발급한 인증서 같은 것들입니다. Full은 이것을 모두 받아 주고, Full (strict)는 하나도 받아 주지 않습니다.
해결: Cloudflare Origin CA 인증서(SSL/TLS → Origin Server → Create Certificate)나 Let’s Encrypt 인증서를 설치하세요. 내부 CA를 계속 쓰고 싶다면 요금제에 있을 경우 Custom Origin Trust Store를 쓰면 됩니다.
3. 인증서에 그 이름이 없음
인증서 자체는 유효한데, Cloudflare가 요청한 호스트명용이 아닙니다.
example.com만 커버하는데 요청은www.example.com이거나, 그 반대.- 와일드카드
*.example.com은www.example.com은 커버하지만example.com과a.b.example.com은 커버하지 않음. - 원 서버에 이 호스트명의 server 블록이 없어서 기본 설정으로 넘어가고, 다른 사이트의 인증서를 내놓음. Cloudflare에 새 서브도메인을 추가하고 원 서버
server_name에는 넣지 않았을 때 흔합니다. - 인증서가
origin.example.com처럼 원 서버 자기 이름용인데 방문자는www.example.com을 씀.
해결: 프록시를 거치는 모든 이름을 넣어 인증서를 다시 발급하거나(certbot --expand -d example.com -d www.example.com), example.com과 *.example.com으로 Origin CA 인증서를 만들고, 호스트명마다 server 블록이 있는지 확인하세요. 와일드카드 규칙은 브라우저와 같습니다. ERR_CERT_COMMON_NAME_INVALID를 참고하세요.
4. 체인이 불완전함
원 서버가 자기 인증서만 보내고, 그것을 신뢰할 수 있는 루트까지 이어 주는 중간 인증서는 보내지 않습니다. 브라우저는 빠진 중간 인증서를 스스로 받아 와서 넘어가 주기도 하지만, Cloudflare의 검증도 그렇게 해 주리라 기대하면 안 됩니다. 전체 체인을 보내세요.
전형적인 실수는 nginx ssl_certificate가 certbot의 fullchain.pem이 아니라 cert.pem을 가리키는 것, Apache 설정에서 체인 파일이 빠진 것, 상용 인증서를 설치하면서 업체가 함께 보내 준 CA 번들을 빠뜨린 것입니다. nginx가 실제로 읽는 파일은 sudo nginx -T | grep -E 'ssl_certificate'로 확인하세요. 자세한 내용은 인증서 체인 문제에 있습니다.
5. 호스트명 하나나 원 서버 하나만 실패함
사이트 대부분은 되는데 서브도메인 하나만 526이라면, 그 호스트명이 자기 인증서를 쓰는 다른 서버를 가리키거나 SSL 모드가 따로 걸려 있는 것입니다. Configuration Rule이나 예전 Page Rule로 존은 Full인 채로 호스트명 하나만 Full (strict)로 설정할 수 있습니다.
같은 URL에서 526이 났다 안 났다 한다면 뒤에 원 서버가 여러 대 있고(프록시된 A 레코드 여러 개, 로드밸런서 풀) 그중 하나의 인증서가 잘못된 것입니다. 원 서버 IP마다 s_client 명령을 돌려 보세요.
SaaS 플랫폼을 가리키는 프록시된 CNAME은 특수한 경우입니다. 인증서는 플랫폼이 내놓는데, 일부 플랫폼은 레코드가 프록시를 거치는 동안 내 커스텀 도메인용 인증서를 발급하지 못합니다. 그 플랫폼의 Cloudflare 연동 문서를 확인하세요.
임시방편: Flexible이 아니라 Full
사이트가 내려가 있는데 인증서를 고치는 데 시간이 걸린다면, 존 전체나 Configuration Rule로 그 호스트명만 Full로 바꾸면 바로 살아납니다. 원 서버 구간은 계속 암호화되고, Cloudflare가 상대가 누구인지 확인하는 것만 멈춥니다. 어딘가에 알림을 걸어 두고, 인증서를 고치면 되돌리세요.
Flexible로는 가지 마세요. 원 서버로 가는 트래픽이 암호화되지 않고, 원 서버가 HTTP를 HTTPS로 리다이렉트한다면 526이 리다이렉트 루프로 바뀔 뿐입니다. 선택지는 Cloudflare SSL 모드에서 비교합니다.
다시 깨지기 어려운 해결
항상 프록시를 거칠 사이트라면 Origin CA 인증서가 가장 손이 덜 갑니다. example.com과 *.example.com으로 긴 유효 기간(최대 15년)을 골라 만들고, 원 서버에 인증서와 키를 설치하고, 웹 서버를 리로드하고, s_client와 Cloudflare Origin CA 루트로 확인한 뒤 Full (strict)로 바꾸면 됩니다. 같은 단계를 525 가이드에서도 설명합니다.
그 호스트명을 언젠가 DNS 전용으로 돌릴 수도 있거나, Cloudflare 밖의 무언가가 원 서버를 직접 검사한다면 DNS-01로 갱신하는 Let’s Encrypt를 쓰세요. 어느 쪽이든 원 서버 인증서 만료일을 누군가의 달력이나 모니터링에 올려 두세요. 자세한 내용은 SSL 만료 체크리스트에 있습니다.
고친 다음에
- 페이지를 새로고침하세요. 오류 화면마다 새 Ray ID가 붙으므로, 새 Ray ID로 526이 또 나온다면 Cloudflare가 아직 인증서를 거부하고 있는 것입니다.
- 신고된 호스트명 하나만이 아니라 프록시를 거치는 모든 호스트명에
-verify_hostname을 넣은 openssl 검사를 돌리세요. - 공개 호스트명에 SSL 점검을 돌려 방문자 쪽 인증서도 정상인지 확인하세요.
비슷해 보이는 다른 오류
- Cloudflare 525 에러: 인증서 검사 전에 원 서버와의 TLS 핸드셰이크가 실패합니다.
- Cloudflare 522 에러: Cloudflare가 원 서버에 아예 닿지 못합니다.
- Cloudflare SSL 모드: Off, Flexible, Full, Full (strict) 비교.
- 인증서 체인 문제: 중간 인증서가 빠지거나 잘못된 경우.
내 도메인에서 바로 확인
무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.