SSL/TLS

2026. 5. 11. 09:08·시스템, 인프라

SSL/TLS 개념

요즘 사람들이 말하는 SSL 인증서 나 SSL 통신 은 대부분 TLS 를 의미한다

SSL 은 Secure Socket Layer 의 약자로 인터넷에서 이루어지는 통신을 암호화, 보안, 인증하는 프로토콜
TLS 프로토콜로 업데이트되었지만, 현재는 혼용해서 사용한다

  • 보안 프로토콜, 데이터 암호화, 신원 인증, 데이터 무결성 등을 지키기 위한 역할을 한다

SSL/TLS 탄생 배경

SSL/TLS 의 탄생 배경을 알기 위해서는 우선 HTTP 와 HTTPS의 차이부터 알아야 한다

HTTP 와 HTTPS 의 차이

깊게 알아보지는 않고 큰 차이정도만 알아보고 넘어가자

HTTP (HyperText Transfer Protocol)

널리 알려져있는 `HTTP` 는 `HyperText` 문서인 `HTML` 을 전송하기 위한 통신 규약이다

80번 포트를 사용하고 암호화하지 않고, 데이터를 평문으로 전송한다
이러한 비암호화 방식의 데이터 통신은 공격자에 의해 데이터들이 탈취될 수 있는 보안상의 위험이 존재한다

평문 통신의 문제점은 조회에만 한정되지는 않는다

특정 사이트에 로그인을 하거나, 송금을 할때 비밀번호 같은 정보들이 평문으로 전송되면서 탈취될 위험도 물론 크다
거기에 더해 중간에서 데이터를 조작할 수도 있따는 문제가 있다

사용자가 정상적인 페이지를 요청해도, 공격자가 중간에서 응답 내용을 바꿔 악성 스크립트가 들어간 페이지를 반환하여 공격을 받을 수도 있다는 문제점이 있다

HTTPS (HTTP Secure)

HTTPS 는 HTTP에 SSL/TLS 보안 계층을 추가한 프로토콜이다

이름만 봐도 알 수 있듯이, HTTP의 요청을 감싸서 안전하게 주고 받는 방식의 프로토콜을 의미한다
보통 443번 포트를 사용한다

평문으로 전송되는 HTTP와 다르게 HTTPS 에서는 데이터 전송 전에 TLS Handshake가 수행되고, 이후에 만들어지 암호화 키를 이용해 데이터를 암호화해서 통신을 하게 된다

SSL/TLS 가 해결하는 문제

크게 세 가지 문제를 해결한다

  1. 암호화 : 중간에서 데이터를 가로채도 내용을 알 수 없게 암호화
  2. 인증 : 접속한 서버가 진짜 서버인지 확인
  3. 무결성 : 데이터가 전송 중간에 변조되지 않았는지 확인

단순히 암호화만 하는 것이 아닌 위와 같은 역할들은 한다

SSL 파일 종류

인증서 파일은 서버의 신원을 증명하는 파일이고, 보통 .crt, .cer, .pem 과 같은 확장자를 가진다.

  • 인증서 파일 안에는 보통 아래와 같은 정보들이 들어가 있다
- 인증서가 발급된 도메인
- 인증서를 발급한 기관
- 인증서 유효기간
- 서버의 공개키
- `CA`의 디지털 서명
  • 인증서 파일
    • 서버의 신원을 증명하는 파일
    • 보통 .crt, .cer, .pem 과 같은 확장자를 가짐
    • 브라우저는 서버가 보낸 인증서 파일을 보고 접속하려는 서버가 맞는지 확인하는 용도이다
    • 암호화를 하지는 않는다
  • 개인키 파일
    • 서버만 가지고 있어야 하는 비밀 키 -> .key 확장자를 가짐
    • 인증서에는 공개키 가 들어있고, 서버에는 공개키와 짝이 되는 개인키가 있음
  • 중간 인증서 / 체인 파일
    • 서버 인증서 단독으로 신뢰할 수 없기 때문에 어떤 기관을 거쳐 발급되었는지 확인하는 파일
    • 서버 인증서와 루트 인증서를 이어주는 파일
    • 서버가 중간 인증서를 제대로 전달하지 않으면 브라우저는 인증서의 신뢰 경로를 완성하지 못할 수 있음
  • 루트 인증서
    • 신뢰의 시작 부분
    • 브라우저나 OS에는 이미 신뢰할 수 있는 루트 인증서 목록이 들어 있음
    • 브라우저는 서버 인증서가 중간 인증서를 거쳐 루트 인증서까지 이어지는지 확인
  • CSR 파일 (Certificate Signing Request)
    • 인증서를 발급받기 위해 인증 기관에 제출하는 요청 파일
    • 보통 도메인 정보와 공개키가 들어있움
서버에서 개인키 생성
개인키 기반 CSR 생성
CSR을 CA에 제출
CA가 도메인 소유권 등 검증
CA가 서버 인증서 발급

-> CSR에 개인키가 들어가는 것은 아님

 **개인키**는 서버에 남아 있고, **CSR**에는 인증서 발급에 필요한 정보와 **공개키**가 들어감

브라우저에서 인증서 확인하기

  • 현재 글을 쓰고 있는 플랫폼인 티스토리의 인증서를 살펴보자
  • 크롬 브라우저의 도메인 부분의 왼쪽에 있는 버튼을 누르면 "이 연결은 안전합니다." 라는 문구를 발견할 수 있다

  • 해당 버튼을 다시 누르면 이런식으로 인증서와 관련된 것들이 나온다
    • *.tistory.com 은 tistory.com의 서브 도메인들에 발급된 와일드카드 인증서라는 의미
  • 유효 기간이 있는 것을 확인할 수 있는데, 이는 인증서가 영구적으로 사용할 수 있는 파일이 아니라는 것을 보여준다
    • 유효 기간이 지난 인증서는 더는 신뢰할 수 없어 HTTPS 경고가 발생할 수 있다
    • 따라서 유효 기간이 지나기 전에 갱신하는 과정을 거쳐야 한다

  • 여기서는 인증서 계층 구조를 볼 수 있다
DigiCert Global Root G2
  └─ Thawte TLS RSA CA G1
      └─ *.tistory.com
  • DigiCert Global Root G2 라는 루트 인증서
    • Thawte TLS RSA CA G1 이라는 중간 인증서
      • *.tistory.com 이라는 실제 서버 인증서
  • 이런식의 계층 구조를 볼 수 있다
  • 브라우저는 *.tistory.com 이라는 인증서 하나만 보고 사이트를 바로 신뢰하지 않는다
    • 그 위의 중간 인증서인 Thawte TLS RSA CA G1를 거쳐, 브라우저나 OS가 이미 신뢰하고 있는 루트 인증서까지 연결되는지 확인한다.

연결 수립 과정

  • TCP 연결
    • 클라이언트가 서버 443 포트로 연결 시도 -> 3-way handshake 과정을 거침
    • 아직 암호화가 되지는 않음
  • Client Hello
    • TCP 연결이 끝나면 클라이언트가 Client Hello 메시지를 보냄
    • SNI 정보도 들어가 있음
      • 하나의 서버 IP에서 여러 HTTPS 도메인을 운영할 수 있기 때문에, 클라이언트는 어떤 도메인에 접속하려는지 서버에게 알려줘야 함. -> OS 버전이 낮으면 SNI를 지원하지 않는 경우가 있음 -> 이 경우, SSL 인증 방식이 달라지게 됨
  • Server Hello
    • 서버는 클라이언트가 보낸 정보를 보고 사용할 TLS 버전과 암호화 방식 선택 후 Server Hello 메시지 응답
  • 서버 인증서 전달
    • 서버가 자신의 인증서를 클라이언트에게 전달
    • 서버 공개키, 도메인 정보, 발급 기관, 유효 기간 등이 들어있음
    • 클라이언트는 이 인증서를 보고 해당 도메인의 서버가 맞는지 확인
  • 인증서 검증
    • 클라이언트는 서버가 보낸 인증서 검증
    • 도메인 일치 여부, 인증서 만료 여부, CA 신뢰 여부, 인증서 체인 검증 등
    • 검증 실패시 브라우저는 보안 경고를 보냄
  • 키 교환
    • 인증서 검증이 성공하면 클라이언트와 서버는 데이터를 암호화할 키를 만들기 위한 과정 진행
    • 공개키와 개인키로 암호화하는 것이 아님
      • 비대칭키 방식은 안전하지만 상대적 느림
    • 연결 수립후 실제 데이터 통신에는 속도가 빠른 대칭키 방식을 사용
  • 세션 키 생성
    • 클라이언트와 서버는 주고받은 랜덤 값과 키 교환 정보를 바탕으로 같은 세션 키를 만듦
  • HTTPS 통신 시작
    • 세션 키 생성이 끝나면 실제 HTTP 통신 시작
    • TLS 계층에서 세션키 로 암호화된 뒤 전송

연결 과정 확인

이론을 알아봤으니 실제로 연결이 어떻게 수립되는지 직접 확인해보자

curl -v https://www.tistory.com

curl -v http://www.tistory.com

curl -v http://www.tistory.com
* Host www.tistory.com:80 was resolved.
* IPv6: (none)
* IPv4: 211.183.210.24
*   Trying 211.183.210.24......
* Connected to www.tistory.com (211.183.210.24) port 80
> GET / HTTP/1.1
> Host: www.tistory.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 308 Permanent Redirect
< Date: Sun, 10 May 2026 12:36:05 GMT
< Content-Type: text/html
< Content-Length: 164
< Connection: keep-alive
< Location: https://www.tistory.com
< server: hide
< X-Content-Type-Options: nosniff
< X-Frame-Options: "allow-from tistory.com"
< X-Xss-Protection: 1
<
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host www.tistory.com left intact
  • 우선 HTTP 요청을 먼저 살펴보면 HTTPS 로 리다이렉트 되는 것을 확인할 수 있다
curl -v https://www.tistory.com

* Host www.tistory.com:443 was resolved.
* IPv6: (none)
* IPv4: 211.183.210.24
*   Trying 211.183.210.24
* Connected to www.tistory.com (211.183.210.24) port 443
* ALPN: curl offers h2,http/1.1

* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):

* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: C=KR; ST=Jeju-do; L=Jeju-si; O=AXZ Corp.; CN=*.tistory.com
*  start date: Mar 30 00:00:00 2026 GMT
*  expire date: Oct 14 23:59:59 2026 GMT
*  subjectAltName: host "www.tistory.com" matched cert's "*.tistory.com"
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Thawte TLS RSA CA G1
*  SSL certificate verify ok.

* using HTTP/1.x
> GET / HTTP/1.1
> Host: www.tistory.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
  • 다음은 HTTPS 요청이다. 실제 응답 본문 부분은 첨부하지 않았다
  • 우선 요청한 도메인의 IP를 찾는 DNS 질의 과정이 먼저 수행된다. 관련 내용은 다른 블로깅으로 찾아올 예정이다
  • IP를 찾으면 해당 IP의 443번 포트로 TCP 연결을 시도하는 것을 볼 수 있다
    • Host http://www.tistory.com:443 was resolved.
      IPv6: (none)
      IPv4: 211.183.210.24
      Trying 211.183.210.24:443...
      Connected to http://www.tistory.com (211.183.210.24) port 443
  • 이후에 바로 HTTP 요청을 보내는 것이 아니라, 위의 과정에서 설명한 TLS Handshake 과정을 확인할 수 있다
    • Client hello 와 Server hello 를 거쳐 키 교환이 진행된다
    • Client hello 에서는 클라이언트가 지원하는 TLS 버전과 암호화 방식 목록을 서버에 전달한다
    • Server hello 에서는 서버가 사용할 방식을 클라이언트에 반환한다
  • 키 교환이 종료되었으면 서버는 자기가 갖고 있는 인증서를 전달해준다
    • Server certificate:
      subject: C=KR; ST=Jeju-do; L=Jeju-si; O=AXZ Corp.; CN=*.tistory.com
      start date: Mar 30 00:00:00 2026 GMT
      expire date: Oct 14 23:59:59 2026 GMT
      subjectAltName: host "http://www.tistory.com" matched cert's "*.tistory.com"
      issuer: C=US; O=DigiCert Inc; OU=http://www.digicert.com; CN=Thawte TLS RSA CA G1
      SSL certificate verify ok.
    • 이 인증서는 DigiCert 라는 곳에서 발급한다는 것을 알 수 있다
    • 이 부분에서 클라이언트는 인증서 도메인 정보와 현재 접속한 도메인이 일치하는지 확인한다
    • 인증서 검증이 끝나면 연결에 사용할 TLS 버전과 암호화 방식이 정해진다
  • 그 후에 실제 HTTP 요청이 전송되는 것을 볼 수 있다
    • GET / HTTP/1.1
      Host: http://www.tistory.com
    • HTTP/1.1 200 OK

-> 위의 과정처럼 실제 인증서 검증 단계를 거치고 키 교환을 한 뒤 암호화된 HTTP 통신인 HTTPS 통신을 시작하게 된다

 

 

openssl s_client -connect www.tistory.com:443 -servername www.tistory.com

 

이번에는 인증서 체인 부분을 좀 더 자세히 한 번 살펴보자

 

openssl s_client -connect www.tistory.com:443 -servername www.tistory.com


Certificate chain
 0 s:C=KR, ST=Jeju-do, L=Jeju-si, O=AXZ Corp., CN=*.tistory.com
   i:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=Thawte TLS RSA CA G1
   a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Mar 30 00:00:00 2026 GMT; NotAfter: Oct 14 23:59:59 2026 GMT

 1 s:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=Thawte TLS RSA CA G1
   i:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2

 2 s:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
   i:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2

Verification: OK

New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Protocol: TLSv1.2
Server public key is 2048 bit
Verify return code: 0 (ok)

 

더 많은 출력들과 키부분도 나오지만 생략하고 인증서 체인 을 중점적으로 봤다

 

  • 위에서 확인한 인증서의 계층 구조를 그대로 확인할 수 있다 
  • s 는 Subject로 인증서의 대상을 의미한다
  • i 는 Issuer로 인증서를 발급한 기관을 의미한다 
  • DigiCert Global Root G2
    • 루트 인증서
    • 자기 자신이 자기 자신을 서명
    • 브라우저나 OS가 이미 알고 신뢰하는 시작점을 의미한다 
  • Thawte TLS RSA CA G1
    • 중간 인증서
    • 루트 인증서인 DigiCert Global Root G2 가 서명해서 신뢰할 수 있는 인증서를 의미한다
  • *.tistory.com
    • 실제 서버 인증서
    • Thawte TLS RSA CA G1 이 서명해서 발급한 인증서를 의미한다

 

인증서 체인은 신뢰가 아래로 이어지는 계층적 구조를 가진다

위의 실제 브라우저의 인증서 부분에서도 확인한 바가 있다 

 

 

 

마무리

이 글에서는 대략적인 SSL/TLS 의 개념과 인증 과정을 살펴봤다 

 

우리가 브라우저에서 HTTP 로 접속을 하려고 할 때, 왜 위험 표시를 해주는지 확실하게 알게 되었고, 이제 HTTP/HTTPS 요청을 할 때마다 이 내용을 상기시키면 기억속에 오래 남을 것 같다

 

다음 글은 DNS 질의 과정 으로 찾아올 예정이다

바뀔 수도 있긴하다

'시스템, 인프라' 카테고리의 다른 글

IP (Internet Protocol)  (0) 2026.06.14
fstab  (1) 2026.06.03
RAID  (2) 2026.05.31
DNS  (0) 2026.05.24
서버 디스크 추가  (1) 2026.05.02
'시스템, 인프라' 카테고리의 다른 글
  • fstab
  • RAID
  • DNS
  • 서버 디스크 추가
나는 허준기
나는 허준기
  • 나는 허준기
    공부
    나는 허준기
  • 전체
    오늘
    어제
    • 분류 전체보기 (17) N
      • 자바 공부 (2)
      • 알고리즘 공부 (1)
      • 일기 (0)
      • Git (2)
      • 클라우드 (3)
      • 시스템, 인프라 (9) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    TLS
    NCP
    terraform
    Linux
    로드밸런싱
    IP
    클라우드
    RAID
    Naver Cloud
    SSL
    fstab
    힙정렬
    inode
    최대힙
    IaC
    DNS
    네이버클라우드
    apache
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
나는 허준기
SSL/TLS
상단으로

티스토리툴바