NET::ERR_CERT_COMMON_NAME_INVALID 원인별 해결 — 도메인과 인증서가 안 맞을 때
NET::ERR_CERT_COMMON_NAME_INVALID 는 이름과 달리 Common Name 을 보는 에러가 아니다.
Chrome 은 인증서의 Common Name 을 보지 않은 지 오래다. 이 에러가 말하는 것은 하나다 —
서버가 내민 인증서의 SAN(subjectAltName) 목록에 주소창의 이름이 없다.
발급자가 믿을 만한지와는 별개다. 공인 CA 가 발급한 멀쩡한 인증서여도 이름이 안 맞으면
이 화면이 뜬다. 그래서 AUTHORITY_INVALID 와 달리 원인이 대개 서버 쪽에 있다.
인증서의 이름 목록이 틀렸거나, 서버가 맞는 인증서를 두고 엉뚱한 인증서를 내보내고
있거나.
에러의 정체
Chrome 내부 코드는 -200 이다. 바로 옆 번호들과 함께 보면 이렇다.
| 에러 코드 | 번호 | 의미 |
|---|---|---|
ERR_CERT_COMMON_NAME_INVALID |
-200 | 접속한 이름이 인증서에 없음 |
ERR_CERT_DATE_INVALID |
-201 | 유효기간 밖 |
ERR_CERT_AUTHORITY_INVALID |
-202 | 신뢰 경로를 못 만듦 |
-202 와 헷갈린다면 NET::ERR_CERT_AUTHORITY_INVALID 원인별 해결 의 구분표부터 본다.
Chromium 소스의 이 에러 정의에는 원인 후보 네 가지가 주석으로 달려 있다.
- 공격자가 트래픽을 다른 곳으로 돌렸다
- 서버 설정이 잘못돼 엉뚱한 인증서로 응답한다
- 무선망 로그인 페이지(캡티브 포털)로 끌려갔다
- OS 가 DNS 검색 접미사를 붙였는데, 서버에 주소창의 짧은 이름용 인증서가 없다
서버 운영자가 고칠 수 있는 건 2번과 4번이다. 3번은 호텔·카페 와이파이에서 망 로그인 전에 HTTPS 사이트를 열 때 나온다. 망 로그인을 마친 뒤 다시 열어 본다.
경고 화면이 이미 답의 절반을 준다
경고 화면의 상세 문구는 이렇다(영문 UI 기준).
This server could not prove that it is www.example.com;
its security certificate is from example.com.
앞은 주소창의 이름, 뒤는 서버가 실제로 내민 인증서의 이름 중 대표 하나(CN 과 같은 SAN, 없으면 첫 번째 SAN)다. 뒤쪽 이름을 보면 방향이 잡힌다.
- 우리 도메인의 변형(
example.com↔www.example.com) → 인증서의 이름 누락 - 전혀 모르는 이름(호스팅 플랫폼 기본 도메인, 같은 서버의 다른 사이트) → 서버가 엉뚱한 인증서를 내보내는 중
인증서에 DNS SAN 이 아예 없으면 문구가 달라진다.
This server could not prove that it is www.example.com;
its security certificate does not specify Subject Alternative Names.
이 문구면 CN 전용 인증서다(원인 2).
30초 판별 — SAN 목록을 직접 본다
OpenSSL 1.1.1 이상이 필요하다. macOS 기본 /usr/bin/openssl 은 LibreSSL 이라 -ext 를
지원하지 않는다. Homebrew 의 openssl@3 를 쓴다.
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -ext subjectAltName
-connect 와 -servername 에 모두 주소창에 친 이름을 그대로 넣는다. -servername
은 브라우저가 SNI 로 보내는 값이고, -connect 에도 같은 이름을 줘야 DNS 로 브라우저가
실제로 가는 IP 에 붙는다. www 와 apex 가 서로 다른 서버(CDN·원서버)를 가리키는 구성이면
이름이 하나만 달라도 엉뚱한 서버를 검사하게 된다.
단, 주소창이 IP 면 -servername 을 빼고 -connect IP:443 만 쓴다(원인 4).
subject=CN=example.com
X509v3 Subject Alternative Name:
DNS:example.com
OpenSSL 3.1 이하에서는 subject=CN = example.com 처럼 = 앞뒤에 공백이 붙는다.
읽는 법:
| SAN 출력 | 원인 |
|---|---|
www 와 apex 중 한쪽만 있음 |
이름 누락 (원인 1) |
SAN 줄이 없음, No extensions in certificate(1.1.1 은 No extensions matched with subjectAltName) |
CN 전용 인증서 (원인 2) |
*.example.com 뿐인데 접속은 example.com·a.b.example.com |
와일드카드 범위 밖 (원인 3) |
w*.example.com, *.intranet 같은 형태 |
Chrome 이 거부하는 와일드카드 (원인 3) |
IP 로 접속했는데 IP Address: 항목이 없음 |
IP 접속 (원인 4) |
| 전혀 다른 도메인 | 기본 인증서 응답 (원인 5·6) |
| 접속한 이름이 있음 | 여기서는 정상. 실패하는 PC 의 DNS·망, 또는 주소창의 이름을 본다 (원인 7) |
함정 — OpenSSL·curl 은 Chrome 보다 관대하다
호스트명 검사 옵션으로 한 번에 끝내고 싶어진다. OpenSSL 에는 두 가지가 있다.
# 파일로 받은 인증서 검사
openssl x509 -in cert.pem -noout -checkhost www.example.com
# 핸드셰이크 중 검사
openssl s_client -connect www.example.com:443 -servername www.example.com \
-verify_hostname www.example.com -verify_return_error -brief </dev/null
불일치면 verify error:num=62:hostname mismatch, 일치하면
Verified peername: www.example.com 이 나온다. 단 공인 인증서일 때 얘기다. 사설 CA·자체
서명이면 체인 검증이 먼저 실패해 num=18(self-signed)·19·20 에서 끝나고 이름 판정까지
가지 않는다. -CAfile <루트.pem> 을 함께 줘야 62 여부가 나온다.
이 결과를 Chrome 결과로 읽으면 안 된다. OpenSSL 의 호스트명 검사는 기본값에서 세 가지를 Chrome 보다 느슨하게 본다.
- CN 폴백 — DNS 타입 SAN 이 하나도 없으면(IP SAN 만 있어도) subject 의 CN 을 본다. OpenSSL 백엔드 curl 도 SAN(dNSName·iPAddress)이 둘 다 없으면 CN 으로 폴백한다
- 부분 와일드카드 —
w*.example.com이www.example.com에 맞는다고 판정한다. curl 은 부분 와일드카드를 거부한다 - 공개 접미사 —
*.co.uk가example.co.uk에 맞는다고 판정한다(Chrome 은 거부)
그래서 CN 전용 인증서를 검사하면 이런 결과가 나온다.
$ openssl x509 -in cn-only.pem -noout -checkhost www.example.com
Hostname www.example.com does match certificate
$ openssl x509 -in cn-only.pem -noout -ext subjectAltName
No extensions in certificate
OpenSSL 은 맞다고 하고, Chrome 은 -200 을 낸다. 최종 판단은 -ext subjectAltName
출력으로 한다. 접속 이름이 SAN 에 글자 그대로 있거나, 왼쪽 첫 레이블 전체가 * 인
와일드카드로 덮여야 Chrome 기준으로 통과다.
원인 1 — SAN 에 그 이름이 없다 (www vs apex)
가장 흔하다. example.com 으로만 받은 인증서에 www.example.com 으로 들어오거나, 그
반대다. 서브도메인을 새로 열면서 인증서에 넣는 걸 잊은 경우도 같다.
Let’s Encrypt 라면 인증서별 이름 목록부터 본다.
sudo certbot certificates
Certificate Name: example.com
...
Identifiers: example.com
Certbot 5.1 이하는 이 줄이 Domains: 로 나온다. Identifiers(구버전 Domains)에 빠진
이름이 있으면 같은 인증서 이름으로 목록을 다시 지정한다.
sudo certbot certonly --cert-name example.com -d example.com,www.example.com
sudo systemctl reload nginx # apache 면 apache2
-d 는 기존 목록에 더하는 게 아니라 목록 전체를 새로 지정한다. 기존 이름도 빠짐없이
다시 적는다. 빠뜨린 이름은 새 인증서에서 사라진다.
certonly 는 인증서 파일만 바꾼다. 웹서버를 reload 하기 전까지는 옛 인증서가 계속
나가므로 “재발급했는데 그대로”로 오진하기 쉽다. 갱신 때마다 자동으로 하려면
--deploy-hook "systemctl reload nginx" 를 붙인다.
상용 CA 인증서도 원리는 같다. 인증서는 서명된 문서라 SAN 만 고칠 수 없다. 두 이름을 모두 넣어 새로 발급받는다. 발급 절차는 인증서 발급 공통 가이드에 있다.
Chrome 이 이 문제를 가려 준다
www·apex 누락은 Chrome 에서 안 보일 때가 있다. Chrome 은 아래 조건이 모두 맞으면 경고 화면 대신 다른 URL 로 조용히 이동한다.
- 에러가 이름 불일치 하나뿐이고, HSTS 등으로 경고 우회가 막힌 상태가 아니다
- 인증서 SAN 에 주소창 이름에서
www를 붙이거나 뗀 이름이 있다 - 그 이름의 같은 경로 URL 에 보낸 HEAD 요청이 3초 안에 HTTPS 200 으로 응답한다 (301·302 리다이렉트면 해당 없음)
www.example.com 인증서만 있는 서버에 https://example.com 으로 들어가면 경고 없이
www 로 넘어간다. 주소창이 www 로 바뀌고, 이유는 개발자 도구 콘솔에 남는다.
Redirecting navigation example.com -> www.example.com because the server
presented a certificate valid for www.example.com but not for example.com.
그래서 “Chrome 에서는 되는데 curl·앱·서버 간 API 호출에서만 실패” 하는 사례가 생긴다. 다른 클라이언트는 이런 보정을 하지 않는다. curl(OpenSSL 백엔드)은 이렇게 끝난다.
curl: (60) SSL: no alternative certificate subject name matches target hostname 'example.com'
curl 8.8 이하는 target host name 으로 나오고, Windows 기본 curl(Schannel)은
SEC_E_WRONG_PRINCIPAL 처럼 문구가 아예 다르다.
Chrome 에서 열린다고 인증서가 맞는 게 아니다. 판별은 항상 위의 openssl 명령으로 한다.
원인 2 — CN 에만 있고 SAN 에 없다
-ext subjectAltName 에 아무것도 안 나오고 subject 의 CN 에만 도메인이 있는
인증서다. CN 이 접속 이름과 글자 하나 안 틀리고 같아도 Chrome 에서는 실패한다.
현재 Chrome 의 호스트명 검증은 SAN 의 dNSName·iPAddress 가 하나도 없으면 CN 을 열어 보지도 않고 바로 실패한다. Chrome 58(데스크톱 stable 2017년 4월 19일)에서 CN 매칭을 제거한 결과다. 갑작스러운 변경은 아니었다.
| 시점 | 문서·제품 | 내용 |
|---|---|---|
| 2000 | RFC 2818 | dNSName SAN 이 있으면 그것을 쓰고, 없을 때만 CN. CN 사용은 deprecated |
| 2012~ | CA/B Forum Baseline Requirements | 공인 인증서에 SAN 필수 |
| 2017 | Chrome 58 | CN 매칭 제거 |
| 2023 | RFC 9525 | RFC 6125 대체. CN 으로 서비스를 식별하면 안 된다(MUST NOT) |
Firefox 도 Firefox 48 부터 새 공인 인증서에 SAN 을 요구했다.
제거를 예고할 당시 Chrome 팀 집계로, 공인 인증서 검증의 0.002% 미만, 사설 CA 인증서의 1.57%(전체 검증 대비 0.1%)가 CN 폴백에 기대고 있었다. 공인 CA 는 BR 상 SAN 없이 발급할 수 없으므로, 지금 CN 전용 인증서가 나오는 곳은 사설 CA 와 자체 서명 쪽이다. 오래된 스크립트로 만든 내부 인증서, 장비 관리 페이지 인증서가 대표적이다.
처리 — SAN 을 넣어 다시 발급한다. OpenSSL 로 CSR 을 만든다면 -addext 로 넣는다.
openssl req -new -newkey rsa:2048 -nodes -keyout app.key -out app.csr \
-subj "/CN=app.corp.example.com" \
-addext "subjectAltName=DNS:app.corp.example.com"
-nodes 는 OpenSSL 3.0 부터 deprecated 이고 -noenc 가 대체다. 동작은 같다.
- 사설 CA 가 CSR 의 SAN 을 그대로 반영하는지는 CA 설정에 따라 다르다. 발급된 인증서에서
-ext subjectAltName을 반드시 다시 확인한다 - 자체 서명이면 같은 명령에
-x509 -days 365를 붙인다. CSR 대신 SAN 이 들어간 인증서가 바로 나온다(-out파일명은 바꿔 둔다).-days를 빼면 기본 30일이라 한 달 뒤DATE_INVALID로 다시 깨진다 - CN 은 남겨도 된다. BR 은 CN 을 NOT RECOMMENDED 로 두고, 넣는다면 SAN 값 중 하나를 그대로 써야 한다고 정한다. 검증에는 쓰이지 않는다
원인 3 — 와일드카드: Chrome 은 RFC 보다 엄격하다
apex 를 안 덮는다, 한 단계만 덮는다 — 기본 규칙은 와일드카드 vs SAN 인증서, 언제 무엇을 쓰나에서 다뤘다. 여기서는 인증서는 만들어지는데 Chrome 에서만 막히는 형태를 본다.
Chrome 의 와일드카드 규칙은 짧다. 왼쪽 첫 레이블 전체가 정확히 * 일 때만 인정하고,
나머지 부분은 글자 그대로 일치해야 한다.
| SAN 값 | 접속 이름 | Chrome |
|---|---|---|
*.example.com |
www.example.com |
✅ |
*.corp.example.com |
wiki.corp.example.com |
✅ |
*.example.com |
example.com |
❌ apex 미포함 |
*.example.com |
a.b.example.com |
❌ 한 단계만 |
w*.example.com |
www.example.com |
❌ 부분 와일드카드 |
*.co.uk |
example.co.uk |
❌ 공개 접미사 |
*.intranet |
wiki.intranet |
❌ 미등록 TLD |
부분 와일드카드. w*.example.com 같은 형태는 RFC 2818 이 허용했다(f*.com 이
foo.com 에 맞는다는 예시까지 있다). RFC 6125(2011)는 왼쪽 첫 레이블이 아닌 곳의
와일드카드는 SHOULD NOT 으로 막았지만, 첫 레이블 안의 부분 와일드카드(baz*.example.net)는
여전히 MAY 로 허용했다. 이를 대체한 RFC 9525 §6.3 에서 비로소 금지됐다.
- 와일드카드 문자는 하나뿐이다
- 왼쪽 첫 레이블의 전체 내용으로만 나타난다
- 레이블 하나만 매칭한다
부분 와일드카드를 막는 점에서 Chrome 은 이 규칙과 같고, 아래 제약을 더 얹는다. 반면 OpenSSL 은 기본값에서 아직 부분 와일드카드를 받아 준다. OpenSSL 통과를 믿으면 안 되는 두 번째 이유다.
공개 접미사와 미등록 TLD. Chrome 은 공개 레지스트리 도메인(*.com, *.co.uk)에
대한 와일드카드를 인정하지 않는다(OpenSSL 은 *.co.uk 도 통과시킨다). 레지스트리
데이터셋에 없는 TLD(사내에서 쓰는 intranet 같은 이름)는 그 마지막 레이블을 레지스트리로
취급하므로 *.intranet 처럼 TLD 바로 아래 와일드카드가 막힌다. *.corp.intranet 처럼 한
단계 아래면 Chrome 도 받아 준다. 숫자로만 된 호스트명과 점이 없는 단일 레이블 이름에도
와일드카드 매칭을 하지 않는다.
공인 CA 는 이런 인증서를 애초에 못 낸다. BR 이 *.co.uk, *.local 같은 발급을 금지한다.
BR 의 와일드카드 도메인명 정의도 *. 바로 뒤에 FQDN 이 오는 형태뿐이라 w*. 같은 부분
와일드카드는 공인 인증서에 들어갈 자리가 없다. 그래서 표의 아래쪽 행들은 사설 CA 로 사내 도메인 전체를 와일드카드 하나로 덮으려 할 때
나온다. 사내 전용 TLD 를 쓰고 있다면 호스트 이름을 SAN 에 나열하거나, 한 단계 아래
와일드카드를 쓴다. 다만 미등록 TLD 는 나중에 공개 TLD 와 이름이 겹칠 위험이 있으니 실제로
소유한 도메인 아래(*.corp.example.com)로 옮기는 편이 낫다.
원인 4 — IP 주소로 접속
https://203.0.113.10/ 처럼 IP 로 들어가면 규칙이 달라진다.
- Chrome 은 IP 로 접속하면 SAN 의 iPAddress 항목만 비교한다. dNSName 에
203.0.113.10이라는 문자열을 넣어도 매칭되지 않는다 - SNI 에는 IP 를 넣을 수 없다(RFC 6066). 서버는 어떤 이름으로 들어왔는지 모른 채 기본 인증서를 준다
그래서 IP 접속은 거의 항상 엉뚱한 인증서를 받는다. 직접 확인할 수 있다.
openssl s_client -connect 203.0.113.10:443 </dev/null 2>/dev/null \
| openssl x509 -noout -subject -ext subjectAltName
s_client 는 -connect 가 IP 면 SNI 를 보내지 않는다. 브라우저의 IP 접속과 같은
조건이다. 인증서 파일이 있다면 IP 매칭만 따로 검사한다.
openssl x509 -in cert.pem -noout -checkip 203.0.113.10
처리
- 가장 간단한 건 이름으로 접속하게 하는 것이다. 모니터링 대상, 연동 설정, 북마크에 IP 가 박혀 있지 않은지 본다
- IP 접속이 꼭 필요하면 iPAddress SAN 이 든 인증서를 쓴다. 사설 CA 라면 CSR 에
-addext "subjectAltName=IP:203.0.113.10"식으로 넣는다 - 공인 인증서도 선택지가 됐다. Let’s Encrypt 는 2026년 1월 15일부터 IP 주소 인증서를 정식 제공한다. 다만 IP 인증서는 shortlived 프로필(유효기간 160시간, 6일 남짓) 로만 나온다. 자동 갱신이 멈추면 일주일 안에 만료된다. 만료 감시 없이 쓰면 안 된다 — SSL 인증서 만료일 확인하는 방법
원인 5 — SNI 없이 들어온 요청: 기본 vhost 인증서
한 서버에 여러 도메인이 올라가 있으면, 서버는 TLS 핸드셰이크의 SNI 를 보고 줄 인증서를 고른다. TLS 연결은 HTTP 요청(Host 헤더)보다 먼저 맺어지므로 SNI 가 유일한 단서다.
SNI 가 없거나, SNI 이름과 맞는 server 블록이 없으면 nginx 는 그 listen 의 default
server 인증서를 준다. 증상은 이렇게 나온다.
- 새 도메인의
server_name에 오타가 있다 → 기본 사이트의 인증서가 나간다 - SNI 를 안 보내는 구형·특수 클라이언트만 실패한다. 브라우저는 멀쩡하다
SNI 를 끄고 재현한다.
openssl s_client -connect example.com:443 -noservername </dev/null 2>/dev/null \
| openssl x509 -noout -subject -ext subjectAltName
여기서 우리 도메인이 아닌 인증서가 나오면 SNI 에 기대는 구성이다. CDN·호스팅 위의 사이트는 SNI 없이 붙으면 플랫폼 기본 인증서가 오거나 연결이 끊기는 경우가 흔하다. 한 CDN 문서는 SNI 로 도메인을 정하지 못하면 연결을 끊는다고 적는다.
테스트 도구 버전도 본다. s_client 는 OpenSSL 1.1.1 부터 -servername 을 안 줘도
-connect 의 이름을 SNI 로 보낸다. 그보다 오래된 OpenSSL 로 -servername 없이
테스트하면 SNI 없이 붙어서 멀쩡한 서버를 오진한다.
nginx 빌드의 SNI 지원 여부:
nginx -V 2>&1 | grep -i 'TLS SNI support'
# TLS SNI support enabled
처리
server_name과 인증서 SAN 이 짝이 맞는지 본다.-connect·-servername을 도메인마다 바꿔 가며 30초 판별 명령을 돌리면 어느 이름이 기본 인증서로 떨어지는지 보인다- 기본 server 가 엉뚱한 인증서를 주는 것 자체를 막을 수 있다. nginx 1.19.4 부터
ssl_reject_handshake가 있다
server {
listen 443 ssl default_server;
ssl_reject_handshake on;
}
기존 server 블록에 이미 default_server 가 있으면 duplicate default server 오류로 설정
로드가 실패하니 그쪽을 떼고 추가한다. IPv6 로도 listen 한다면
listen [::]:443 ssl default_server; 를 같은 블록에 함께 넣는다.
SNI 가 어떤 server_name 과도 안 맞으면 다른 사이트 인증서를 내미는 대신 핸드셰이크를
거부한다. 사용자는 이름 불일치 경고 대신 명확한 연결 실패를 보고, 다른 도메인 이름이
인증서로 노출되지도 않는다. 대신 SNI 를 안 보내는 클라이언트는 확실히 끊긴다. 그런
클라이언트가 없는지 먼저 확인한다. nginx 설정 전반은 Nginx 가이드.
원인 6 — CDN·호스팅에 커스텀 도메인이 안 붙었다
경고 화면 뒤쪽 이름이 *.<플랫폼 기본 도메인> 형태면 여기다. CDN·정적 호스팅은 자기
기본 도메인용 와일드카드 인증서를 기본으로 내보내고, 커스텀 도메인용 인증서는 연결
설정을 마쳐야 나간다.
흔한 경로:
- DNS 의 CNAME 은 이미 CDN 을 가리키는데, CDN 쪽에 대체 도메인 등록이나 인증서 연결을 안 했다
- CDN 에 붙인 인증서가 그 도메인을 SAN 으로 덮지 못한다. 주요 CDN 문서도 대체 도메인을
추가하려면 그 이름을 SAN 으로 덮는 인증서가 필요하다고 명시하고,
*.example.com으로는example.com이나marketing.product.example.com을 추가할 수 없다고 적는다 - SNI 를 안 보내는 클라이언트다. CDN 도 원인 5 와 같은 이유로 플랫폼 기본 인증서를 주거나 연결을 끊는다
- 정적 호스팅에 커스텀 도메인을 막 연결했다. 한 호스팅 서비스 문서는 HTTPS 가 붙기까지 최대 1시간이 걸릴 수 있고, DNS 를 바꾼 뒤에는 커스텀 도메인을 지웠다 다시 추가해야 인증서 발급이 시작될 수 있다고 안내한다
DNS 를 전환하기 전에 새 엣지가 이 이름에 맞는 인증서를 주는지 확인한다. --resolve
는 DNS 를 거치지 않고 지정한 IP 에 이 이름으로 붙는다.
curl -sSv -o /dev/null --resolve www.example.com:443:203.0.113.10 https://www.example.com/
불일치면 curl: (60) SSL: no alternative certificate subject name matches target hostname
으로 끝난다(원인 1 의 버전·백엔드별 문구 차이 참고). -S 를 빼고 -s 만 주면 이 마지막
에러 줄이 숨고 종료 코드 60 만 남는다. 전환 뒤 사용자 브라우저에서 알게 되는 것보다 훨씬 싸다.
원인 7 — 사내 단축 호스트명
사내에서 주소창에 wiki 만 치고 들어가는 경우다. OS 가 DNS 검색 접미사
(corp.example.com)를 붙여 wiki.corp.example.com 으로 찾아가므로 서버에는 잘
닿는다. 하지만 Chrome 이 인증서와 비교하는 건 주소창의 이름 wiki 다. 인증서에
wiki.corp.example.com 만 있으면 -200 이다. Chromium 주석의 4번 원인이 정확히 이 경우다.
공인 인증서로는 풀 수 없다. BR 은 IANA 루트존에 등록된 TLD 로 끝나지 않는 이름
(Internal Name)이 든 인증서 발급을 금지한다. wiki 같은 단일 레이블 이름은 공인 CA 가
넣어 주지 않는다.
처리
- FQDN 으로 접속하게 한다 — 사내 포털 링크·북마크·문서의 주소를
https://wiki.corp.example.com/으로 정리한다. 이 경우 공인 인증서도 쓸 수 있다 - 단축 이름도 살려야 하면 사설 CA 로 SAN 에 둘 다 넣는다
openssl req -new -newkey rsa:2048 -nodes -keyout wiki.key -out wiki.csr \
-subj "/CN=wiki.corp.example.com" \
-addext "subjectAltName=DNS:wiki.corp.example.com,DNS:wiki"
단일 레이블 이름은 와일드카드로 덮을 수 없으니(원인 3) 이름마다 SAN 에 넣는다. 사설 CA
루트를 PC 들이 신뢰하게 만드는 건 별개 문제다. 그쪽은 AUTHORITY_INVALID 로 나오고,
원인별 해결의 사내 CA 항목에서 다뤘다.
판별 순서 정리
1. 경고 화면의 두 이름 ("could not prove that it is A; its security certificate is from B")
└ "does not specify Subject Alternative Names" → CN 전용 (원인 2)
└ B 가 우리 도메인의 변형 → 2번으로
└ B 가 플랫폼 기본 도메인 → CDN·호스팅 연결 (원인 6)
└ B 가 같은 서버의 다른 사이트 → 기본 vhost·SNI (원인 5)
2. s_client -connect A:443 -servername A | x509 -ext subjectAltName
└ SAN 없음 → CN 전용, SAN 넣어 재발급 (원인 2)
└ www/apex 한쪽만 → 이름 추가 재발급 (원인 1)
└ 와일드카드뿐 → 범위·형태 확인 (원인 3)
└ A 가 있음 → 3번으로
3. 주소창의 A 가 어떤 형태인가
└ IP 주소 → iPAddress SAN 또는 이름 접속 (원인 4)
└ 점 없는 단축 이름 → FQDN 접속 또는 SAN 추가 (원인 7)
└ 정상 FQDN → 실패하는 PC 의 DNS·망(캡티브 포털) 확인
OpenSSL(CN 폴백·부분 와일드카드·공개 접미사)과 curl(OpenSSL 백엔드의 CN 폴백)의 “일치” 판정은 이 순서에 넣지 않는다. Chrome 과 결론이 갈린다. 기준은 언제나 SAN 목록 원문이다.
AUTHORITY_INVALID 는 대개 검증하는 쪽 문제라 재발급이 답이 아니었다. 이 에러는 반대다.
인증서의 이름 목록을 바로잡는 재발급(원인 1~3), 맞는 인증서가 나가게 하는 서버·CDN
설정(원인 5·6), 접속 이름 정리(원인 4·7) — 대부분 서버를 운영하는 쪽에서 끝난다.
무료 진단 툴은 CT 로그 기준으로 이 도메인에 발급된 최신 공인 인증서의 SAN·만료일을
보여준다. 재발급한 인증서에 이름이 제대로 들어갔는지 볼 때 쓸 수 있다. 서버가 실제로
내보내는 인증서는 위의 openssl s_client 명령으로 확인한다.
참조
- Chromium — net_error_list.h (CERT_COMMON_NAME_INVALID -200)
- Chromium — ssl_errors_strings.grdp (경고 화면 문구)
- Chromium — x509_certificate.cc (VerifyHostname)
- Chromium — ssl_error_handler.cc (www 제안 URL 이동)
- Chromium — common_name_mismatch_handler.cc (제안 URL HEAD 확인)
- Chromium — error_info.cc (경고 화면 이름 표시)
- Chromium — EnableCommonNameFallbackForLocalAnchors 정책 정의
- Chrome Platform Status — Support for commonName matching in Certificates
- Chrome Releases — Stable Channel Update for Desktop (2017-04-19)
- Chrome for Developers — Chrome 58 deprecations
- Chromium security-dev — commonName 매칭 제거 공지
- RFC 2818 — HTTP Over TLS
- RFC 6125 — Representation and Verification of Domain-Based Application Service Identity
- RFC 9525 — Service Identity in TLS
- RFC 6066 — TLS Extensions (Server Name Indication)
- CA/Browser Forum — Baseline Requirements
- nginx — Configuring HTTPS servers
- nginx — ngx_http_ssl_module (ssl_reject_handshake)
- OpenSSL — openssl-s_client
- OpenSSL 1.1.1 — s_client
- OpenSSL 3.0 — openssl-x509
- OpenSSL 1.1.1 — x509
- OpenSSL 3.0 — X509_check_host
- OpenSSL 3.0 — openssl-verification-options
- OpenSSL 3.0 — openssl-req
- curl — lib/vtls/openssl.c
- curl — lib/vtls/hostcheck.c
- curl — manpage (-s)
- curl — manpage (–resolve)
- CDN 개발자 문서 — 대체 도메인 이름과 인증서 요건
- CDN 개발자 문서 — SNI 와 전용 IP 로 HTTPS 제공
- 정적 호스팅 문서 — 커스텀 도메인 문제 해결
- Certbot — User Guide
- Certbot — cert_manager.py (certificates 출력 형식)
- Let’s Encrypt — 6-day and IP address certificates general availability
- Let’s Encrypt — Profiles