TLS/SSL 동작 원리와 인증서 체인, HTTPS 장애 분석
TLS/SSL 동작 원리와 인증서 체인, HTTPS 장애 분석
1. TLS와 SSL이란 무엇인가?
웹 서비스를 운영하는 시스템 엔지니어라면 다음과 같은 오류를 경험할 수 있다.
- HTTP 접속은 되지만 HTTPS 접속은 실패한다.
- 인증서가 만료되어 브라우저에서 보안 경고가 발생한다.
- Nginx를 재시작했는데도 이전 인증서가 계속 제공된다.
curl에서는 인증서 오류가 발생하지만 브라우저에서는 정상적으로 접속된다.- TLS Handshake가 실패하면서 연결이 종료된다.
- 여러 도메인이 같은 IP를 사용하면서 잘못된 인증서가 반환된다.
이러한 문제를 해결하려면 TLS가 무엇이고, HTTPS 연결 과정에서 어떤 역할을 하는지 이해해야 한다.
**TLS(Transport Layer Security)**는 네트워크 통신의 기밀성, 무결성, 상대방 인증을 제공하는 보안 프로토콜이다.
과거에는 SSL(Secure Sockets Layer)이 사용되었지만, SSL 2.0과 SSL 3.0은 오래전에 폐기되었다. 현재는 TLS를 사용하며, TLS 1.2와 TLS 1.3이 대표적인 버전이다.
현업에서는 여전히 SSL 인증서, SSL 설정이라는 표현을 사용하지만, 실제로는 TLS 인증서와 TLS 설정을 의미하는 경우가 많다.
HTTPS는 HTTP 통신을 TLS로 보호하는 방식이다.
일반 HTTP
Client ---------------------> Web Server
평문 HTTP
HTTPS
Client ---------------------> Web Server
TLS
암호화된 HTTP
TLS가 적용되면 네트워크 중간에서 패킷을 관찰하더라도 일반적으로 HTTP 요청 경로, 헤더, 본문을 그대로 읽을 수 없다.
다만 TLS가 모든 정보를 숨기는 것은 아니다. 연결 IP 주소, 포트, 트래픽 크기와 타이밍 등은 관찰될 수 있으며, DNS 및 TLS 설정에 따라 접속 대상 도메인과 관련된 정보가 노출될 가능성도 있다.
2. TLS가 제공하는 세 가지 보안 기능
TLS를 이해할 때는 세 가지 핵심 기능을 구분해야 한다.
2-1. 기밀성(Confidentiality)
기밀성은 통신 내용을 허가되지 않은 사용자가 읽을 수 없도록 보호하는 기능이다.
예를 들어 사용자가 HTTPS 웹 사이트에 로그인한다고 가정하자.
사용자 브라우저
|
| 암호화된 로그인 요청
v
웹 서버
네트워크 구간에서 패킷을 캡처하더라도 정상적인 TLS 복호화 키가 없다면 로그인 요청의 HTTP 본문을 직접 읽을 수 없다.
2-2. 무결성(Integrity)
무결성은 통신 중 데이터가 변조되었는지 탐지할 수 있도록 하는 기능이다.
TLS는 레코드 보호를 통해 통신 데이터의 무단 변경을 탐지한다. TLS 1.2와 TLS 1.3은 세부적인 암호화 구조가 다르지만, 현대적인 TLS 연결에서는 일반적으로 인증된 암호화(AEAD) 방식이 사용된다.
2-3. 인증(Authentication)
인증은 통신 상대가 누구인지 확인하는 기능이다.
HTTPS에서 브라우저는 서버가 제공한 인증서를 검증한다.
예를 들어 사용자가 다음 주소에 접속한다고 가정하자.
https://www.example.com
브라우저는 서버가 제시한 인증서가 www.example.com에 유효한지, 신뢰할 수 있는 인증기관에서 발급되었는지, 유효 기간이 지나지 않았는지 등을 확인한다.
인증서 검증이 성공하면 브라우저는 인증서에 연결된 공개키와 TLS 키 교환 과정을 통해 서버와 안전한 연결을 수립할 수 있다.
단, 서버 인증서가 유효하다는 사실만으로 웹 사이트의 모든 콘텐츠가 안전하거나 서버가 운영하는 서비스 자체가 신뢰할 만하다는 뜻은 아니다.
3. 공개키와 개인키의 차이
TLS 인증서를 이해하려면 공개키와 개인키부터 알아야 한다.
공개키 암호 방식에서는 서로 수학적으로 연관된 두 개의 키를 사용한다.
- 공개키(Public Key): 다른 사람에게 공개할 수 있는 키
- 개인키(Private Key): 소유자가 안전하게 보관해야 하는 키
TLS에서 서버 인증서에는 서버의 공개키가 포함된다. 이에 대응하는 개인키는 서버가 안전하게 보관한다.
인증기관(CA)
|
| 인증서 발급
v
서버 인증서
+----------------+
| 도메인 정보 |
| 공개키 |
| 발급자 정보 |
| 유효 기간 |
+----------------+
|
v
클라이언트 검증
서버 내부
+-------------------------+
| 인증서 파일 |
| 개인키 파일 |
+-------------------------+
개인키가 외부로 유출되면 공격자가 서버를 사칭하거나 해당 키에 의존하는 보안 기능을 악용할 위험이 생긴다. 따라서 개인키 파일은 접근 권한을 제한하고 안전하게 관리해야 한다.
3-1. 공개키로 데이터를 암호화하면 개인키로 복호화할 수 있을까?
이 설명은 RSA와 같은 일부 공개키 암호 방식에서는 이해를 돕는 예시로 사용할 수 있지만, TLS 전체를 설명하는 일반 규칙은 아니다.
현대적인 TLS 1.3에서는 일반적인 HTTPS 연결에서 공개키로 HTTP 데이터를 직접 암호화하지 않는다.
대신 키 교환 과정에서 세션 키를 설정하고, 실제 통신 데이터는 대칭키 암호화로 보호한다.
이 방식이 효율적인 이유는 대칭키 암호화가 대량의 데이터를 처리하는 데 적합하기 때문이다.
4. TLS Handshake의 전체 과정
브라우저가 HTTPS 서버에 처음 연결할 때는 TLS Handshake가 수행된다.
일반적인 TLS 1.3 연결의 개념적인 흐름은 다음과 같다.
Client Server | | |------ TCP 3-Way Handshake ------------>| | | |------ ClientHello --------------------->| | | |<----- ServerHello ----------------------| |<----- EncryptedExtensions --------------| |<----- Certificate ----------------------| |<----- CertificateVerify ----------------| |<----- Finished -------------------------| | | |------ Finished ------------------------>| | | |======= 암호화된 HTTP 통신 ==============|
위 그림은 일반적인 TLS 1.3 전체 Handshake의 개념도다. 실제 메시지 순서는 연결 조건과 확장 기능에 따라 달라질 수 있다.
각 메시지의 의미를 살펴보자.
4-1. ClientHello
클라이언트는 서버에 ClientHello 메시지를 전송한다.
여기에는 다음과 같은 정보가 포함될 수 있다.
- 지원하는 TLS 버전과 관련 확장 정보
- 지원하는 암호화 방식
- 키 교환에 필요한 임시 공개키 정보
- SNI를 통한 서버 이름
- ALPN을 통한 애플리케이션 프로토콜 협상 정보
ALPN은 HTTP/1.1과 HTTP/2 같은 애플리케이션 프로토콜을 협상하는 데 사용된다.
4-2. ServerHello
서버는 ClientHello를 확인하고 협상할 TLS 설정을 선택한 뒤 ServerHello를 반환한다.
TLS 1.3의 일반적인 키 교환에서는 양측이 임시 키 교환 값을 이용해 공유 비밀을 계산한다.
이 공유 비밀을 바탕으로 통신에 사용할 암호화 키가 파생된다.
중요한 점은 일반적인 TLS 1.3 연결에서 서버의 인증서 개인키로 HTTP 데이터를 직접 암호화하는 것이 아니라는 사실이다.
4-3. Certificate
서버는 자신의 인증서를 전달한다.
인증서에는 공개키, 도메인 정보, 발급자, 유효 기간 등의 정보가 포함된다.
서버는 구성에 따라 중간 인증서를 함께 전달할 수 있다. 루트 인증서는 일반적으로 클라이언트의 신뢰 저장소에 이미 포함되어 있다.
4-4. CertificateVerify
서버는 인증서에 연결된 개인키를 사용해 Handshake 관련 데이터에 대한 서명을 생성한다.
클라이언트는 인증서의 공개키를 이용해 서명을 검증한다.
이 과정은 서버가 인증서에 대응하는 개인키를 실제로 보유하고 있음을 확인하는 데 중요한 역할을 한다.
4-5. Finished
양측은 Handshake 과정에서 설정된 키를 이용해 Finished 메시지를 검증한다.
이 검증이 성공하면 TLS 연결을 통해 애플리케이션 데이터를 안전하게 주고받을 수 있다.
시스템 엔지니어 입장에서는 TLS Handshake가 실패하는 지점을 파악하는 것이 중요하다.
예를 들어 ClientHello까지 전송된 뒤 연결이 종료된다면 TLS 버전, 암호화 설정, SNI, 서버 정책 등을 살펴볼 수 있다. 인증서 검증에서 실패한다면 인증서 체인, 도메인 이름, 유효 기간을 확인해야 한다.
5. 인증서란 무엇인가?
TLS 인증서는 공개키와 서버 또는 도메인의 신원을 연결하는 전자 문서다.
일반적으로 X.509 인증서 형식이 사용된다.
인증서에는 다음과 같은 정보가 포함될 수 있다.
항목설명Subject인증서의 대상Issuer인증서를 발급한 기관Validity인증서 유효 시작 및 종료 시각Subject Public Key공개키 정보Subject Alternative Name(SAN)인증서가 유효한 도메인 또는 기타 이름Signature발급자가 인증서에 대해 생성한 서명Key Usage키의 허용된 용도Extended Key Usage서버 인증 등 확장 용도
최근의 일반적인 웹 서버 인증서에서는 접속 도메인과의 일치 여부를 SAN을 기준으로 검증한다.
예를 들어 인증서의 SAN에 다음 도메인이 포함되어 있다고 가정하자.
DNS:www.example.com DNS:api.example.com
이 인증서는 해당 이름들에 대한 검증을 통과할 수 있다. 하지만 admin.example.com이 포함되어 있지 않다면 해당 이름으로 접속할 때 인증서 이름 불일치 오류가 발생할 수 있다.
와일드카드 인증서인 *.example.com은 일반적으로 한 단계의 하위 도메인과 일치한다. 예를 들어 api.example.com에는 적용될 수 있지만, v1.api.example.com까지 자동으로 포함하지는 않는다.
6. 인증서 체인(Certificate Chain)
운영 현장에서 자주 발생하는 TLS 오류 중 하나가 인증서 체인 문제다.
인증서는 보통 신뢰할 수 있는 루트 인증기관과 연결되는 구조를 가진다.
Root CA | | 서명 v Intermediate CA | | 서명 v Server Certificate | v www.example.com
각 단계의 역할은 다음과 같다.
- Root CA: 클라이언트가 신뢰 저장소를 통해 신뢰하는 루트 인증기관
- Intermediate CA: 루트 또는 다른 중간 인증기관으로부터 서명받은 중간 인증기관
- Server Certificate: 실제 웹 서버의 도메인에 사용되는 인증서
브라우저는 서버 인증서를 검증할 때 신뢰할 수 있는 루트까지 연결되는 인증 경로를 구성한다.
서버가 중간 인증서를 누락하면 클라이언트 환경에 따라 인증서 검증이 실패할 수 있다.
일부 클라이언트는 중간 인증서를 캐시하거나 다른 경로로 가져올 수 있기 때문에, 특정 브라우저에서는 성공하지만 다른 클라이언트에서는 실패하는 현상이 나타날 수 있다.
6-1. 인증서 체인 확인
다음 명령어를 실행한다.
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ -showcerts
출력에서 서버가 제공하는 인증서들을 확인한다.
일반적으로 서버 인증서와 필요한 중간 인증서가 제공되는지 확인해야 한다.
검증 결과를 확인하려면 다음과 같이 실행할 수 있다.
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ -verify_return_error \ -verify_hostname www.example.com
성공적인 검증에서는 환경에 따라 다음과 같은 결과가 나타날 수 있다.
Verification: OK Verify return code: 0 (ok)
이 결과는 해당 클라이언트의 신뢰 저장소와 검증 조건을 기준으로 인증서 검증이 성공했다는 의미다.
운영체제의 CA 저장소, OpenSSL 버전, 인증서 체인 구성에 따라 결과가 달라질 수 있다.
7. 인증서 파일과 개인키 파일 확인하기
Linux 서버에서는 인증서와 개인키를 별도의 파일로 관리하는 경우가 많다.
예를 들어 Nginx 설정에서 다음과 같이 지정할 수 있다.
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate
/etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key
/etc/letsencrypt/live/www.example.com/privkey.pem;
}
일반적으로 다음 파일의 역할은 다르다.
파일역할cert.pem서버 인증서chain.pem중간 인증서 체인fullchain.pem서버 인증서와 중간 인증서를 결합한 파일privkey.pem서버 개인키
위 파일명은 Let's Encrypt에서 흔히 사용하는 구조다. 다른 인증기관이나 운영 환경에서는 파일 이름과 배치가 다를 수 있다.
Nginx의 ssl_certificate에는 일반적으로 서버 인증서와 필요한 중간 인증서를 포함한 파일을 지정한다. ssl_certificate_key에는 해당 인증서의 개인키를 지정한다.
7-1. 인증서 유효 기간 확인
openssl x509 \ -in /etc/letsencrypt/live/www.example.com/fullchain.pem \ -noout -subject -issuer -dates
이 명령어로 인증서의 대상, 발급자, 유효 시작 시각과 종료 시각을 확인할 수 있다.
7-2. 개인키와 인증서가 일치하는지 확인
먼저 공개키 정보를 추출한다.
openssl x509 \ -in /etc/letsencrypt/live/www.example.com/cert.pem \ -pubkey -noout \ | openssl pkey -pubin -outform DER \ | sha256sum
개인키에서 공개키를 추출해 비교한다.
openssl pkey \ -in /etc/letsencrypt/live/www.example.com/privkey.pem \ -pubout -outform DER \ | sha256sum
두 결과의 해시가 같다면 인증서의 공개키와 개인키에서 추출한 공개키가 일치한다는 의미다.
이 방법은 RSA뿐 아니라 OpenSSL에서 지원하는 여러 공개키 유형에도 적용할 수 있다.
개인키 자체를 화면에 출력하거나 외부로 전송하지 말고, 접근 권한을 제한해 관리해야 한다.
8. TLS 인증서 검증이 실패하는 대표적인 원인
8-1. 인증서 만료
인증서의 유효 기간이 종료되면 클라이언트가 검증에 실패할 수 있다.
확인 명령어:
openssl x509 \ -in /etc/letsencrypt/live/www.example.com/cert.pem \ -noout -dates
인증서 만료가 확인되면 발급기관의 갱신 절차에 따라 새 인증서를 발급받고 웹 서버에 적용해야 한다.
8-2. 도메인 이름 불일치
인증서는 www.example.com에 발급되었는데 클라이언트가 api.example.com으로 접속하면 이름 불일치 오류가 발생할 수 있다.
검증 명령어:
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ -verify_hostname www.example.com
8-3. 중간 인증서 누락
서버가 필요한 중간 인증서를 전달하지 않으면 일부 클라이언트에서 신뢰 체인을 구성하지 못할 수 있다.
Nginx에서는 인증서 파일에 필요한 중간 인증서가 포함되어 있는지 확인한다.
8-4. 서버 시간 오류
시스템 시간이 크게 틀어지면 아직 유효하지 않은 인증서나 만료된 인증서로 판단될 수 있다.
Linux에서 다음과 같이 확인한다.
date timedatectl status
NTP 동기화 상태와 시간대 설정도 점검한다.
8-5. 신뢰 저장소 문제
서버 인증서가 정상이어도 클라이언트의 CA 저장소가 오래되었거나 내부 인증기관을 신뢰하지 않으면 검증에 실패할 수 있다.
이 경우 서버 인증서뿐 아니라 클라이언트의 신뢰 저장소와 조직 내부 인증서 정책도 확인해야 한다.
9. 실제 장애 사례 1 — 인증서를 갱신했는데 이전 인증서가 보이는 경우
인증서를 갱신했지만 외부에서 확인하면 이전 인증서가 계속 보인다고 가정하자.
가능한 원인은 다음과 같다.
- 새 인증서가 다른 경로에 저장되었다.
- Nginx 설정이 이전 인증서 경로를 참조한다.
- 인증서는 갱신했지만 Nginx를 재로드하지 않았다.
- 여러 서버 중 일부만 갱신되었다.
- 로드밸런서나 CDN이 별도의 인증서를 제공한다.
- DNS가 서로 다른 서버 IP를 반환한다.
먼저 서버가 실제로 제공하는 인증서를 확인한다.
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ </dev/null 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates
다음으로 Nginx 설정을 확인한다.
sudo nginx -t sudo nginx -T
nginx -T는 실제로 읽힌 설정을 출력하므로 인증서 경로와 server_name을 확인하는 데 유용하다. 단, 출력에 민감한 설정 정보가 포함될 수 있으므로 공유하거나 저장할 때 주의한다.
설정과 인증서 파일이 정상이라면 적절한 시점에 Nginx를 재로드한다.
sudo systemctl reload nginx
재로드 후 다시 외부에서 인증서를 확인한다.
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ </dev/null 2>/dev/null \ | openssl x509 -noout -dates
여러 IP가 존재한다면 각 IP를 개별적으로 확인하는 것이 좋다.
openssl s_client \ -connect 192.168.10.100:443 \ -servername www.example.com \ </dev/null
이때 -servername을 지정해야 SNI 기반으로 올바른 인증서가 선택되는지 확인할 수 있다.
10. 실제 장애 사례 2 — IP 주소로 접속하면 인증서 오류가 발생하는 경우
다음과 같이 접속한다고 가정하자.
https://192.168.10.100
서버가 www.example.com용 인증서를 제공한다면 IP 주소로 접속할 때 이름 불일치 오류가 발생할 수 있다.
인증서가 IP 주소를 SAN에 포함하지 않는 한, 일반적으로 도메인 이름으로 접속해야 한다.
https://www.example.com
DNS가 아직 구성되지 않은 테스트 환경이라면 curl --resolve를 사용해 도메인 이름은 유지하면서 연결 IP를 지정할 수 있다.
curl -v \ --resolve www.example.com:443:192.168.10.100 \ https://www.example.com/
이 명령어는 다음과 같이 동작한다.
- URL의 호스트 이름은
www.example.com으로 유지한다. - 해당 호스트의 443번 연결에는
192.168.10.100을 사용한다. - TLS SNI와 인증서 호스트 이름 검증도 해당 도메인을 기준으로 수행한다.
따라서 DNS 문제와 인증서 문제를 분리해서 점검할 수 있다.
11. 실제 장애 사례 3 — TLS Handshake 실패
HTTPS 요청을 실행했는데 다음과 같은 오류가 발생한다고 가정하자.
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL
이 오류만으로 원인을 확정할 수는 없다. TLS 연결 도중 연결이 종료되었거나 통신 과정에서 오류가 발생했을 수 있다.
먼저 상세 로그를 확인한다.
curl -v https://www.example.com
TLS 연결만 확인하려면 다음 명령어를 사용할 수 있다.
openssl s_client \ -connect www.example.com:443 \ -servername www.example.com \ -state
확인할 항목은 다음과 같다.
- TCP 연결이 먼저 성공했는가?
- ClientHello가 전송되었는가?
- 서버가 TLS 응답을 반환하는가?
- 인증서가 정상적으로 전달되는가?
- TLS 버전이나 암호화 방식 협상에서 문제가 발생하는가?
- 중간 장비가 연결을 종료하는가?
- 서버 로그에 TLS 관련 오류가 기록되는가?
서버 측에서는 다음 명령어를 사용해 연결 상태를 확인한다.
sudo ss -lntp | grep ':443'
패킷 흐름도 확인한다.
sudo tcpdump -nn -i ens160 'tcp port 443'
TCP 연결이 수립되지만 TLS Handshake가 실패한다면 웹 서버의 TLS 설정, 인증서, SNI, 클라이언트와 서버의 TLS 호환성 등을 확인한다.
반대로 TCP SYN에 대한 SYN-ACK가 반환되지 않는다면 TLS 설정을 살펴보기 전에 방화벽, 라우팅, 서버 포트 상태부터 확인해야 한다.
12. TLS 1.2와 TLS 1.3의 차이
TLS 1.2와 TLS 1.3은 모두 안전한 통신을 위한 프로토콜이지만 Handshake 구조와 지원 암호화 방식 등에 차이가 있다.
항목TLS 1.2TLS 1.3Handshake일반적으로 TLS 1.3보다 왕복 과정이 길 수 있음일반적인 전체 Handshake를 1-RTT로 수행 가능암호화 방식다양한 구형 암호군도 구현에 따라 지원취약하거나 불필요한 구형 암호군 제거키 교환구성에 따라 전방향 안전성 지원 여부가 다름일반적인 인증서 기반 키 교환에서 (EC)DHE 등 사용서버 인증서Handshake 과정에서 전달Handshake 과정에서 전달되며 관련 메시지가 암호화됨0-RTT표준적인 TLS 1.2 기능이 아님조건에 따라 재개 연결에서 사용 가능
여기서 1-RTT는 일반적인 전체 TLS Handshake에서 클라이언트와 서버 사이에 한 번의 왕복 지연을 이용해 연결을 설정할 수 있다는 의미다. TCP 연결 수립 시간은 별도다.
TLS 1.3의 0-RTT는 세션 재개 상황에서 일부 데이터를 더 일찍 전송할 수 있도록 하지만, 재전송 공격과 관련된 주의점이 있다. 따라서 모든 요청에 무조건 적용하는 것이 적절하지 않으며, 서버와 애플리케이션이 해당 위험을 고려해야 한다.
운영 환경에서는 가능하면 현대적인 TLS 설정을 사용하되, 실제 지원 범위는 클라이언트 호환성과 서비스 요구 사항을 함께 검토해야 한다.
13. Nginx HTTPS 설정 점검
Linux 서버에서 Nginx를 사용한다면 HTTPS 설정을 다음 순서로 점검할 수 있다.
13-1. 설정 파일 검사
sudo nginx -t
설정 파일의 문법과 기본적인 설정 유효성을 확인한다.
13-2. 실제 적용 설정 확인
sudo nginx -T
server_name, listen 443 ssl, 인증서 경로, TLS 관련 설정 등을 확인한다.
13-3. 인증서와 개인키 경로 확인
sudo ls -l /etc/letsencrypt/live/www.example.com/
심볼릭 링크가 가리키는 실제 파일이 존재하는지, Nginx 프로세스가 필요한 파일을 읽을 수 있는지 확인한다.
개인키는 불필요하게 넓은 권한으로 공개하지 않는다.
13-4. Nginx 상태 확인
sudo systemctl status nginx
최근 로그도 확인한다.
sudo journalctl -u nginx --since "30 minutes ago"
13-5. 설정 변경 적용
문법 검사와 사전 점검이 완료되었다면 적절한 시점에 재로드한다.
sudo nginx -t && sudo systemctl reload nginx
재로드 후에는 실제 서비스에 다시 접속해 인증서와 HTTP 응답을 확인한다.
재로드 명령이 성공했다고 해서 올바른 인증서가 제공된다는 의미는 아니다. 외부에서 실제 연결을 검증해야 한다.
14. 실전 장애 분석 종합 절차
HTTPS 장애가 발생하면 다음 순서로 분석한다.
1. DNS 조회
|
v
2. TCP 443 연결
|
v
3. TLS Handshake
|
v
4. 인증서 검증
|
v
5. HTTP 요청 및 응답
|
v
6. Reverse Proxy
|
v
7. Backend Application
각 단계에서 사용하는 주요 명령어는 다음과 같다.
단계명령어확인 목적DNSdig www.example.com도메인 해석 결과TCPnc -zv www.example.com 443포트 연결 가능 여부TLSopenssl s_clientHandshake 및 인증서 확인HTTPcurl -v https://www.example.comHTTP 요청과 TLS 오류Socketss -lntp서버 포트 LISTEN 상태Packettcpdump실제 패킷 흐름Web Servernginx -t, journalctl설정과 서비스 로그
시스템 엔지니어는 하나의 오류 메시지만 보고 해결책을 결정하기보다, 각 단계의 결과를 연결해서 원인을 찾아야 한다.
예를 들어 다음과 같은 결과가 나왔다고 가정하자.
DNS 조회 : 성공 TCP 443 연결 : 성공 TLS Handshake : 성공 인증서 검증 : 성공 HTTP 응답 : 502 Bad Gateway
이 경우 DNS, TCP, TLS 연결은 정상적으로 진행되었다. 다음으로 Nginx와 백엔드 사이의 통신, 업스트림 주소, 백엔드 서비스 상태 및 로그를 확인해야 한다.
반대로 TCP 연결 자체가 실패한다면 인증서 파일을 변경하는 것은 적절한 첫 번째 조치가 아니다.
장애가 발생한 계층을 먼저 식별해야 불필요한 설정 변경을 줄이고 복구 시간을 단축할 수 있다.
마무리
이번 편에서는 TLS와 SSL의 차이, TLS의 보안 기능, 공개키와 개인키, TLS Handshake, 인증서 체인, Linux에서의 인증서 검증 및 HTTPS 장애 분석을 살펴보았다.
현장에서 HTTPS 장애를 분석할 때는 인증서 만료 여부만 확인해서는 안 된다. 인증서와 개인키의 일치 여부, 중간 인증서 체인, SNI, TLS 버전, 서버 시간, Nginx 설정 및 실제 패킷 흐름을 함께 확인해야 한다.
특히 다음 세 가지를 기억하자.
- TCP 연결 성공과 TLS Handshake 성공은 서로 다른 단계다.
- 인증서 파일이 정상이어도 서버가 실제로 제공하는 인증서가 다를 수 있다.
- HTTPS 장애는 DNS, TCP, TLS, HTTP, 백엔드 계층으로 나누어 분석해야 한다.
이러한 원칙은 Nginx뿐 아니라 Apache, HAProxy, Kubernetes Ingress, API Gateway 등 다양한 운영 환경에서 활용할 수 있다.
다음 편에서는 시스템 엔지니어를 위한 네트워크 15편 — Port와 Socket 완벽 이해를 다룬다. TCP/UDP 포트, IP와 포트의 조합, 소켓의 의미, ss를 이용한 LISTEN·ESTABLISHED·TIME_WAIT 상태 분석, 포트 충돌 및 연결 수 고갈 문제를 실제 Linux 명령어 중심으로 살펴보겠다.
다음 편에서는 웹 서비스와 데이터베이스 연결 장애를 진단할 때 반드시 필요한 Port와 Socket의 차이, Linux 소켓 상태 분석, 포트 충돌 및 연결 고갈 장애로 이어가면 됩니다.
댓글
아직 댓글이 없습니다.
로그인 후 댓글을 남길 수 있습니다.