- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며
- 1. 파일 형식 구분 — 무엇을 받았는지부터 확인
- 2. 인증서 읽기 — 이 파일이 무엇인지 확인
- 3. 키와 인증서가 짝인지 확인
- 4. CSR 만들기 — SAN을 반드시 넣기
- 5. 체인 검증 — 중간 인증서 누락 잡기
- 6. 서버에 붙어 진단하기 — s_client
- 7. 자주 겪는 오류와 판별 순서
- 퀴즈: 실력을 확인해 보세요
- 마치며
- 참고 자료
- 이어서 읽기
들어가며
인증서 문제는 항상 급합니다. 갱신을 놓쳐 서비스가 멈췄거나, 새로 설치했는데 일부 클라이언트만 실패하거나, 파일 형식이 맞지 않아 로드가 안 됩니다. 그때 필요한 것은 TLS 핸드셰이크 이론이 아니라 지금 이 파일이 무엇이고 무엇이 빠졌는지 확인하는 명령입니다.
이 블로그에는 SSL/TLS 인증서 완벽 가이드가 이미 있습니다. 그 글은 Let's Encrypt 발급, Nginx 설정, 자동 갱신 같은 발급과 운영 흐름을 다룹니다. 이 글은 다른 것을 목표로 합니다. openssl 명령 자체의 레퍼런스입니다. 인증서 파일을 앞에 두고 무엇을 확인해야 하는지, 어떤 명령이 어떤 사실을 알려 주는지를 목적별로 정리합니다. 발급 방법이 아니라 진단 방법이 주제입니다.
이 글의 명령은 전부 읽기와 진단 위주입니다. 인증서를 잘못 읽어서 생기는 피해는 없지만, 개인 키를 다루는 명령은 다릅니다. 키 파일을 화면에 출력하거나 잘못된 권한으로 저장하면 그 순간 유출입니다. 그래서 이 글은 가능한 한 키 내용을 출력하지 않고 다이제스트만 비교하는 방식을 기본으로 삼습니다.
기준은 OpenSSL 3.x입니다. OpenSSL 1.1.1과 3.x는 일부 옵션과 기본 동작이 다릅니다. 또한 macOS 기본 환경이나 일부 배포판은 LibreSSL을 쓰며, 이 경우 옵션이 다를 수 있습니다. 실행 전에 버전을 확인하세요.
openssl version -a
1. 파일 형식 구분 — 무엇을 받았는지부터 확인
인증서 관련 사고의 상당수는 형식 착오에서 시작합니다. 확장자는 참고일 뿐 내용을 보장하지 않습니다.
| 형식 | 내용 | 흔한 확장자 |
|---|---|---|
| PEM | Base64 텍스트. 헤더 줄이 있음 | .pem .crt .cer .key |
| DER | 이진 인코딩 | .der .cer |
| PKCS#12 | 인증서와 개인 키를 한 파일에 | .p12 .pfx |
| PKCS#7 | 인증서 묶음(키 없음) | .p7b .p7c |
| PKCS#8 | 개인 키 표준 형식 | .key .pem |
먼저 파일이 텍스트인지 이진인지 봅니다.
file server.crt
head -1 server.crt
PEM이면 첫 줄에 -----BEGIN 으로 시작하는 표시가 있습니다. 그 표시가 무엇인지가 곧 내용입니다.
BEGIN CERTIFICATE: 인증서BEGIN CERTIFICATE REQUEST: CSRBEGIN PRIVATE KEY: PKCS#8 개인 키BEGIN RSA PRIVATE KEY: 전통적 RSA 개인 키BEGIN ENCRYPTED PRIVATE KEY: 암호화된 개인 키
형식 변환은 다음과 같습니다.
openssl x509 -in server.der -inform DER -out server.pem -outform PEM
openssl x509 -in server.pem -outform DER -out server.der
openssl pkcs12 -in bundle.pfx -nodes -out bundle.pem
openssl pkcs12 -export -inkey server.key -in server.crt -certfile chain.crt -out bundle.pfx
openssl pkcs7 -print_certs -in chain.p7b -out chain.pem
-inform과 -outform은 입력·출력 인코딩을 지정합니다. PKCS#12 변환에서 -nodes는 개인 키를 암호화하지 않고 출력한다는 뜻이므로, 결과 파일의 권한을 즉시 제한해야 합니다.
chmod 600 bundle.pem
형식 착오가 실제로 어떻게 사고로 이어지는지 하나만 예를 들면 이렇습니다. 윈도우 서버에서 내보낸 .pfx 파일을 받아 Nginx에 그대로 지정하면 서버가 뜨지 않습니다. Nginx는 PEM 형식의 인증서와 키를 각각 요구하기 때문입니다. 반대로 자바 애플리케이션에 PEM 쌍을 그대로 주면 keystore 형식이 아니라며 거부합니다. 파일을 받으면 확장자를 믿지 말고 내용을 먼저 확인하는 것이 30분을 아껴 줍니다.
PKCS#12 묶음에서 필요한 부분만 꺼낼 수도 있습니다. 인증서만, 또는 키만 분리해야 하는 상황이 자주 생깁니다.
openssl pkcs12 -in bundle.pfx -clcerts -nokeys -out server.crt
openssl pkcs12 -in bundle.pfx -cacerts -nokeys -out chain.crt
openssl pkcs12 -in bundle.pfx -nocerts -nodes -out server.key
-clcerts는 클라이언트(최종 개체) 인증서만, -cacerts는 CA 인증서만, -nocerts는 인증서를 제외한 키만 출력합니다.
2. 인증서 읽기 — 이 파일이 무엇인지 확인
가장 많이 쓰는 명령부터 봅니다.
openssl x509 -in server.crt -noout -text
openssl x509 -in server.crt -noout -subject -issuer -dates
openssl x509 -in server.crt -noout -serial -fingerprint -sha256
openssl x509 -in server.crt -noout -ext subjectAltName
옵션의 의미는 문서 기준으로 다음과 같습니다.
-noout은 인코딩된 원본 출력을 억제하고, 요청한 항목만 보여 줍니다.-text는 인증서 전체를 사람이 읽는 형태로 출력합니다.-subject,-issuer는 주체와 발급자,-dates는 유효 시작·종료 시각을 보여 줍니다.-startdate,-enddate로 각각 볼 수도 있습니다.-fingerprint는 DER 인코딩본의 다이제스트를 계산합니다.-ext는 지정한 X.509 확장을 출력합니다.
실무에서 가장 자주 확인해야 하는 것은 SAN(Subject Alternative Name) 입니다. 현대 브라우저와 라이브러리는 CN을 보지 않고 SAN만 봅니다. CN에 도메인이 있어도 SAN에 없으면 실패합니다.
openssl x509 -in server.crt -noout -ext subjectAltName
만료 여부는 초 단위로 판정할 수 있습니다. 문서에 따르면 -checkend는 지정한 초 이내에 만료되는지 확인합니다.
openssl x509 -in server.crt -noout -checkend 0
openssl x509 -in server.crt -noout -checkend 2592000
echo "exit=$?"
종료 코드가 0이면 그 기간 안에 만료되지 않는다는 뜻입니다. 30일(2592000초)을 넣어 두면 갱신 알림 스크립트를 그대로 만들 수 있습니다.
인증서 본문에서 실제로 확인할 가치가 있는 항목은 생각보다 적습니다. 유효 기간과 SAN이 8할이고, 나머지는 문제 상황에서만 봅니다. -text 출력에서 눈여겨볼 것을 꼽으면 다음과 같습니다.
- Signature Algorithm: 서명 알고리즘입니다. 오래된 SHA-1 서명은 최신 클라이언트가 거부합니다.
- Public Key Algorithm과 키 길이: RSA 1024비트 같은 짧은 키는 거부됩니다.
- Basic Constraints: CA 여부입니다. 서버 인증서인데 CA로 표시되어 있으면 잘못 발급된 것입니다.
- Key Usage와 Extended Key Usage: 서버 인증 용도가 포함되어 있어야 합니다. 클라이언트 인증용으로 발급된 인증서를 서버에 설치하면 실패합니다.
- Authority Information Access: 발급자 인증서와 OCSP 응답기 주소가 들어 있습니다.
이 항목들은 새 CA를 도입하거나 발급 요청 양식을 바꿨을 때 한 번은 확인해 두는 편이 좋습니다.
#!/usr/bin/env bash
set -uo pipefail
for CRT in /etc/pki/tls/certs/*.crt; do
if ! openssl x509 -in "$CRT" -noout -checkend 2592000 >/dev/null 2>&1; then
echo "EXPIRING SOON: $CRT"
openssl x509 -in "$CRT" -noout -subject -enddate
fi
done
3. 키와 인증서가 짝인지 확인
"인증서를 바꿨는데 서버가 안 뜬다"의 절반은 키와 인증서가 짝이 아니어서입니다. 판별 방법은 공개 키 부분을 비교하는 것입니다.
RSA 키라면 modulus를 비교합니다.
openssl x509 -in server.crt -noout -modulus | openssl sha256
openssl rsa -in server.key -noout -modulus | openssl sha256
openssl req -in server.csr -noout -modulus | openssl sha256
세 값이 같으면 CSR, 인증서, 키가 모두 한 쌍입니다. 다르면 짝이 아닙니다.
RSA가 아닌 키(ECDSA, Ed25519)에는 -modulus가 없습니다. 이 경우 공개 키 자체를 뽑아 비교합니다.
openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
이 방법은 키 종류와 무관하게 동작하므로, 기억할 명령을 하나만 고른다면 이쪽이 낫습니다.
개인 키 자체의 정보는 다음으로 봅니다.
openssl pkey -in server.key -noout -text
openssl rsa -in server.key -check -noout
파괴적 명령 경고 대신 유출 주의: 개인 키를 출력하는 명령은 터미널 기록과 화면 공유에 그대로 남습니다. 키 내용 전체를 출력하는 대신 위처럼 다이제스트만 비교하는 습관을 들이세요.
4. CSR 만들기 — SAN을 반드시 넣기
CSR 생성에서 가장 흔한 실수는 SAN을 넣지 않는 것입니다. 설정 파일을 쓰는 편이 확실합니다.
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
C = KR
ST = Seoul
O = Example Corp
CN = www.example.com
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
DNS.3 = api.example.com
이 파일을 csr.cnf로 저장한 뒤 생성합니다.
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -config csr.cnf
openssl req -in server.csr -noout -text
openssl req -in server.csr -noout -verify
ECDSA 키를 쓸 경우입니다.
openssl ecparam -name prime256v1 -genkey -noout -out server-ec.key
openssl req -new -key server-ec.key -out server-ec.csr -config csr.cnf
생성 후에는 반드시 SAN이 들어갔는지 확인하세요. 여기서 놓치면 발급을 다시 받아야 합니다.
openssl req -in server.csr -noout -text | grep -A3 'Subject Alternative Name'
내부 테스트용 사설 CA와 서버 인증서는 다음처럼 만듭니다.
openssl req -x509 -new -nodes -newkey rsa:4096 -sha256 -days 3650 \
-subj '/C=KR/O=Example Internal/CN=Example Internal Root CA' \
-keyout ca.key -out ca.crt
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 397 -sha256 -extfile csr.cnf -extensions req_ext
-CAcreateserial은 일련번호 파일이 없으면 만듭니다. -extfile과 -extensions를 지정하지 않으면 SAN이 서명 결과에 포함되지 않습니다. 사설 CA에서 만든 인증서가 브라우저에서 실패하는 가장 흔한 원인입니다.
5. 체인 검증 — 중간 인증서 누락 잡기
"내 브라우저에서는 되는데 서버에서 curl로는 안 된다"의 표준 원인은 중간 인증서 누락입니다. 브라우저는 캐시나 AIA 정보로 중간 인증서를 보충하지만, 명령줄 도구와 서버 간 통신은 그렇지 않습니다.
로컬 파일로 검증합니다.
openssl verify -CAfile ca.crt server.crt
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt
openssl verify -show_chain -CAfile /etc/pki/tls/certs/ca-bundle.crt server.crt
-CAfile은 신뢰 앵커(루트)를 지정합니다.-untrusted는 중간 인증서를 제공합니다.-show_chain은 구성된 체인을 보여 줍니다.
시스템 신뢰 저장소 경로는 배포판마다 다릅니다. RHEL 계열은 /etc/pki/tls/certs/ca-bundle.crt, Debian/Ubuntu 계열은 /etc/ssl/certs/ca-certificates.crt 입니다.
인증서 파일 안에 몇 장이 들어 있는지 세는 것도 유용합니다.
grep -c 'BEGIN CERTIFICATE' fullchain.pem
서버에 설치하는 파일은 보통 서버 인증서 다음에 중간 인증서 순서로 이어 붙입니다. 루트는 포함하지 않는 것이 관례입니다. 순서가 뒤바뀌면 일부 클라이언트가 실패합니다.
cat server.crt intermediate.crt > fullchain.pem
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout
마지막 명령은 묶음 파일 안의 각 인증서의 subject와 issuer를 나열해 줍니다. 앞 인증서의 issuer가 다음 인증서의 subject와 일치하는지 확인하면 순서가 맞는지 알 수 있습니다.
체인 구성에서 헷갈리기 쉬운 지점을 정리하면 이렇습니다. 서버가 보내야 하는 것은 자신의 인증서와, 루트에 도달하기까지 필요한 중간 인증서 전부입니다. 루트 인증서는 클라이언트가 이미 신뢰 저장소에 가지고 있으므로 보낼 필요가 없고, 보내도 대개 무시됩니다. 다만 보내면 핸드셰이크마다 불필요한 바이트가 오가므로 관례적으로 제외합니다.
중간 인증서가 여러 장인 경우도 있습니다. 요즘 상용 CA는 두 단계 중간 구조를 쓰는 경우가 있어, 발급 메일에 첨부된 번들을 그대로 쓰지 않고 직접 조립하다가 한 장을 빠뜨리는 사고가 생깁니다. 조립했다면 반드시 검증까지 하세요.
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt -untrusted intermediate.crt server.crt
이 명령이 OK를 출력하면 로컬 신뢰 저장소 기준으로 체인이 완성된 것입니다. 실패하면 어느 단계에서 끊겼는지 오류 메시지에 나옵니다.
6. 서버에 붙어 진단하기 — s_client
실제 서버가 무엇을 보내는지 확인하는 명령입니다.
openssl s_client -connect example.com:443 -servername example.com
openssl s_client -connect example.com:443 -servername example.com -showcerts
openssl s_client -connect example.com:443 -servername example.com -brief
openssl s_client -connect example.com:443 -servername example.com -tls1_2
openssl s_client -connect example.com:443 -servername example.com -status
openssl s_client -connect smtp.example.com:587 -starttls smtp
옵션의 의미는 문서 기준입니다.
-connect는 접속 대상입니다.-servername은 ClientHello에 SNI를 넣습니다. 가상 호스팅 환경에서 이것이 없으면 엉뚱한 기본 인증서를 받습니다. 진단할 때 반드시 넣으세요.-showcerts는 서버가 보낸 인증서 목록을 그대로 보여 줍니다. 문서가 명시하듯 이것은 검증된 체인이 아니라 서버가 보낸 그대로입니다. 그래서 중간 인증서 누락을 확인하는 데 딱 맞습니다.-status는 OCSP 스테이플링 응답을 요청합니다.-brief는 연결 요약만 출력합니다.-starttls는 프로토콜별 전환 메시지를 보냅니다. smtp, imap, pop3, ftp, postgres, mysql, ldap 등을 지원합니다.
명령이 입력을 기다리며 멈춰 있으므로, 스크립트에서는 표준 입력을 닫아 줍니다.
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -dates
이 한 줄이 원격 인증서 만료 확인의 표준 관용구입니다. 배치로 여러 호스트를 점검할 때 그대로 씁니다.
for H in www.example.com api.example.com admin.example.com; do
printf '%s ' "$H"
echo | openssl s_client -connect "$H:443" -servername "$H" 2>/dev/null \
| openssl x509 -noout -enddate
done
체인 검증 결과는 출력 앞부분의 verify 관련 줄에서 확인합니다. unable to get local issuer certificate가 보이면 중간 인증서가 빠졌거나 로컬 신뢰 저장소에 루트가 없는 것입니다.
7. 자주 겪는 오류와 판별 순서
| 증상 | 확인 명령 | 원인 후보 |
|---|---|---|
| 브라우저는 되고 curl은 실패 | s_client -showcerts | 중간 인증서 누락 |
| 특정 도메인만 실패 | x509 -ext subjectAltName | SAN 누락 |
| 서버 기동 실패, 키 오류 | modulus 또는 pubkey 다이제스트 비교 | 키-인증서 불일치 |
| 갱신했는데 옛 인증서가 보임 | s_client -servername | 재적재 누락, 다른 가상 호스트 |
| 오래된 클라이언트만 실패 | s_client -tls1_2 | 프로토콜·암호군 불일치 |
| 사설 CA 인증서가 거부됨 | verify -CAfile | 신뢰 저장소에 CA 미등록 |
| 만료 직전 알림이 안 옴 | x509 -checkend | 모니터링 부재 |
판별 순서는 항상 같습니다. 첫째, 파일이 무엇인지 확인합니다. 둘째, 키와 짝인지 확인합니다. 셋째, 체인이 완전한지 확인합니다. 넷째, 서버가 실제로 무엇을 보내는지 확인합니다. 이 순서를 지키면 대부분 두 번째나 세 번째에서 원인이 나옵니다.
사설 CA를 시스템 신뢰 저장소에 등록하는 방법도 배포판마다 다릅니다.
# RHEL 계열
sudo cp internal-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract
# Debian 계열
sudo cp internal-ca.crt /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificates
주의: 파일 확장자가 배포판마다 요구되는 형태가 다릅니다. Debian 계열은 .crt 확장자와 PEM 형식을 요구합니다. 등록 후에는 실제로 신뢰되는지 확인하세요.
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.crt
curl -sSI https://internal.example.com | head -1
갱신 후 반영되지 않는 문제도 흔합니다. 파일만 바꾸고 서비스를 재적재하지 않으면 프로세스가 메모리에 올려 둔 옛 인증서를 계속 씁니다. 파일 시각과 실제 제공 중인 인증서를 대조하면 즉시 판별할 수 있습니다.
ls -l --time-style=long-iso /etc/pki/tls/certs/server.crt
openssl x509 -in /etc/pki/tls/certs/server.crt -noout -enddate
echo | openssl s_client -connect localhost:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -enddate
파일의 만료일과 서버가 실제로 제공하는 인증서의 만료일이 다르면 재적재가 빠진 것입니다. 자동 갱신을 설정했다면 갱신 훅에 서비스 재적재까지 포함되어 있는지 반드시 확인하세요. 갱신은 성공했는데 반영이 안 되어 만료로 장애가 나는 사례가 실제로 적지 않습니다.
또 하나 자주 잊는 것이 애플리케이션마다 신뢰 저장소가 다르다는 사실입니다. 자바는 자체 keystore를, Python은 certifi 번들을, Node.js는 내장 목록을 씁니다. 시스템에 CA를 등록했는데도 특정 애플리케이션만 실패한다면 그 런타임의 신뢰 저장소를 따로 확인해야 합니다.
퀴즈: 실력을 확인해 보세요
퀴즈 1: 브라우저에서는 정상인데 서버 간 API 호출만 인증서 오류가 납니다. 무엇을 먼저 확인하나요?
정답: 서버가 중간 인증서를 함께 보내는지 확인합니다
설명: 브라우저는 캐시나 AIA 정보로 중간 인증서를 보충하지만, 명령줄 도구와 대부분의 언어 런타임은 그렇지 않습니다.
echo | openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts 2>/dev/null | grep -c 'BEGIN CERTIFICATE'
1이 나오면 서버 인증서만 보내는 것이므로 중간 인증서가 빠진 것입니다. 서버에 설치할 파일을 서버 인증서 다음에 중간 인증서 순서로 이어 붙여 다시 설치하세요.
퀴즈 2: 인증서와 개인 키가 한 쌍인지 확인하는, 키 종류와 무관한 방법은?
정답: 양쪽에서 공개 키를 뽑아 다이제스트를 비교합니다
설명: -modulus 비교는 RSA에만 통합니다. ECDSA나 Ed25519에서는 다음 방법을 씁니다.
openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
두 값이 같으면 한 쌍입니다. 이 방법은 키 종류를 가리지 않으므로 하나만 외운다면 이쪽입니다. 개인 키 내용 자체를 화면에 출력하지 않는다는 점에서도 안전합니다.
퀴즈 3: 사설 CA로 만든 서버 인증서가 브라우저에서 도메인 불일치로 거부됩니다. 무엇을 빠뜨렸을까요?
정답: 서명 시 SAN 확장을 포함하지 않았습니다
설명: CSR에 SAN을 넣었더라도 openssl x509 -req로 서명할 때 확장을 명시하지 않으면 결과 인증서에 SAN이 들어가지 않습니다.
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 397 -sha256 -extfile csr.cnf -extensions req_ext
서명 후 반드시 확인하세요.
openssl x509 -in server.crt -noout -ext subjectAltName
현대 클라이언트는 CN을 보지 않고 SAN만 봅니다.
퀴즈 4: 여러 도메인이 한 IP에 있습니다. s_client로 특정 도메인의 인증서를 확인하려면?
정답: -servername으로 SNI를 지정합니다
설명: SNI를 주지 않으면 서버가 기본 가상 호스트의 인증서를 반환하므로, 확인하려던 도메인의 인증서가 아닌 것을 보게 됩니다.
echo | openssl s_client -connect 203.0.113.10:443 -servername api.example.com 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
문서에 따르면 -servername을 생략하면 -connect의 호스트명이 기본값으로 쓰이므로, IP로 직접 접속할 때는 반드시 명시해야 합니다.
퀴즈 5: 30일 안에 만료되는 인증서를 자동으로 찾아내려면?
정답: -checkend에 초 단위 값을 주고 종료 코드로 판정합니다
설명: 문서에 따르면 -checkend는 지정한 초 이내에 인증서가 만료되는지 확인합니다. 30일은 2592000초입니다.
for CRT in /etc/pki/tls/certs/*.crt; do
openssl x509 -in "$CRT" -noout -checkend 2592000 >/dev/null 2>&1 \
|| echo "EXPIRING: $CRT"
done
원격 서버도 같은 방식으로 점검할 수 있습니다.
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -checkend 2592000
퀴즈 6: 시스템 신뢰 저장소에 사내 CA를 등록했는데 자바 애플리케이션만 여전히 실패합니다. 왜일까요?
정답: 애플리케이션 런타임이 자체 신뢰 저장소를 쓰기 때문입니다
설명: 자바는 자체 keystore를, Python은 certifi 번들을, Node.js는 내장 CA 목록을 사용합니다. OS 신뢰 저장소를 갱신해도 그 런타임에는 반영되지 않습니다.
먼저 시스템 수준에서는 정상인지 확인합니다.
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.crt
curl -sSI https://internal.example.com | head -1
curl은 되는데 애플리케이션만 실패한다면 원인이 확정됩니다. 각 런타임에 CA를 등록하는 정확한 절차는 해당 런타임 문서에서 확인하세요.
마치며
인증서 진단은 순서만 지키면 어렵지 않습니다. 파일이 무엇인지, 키와 짝인지, 체인이 완전한지, 서버가 실제로 무엇을 보내는지. 이 네 가지를 차례로 확인하면 원인이 드러납니다.
그리고 급할 때 기억나지 않는 명령은 소용이 없습니다. 다음 세 줄만은 외워 두세요.
# 1. 로컬 파일 확인
openssl x509 -in server.crt -noout -text
# 2. 원격 서버 확인
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -dates
# 3. 키와 인증서 짝 확인
openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
이 세 블록이 인증서 관련 작업의 90퍼센트를 커버합니다.
마지막으로, 만료로 인한 장애는 100퍼센트 예방 가능한 사고입니다. -checkend 한 줄로 만드는 점검 스크립트를 오늘 안에 걸어 두세요.
참고 자료
- openssl-x509 공식 문서 (2026-08-15 확인)
- openssl-s_client 공식 문서 (2026-08-15 확인)
- openssl-req 공식 문서 (2026-08-15 확인)
- openssl-verify 공식 문서 (2026-08-15 확인)
이어서 읽기
- 이전 글: 백업과 복구 완전 가이드
- 다음 글: 파일 디스크립터와 inode 완전 가이드
- SSL/TLS 인증서 완벽 가이드 — 발급과 자동 갱신 흐름
- SSH 운영 완전 가이드 — 같은 계열의 키 관리 문제
- curl 빌더 — TLS 옵션이 붙은 curl 명령 만들기
- Linux 터미널 — openssl 명령 연습