Domain 과 SSL 에 대하여 (부제 : https 는 뭘까?)
제목 : Domain 과 SSL 에 대하여
이 글을 작성하게 된 계기
이전에 팀 프로젝트를 수행 할 때, DevOps 역할을 맡았던 내가 골머리를 썩혔던 구간이,
바로 Domain 과, SSL 부분이었다.
나는 백엔드 서버를 단순 IP 로서 접근하게 만들기보다는,
도메인을 통해 정확한 백엔드 서버로 도착하게 만들고 싶었다.
그 이유가, NestJS 에서 API 목록 제공 시 사용하는 외부 API 가 Swagger 라는 라이브러리인데,
이는 백엔드 루트 주소에서 특정 루트로 입장 시 내가 작성한 API 코드를 자동으로 인식하여
목록으로 정돈되어 보여주기 때문이었다.
나는 AWS EC2 + RDS (MariaDB) 를 사용하였는데,
EC2 (Amazon Linux) 를 기반으로 처음부터 프로그램을 설치하여 Express 어댑터 기반의 NestJS 를 만들었다.
지금은 프로젝트를 수행했기 때문에 안 사실이지만, EC2 에서 https
프로토콜을 지원하기 위해서는
특정 프로그램을 설치하고, 적용해야 한다는 것이었다.
이 때 도메인 이름을 적용하는 방식과 SSL 을 무료로 사용하는 방법(Let's Encrypt) 을 알게 되었다.
그런데, 나는 웹 사이트 개발과 배포 과정에서
수많은 사이트 프로그램들이 도메인 이름과 SSL 인증서를 동시에 지원해 주기 때문에,
웹 사이트 배포 시 이를 신경쓰지 않아도 된다는 것을 발견했다.
이런 과정을 대신 해 주기 때문에, 배포 시 https
프로토콜을 지원하는 자신의 웹을 볼 수 있다.
나는 프로젝트 시 WAS(백엔드) 파트를 맡았기 때문에,
웹에서 제공하는 https
프로토콜을 지원하기 위해 도메인과 ssl 을 설치하고 적용했다.
이 과정이 힘들었던 이유는, 도메인과 ssl 의 개념에 대해서 알지 못한 채 적용했기 때문이라고 생각한다.
뿐만 아니라, 어떻게 웹사이트 자동 배포 사이트에서 https
를 쉽게 적용했을까 의문이 들기 시작했다.
이들도 결국 도메인과 ssl, Certificate 라는 개념에 대해 정확히 알고 있기 때문에,
개발자들의 편의 니즈를 정확히 건드린 것이라고 생각한다.
그리고 혹시 아는가? 내가 이 개념을 배우는 과정에서 또 다른 편의성 프로그램을 만들지는 미지수다.
따라서 이 개념과 인증이 어떤 역할을 해주는지 정확하게 알기 위해서 이 글을 작성하며 배운다.
도메인 (Domain) 이란 무엇인가?
모든 서버는 IP 주소를 갖는다.
이 때, IP 주소는 2 가지 버전을 가진다.
1. IPv4 버전
EX - xxx.xxx.xxx.xxx
각각의 숫자 파트를 xxx
로 표현했으며, 0
~ 255
까지 할당 할 수 있다. (맨 앞은 254
까지인듯)
이는 각 숫자의 파트가 8비트를 가지기 때문이다.
이 버전의 IP 는 각종 디지털 디바이스가 늘어나기에 빠르게 소진되어 IPv6 라는 새로운 버전이 생기게 되었다.
2. IPv6 버전
IPv4 의 주소가 빠르게 소진됨과 동시에, 새로이 만들어지는 스마트 기기에 IP 주소를 할당하기 위해 나타난 체계이다.
EX - xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
총 8 개의 파트를 가지고 있는데,
IPv4 에서 xxx
는 10 진수이며, 0
~ 255
까지 값을 가진 반면에,
IPv6 에서는 각 숫자 표기법이 다르다.
각 x
는 0
~ e
로 표현되는데, 이는 16진수 표기법이다.
그래서, 20ab:8ae9:....:5be9
이러한 형식으로 작성 할 수 있다.
IPv4 의 $256^4$ 주소 영역과, IPv6 의 $(16^4)^8$ 를 비교 해 본다면,
IPv4 에 비해 IPv6 가 얼마나 방대한 주소 영역을 가지는지 알 수 있다.
IPv4 : 2^32 개, IPv6 : 2^128 개
다시 돌아와서, 도메인 이름은 IPv4 이던, IPv6 이던 굉장히 복잡한 숫자로 표현되므로,
이러한 숫자를 쉽게 문자열로 입력하여 검색 할 수 있도록 IP 와 연결된 문자열을 "도메인 이름" 이라고 한다.
우리는 naver.com
을 IP 주소로 입력하지 않는다.
문장으로 되어 있으니, 사람이 잘 기억할 수 있는 것이다.
그러나, 수많은 서버가 생기면서 당연히 수많은 도메인 이름 또한 생겨났다.
이를 관리해야 할 체계가 필요하면서, 도메인 이름에 따른 관리 서버가 생겨났다.
이 체계를 바로 "도메인 체계" 라고 부른다.
위에서 언급한 네이버의 .com
또한 DNS (Domain Name System) 의 최상위 서버이다.
.com
, .org
, .net
, ... 등등 여러가지 최상위 도메인이 존재한다.
예를 들어, 한국 도메인의 경우 .kr
이 있으며, 주로 .co.kr
를 많이 보았을 것이다.
예를 들어서, damsoon.co.kr
사이트가 있다고 가정 해 보자.
우리는 이 사이트를 현재 탐색하려는 기기에서 검색 한 적이 없다고 가정한다.
그렇다면, 내 기기의 DNS Resolver 는 제일 먼저 어디로 요청을 보낼까?
먼저, root 도메인 이름 서버 (Root Domain Name Server)로 요청을 보낸다.
그리고, TLD (Top Level Domain) 인 kr
도메인 이름 서버에 요청을 보낸다.
kr
도메인 이름 서버는 co
도메인 이름 서버에 요청을 보낸다.
co
도메인 이름 서버는 damsoon
사이트의 IP 주소를 반환한다.
이것을 그래프로 변환 해 본다면,
참고로, TLD 는 Top Level Domain Name Server 를 의미하고,
SLD 는 Second Level Domain Name Server 를 의미한다.
flowchart TB
subgraph Client-Device
Client("클라이언트")
Client-DNS-Resolver("클라이언트 DNS Resolver")
Client <--> Client-DNS-Resolver
end
subgraph DNS-Servers
Root-Server[".(Root)"]
TLD[".kr(TLD)"]
SLD[".co(SLD)"]
Damsoon("damsoon IP 주소!")
Root-Server <--> TLD
TLD <--> SLD
SLD <--> Damsoon
end
Client-Device ~~~ DNS-Servers
Client-DNS-Resolver <--> Root-Server
위의 상황에서 "한 번도 방문 한 적 없다" 라고 조건을 걸었는데,
이는 검색 했을 경우, DNS 서버에서 찾을 필요가 없고,
로컬 기기에서 찾고 끝이기 때문이다.
항상 어딘가에 웹을 요청하기 위해 DNS 서버에 이름을 찾게 된다면,
이는 네트워크 상으로 큰 문제일 것이다.
따라서, 로컬 기기의 브라우저, 혹은 DNS Resolver 가 문자열에 해당되는 도메인 이름을 캐싱 해 놓는다.
여기서 우리가 깨닫을 수 있는 것은,
우리가 문자열로 특정 웹 사이트를 방문 하게 된다면, 무조건 DNS 서버에서 IP 주소를 가져 온 적이 있다는 것이다.
그리고, 이러한 DNS 서버들은 전 세계에 퍼져 있다.
원하는 도메인 이름은 구입해야 한다.
이것이 포인트인데, 사용자들이 편히 웹 사이트에 접근하기 위해서는 도메인 이름을 사용하는데,
이를 등록 해 주는 사이트와, 관리하는 네임서버 회사들이 따로 존재한다는 것이다.
kisa 사이트에서 등록대행자 회사를 선택하고 구입이 가능 한 것으로도 알고 있지만,
특히 한국에서 Gabia (가비아) 사이트가 굉장히 유명하다.
.com
과 같은 유명한 TLD 의 경우, 오만원에서 십만원 쯤 하며,
본 적 없는 것 같아 보이는 도메인의 경우 거의 공짜 수준으로 사용 할 수 있기도 하다.
SSL 이란 무엇일까?
먼저, SSL 인증서를 알아보기 전에, 이에 대한 개념을 정확하게 짚고 넘어가야 한다고 생각했다.
SSL 이란, (Secure Sockets Layer) 의 약자이다. 암호화 기반 인터넷 보안 protocol 이다.
공식문서를 보니까, TLS 는 SSL 의 다음 버전이며 현재도 사용되고 있는 것은 TLS 인데,
사람들이 혼용하여 사용하여 그냥 SSL 을 말하면 TLS 로 인식하면 된다고 한다.
즉, "SSL 인증서"는 사실 공식적으로 "TLS 인증서" 라고 한다.
나도 공식적으로는 TLS 라고 인식하겠지만, 편하게 SSL 이라고 부르겠다.
다시 돌아와서, SSL 을 사용하는 웹 사이트는 https
를 사용한다.
왜 기존의 http
프로토콜을 사용하지 않느냐 하면,
우리가 작성해야 서버로 보내는 정보들이 전부 평문으로 전달되기 때문이다.
로그인 form 에서 이메일과 비밀번호를 평문으로 전달했다고 가정 해 보자.
갖은 방식으로 데이터를 탈취하는 스푸퍼들은 해석 할 필요도 없이 나의 계정을 탈취 할 것이다.
따라서, 이러한 스푸핑을 막기 위해, 웹 사이트는 SSL 인증서를 전달하여
보안성과 무결성을 챙겼다.
SSL/TLS 을 더 정확히 정의 해 보자.
SSL/TLS 는 일종의 암호화 과정 규약이라고 말할 수 있다.
어떤 과정을 거치느냐면, SSL/TLS 핸드셰이크를 수행한다. 이는 TCP 핸드셰이크랑은 엄연히 다르다.
TCP 의 경우, DNS 조회를 통해 IP 를 알고 나서,
브라우저와 웹 서버가 이러한 TCP 핸드셰이크 과정을 거친다.
sequenceDiagram
Client->>Server: SYN
Server->>Client: SYN + ACK
Client->>Server: ACK
양측의 서버 통신이 양호함을 확인 한 후, TLS 핸드셰이크 과정을 수행한다.
sequenceDiagram
Client->>Server: ClientHello
Server->>Client: ServerHello + Certificate
Server->>Client: ServerHelloDone
Client->>Server: ClientKeyExchange + ChangeCipherSpec
Client->>Server: Finished
Server->>Client: ChangeCipherSpec
Server->>Client: Finished
TLS 는 인터넷 통신을 위한 암호화 및 인증 프로토콜이다.
TLS 핸드셰이크는, TLS 암호화를 사용하는 통신 세션을 실행하는 프로세스이다.
여기서 핸드셰이크 중에, 양 측에서는 메세지를 교환하여 서로를 인식하고, 검증하며,
사용할 암호화 알고리즘을 구성하고 세션 키에 합의한다. (그래서 TLS Negotiation(협상) 이라고 부르는듯.)
위에서 표현된 Certificate
는, SSL 인증서를 의미한다.
ClientHello 란?
이 메세지에는 클라이언트가 지원하는 TLS 버전, 암호 제품군,
그리고 "Client Random" 이라고 부르는 무작위 바이트 문자열이 포함된다.
ServerHello 란?
클라이언트 헬로 메세지의 응답으로 서버의 SSL 인증서,
서버에서 선택한 클라이언트와 호환되는 암호 제품군,
그리고 서버 측에서 생성한 무작위 바이트 문자열 "Server Random" 을 보낸다.
ServerHelloDone 이후,
클라이언트는 서버로부터 받은 SSL 인증서를 CA (인증서 발행 기관) 을 통해 검증한다.
인증서를 검증하는 과정에서, 서버가 실제로 인증서에 명시된 서버인지,
그리고 클라이언트가 상호작용 중인 서버가 실제 해당 도메인의 소유자인지 확인한다.
맞다면, 이제 브라우저에서 경고문 없이 https
프로토콜로 통신할 수 있다.
세션 키와 예비 마스터 키 생성 및 대칭화 과정은 넣지 않았다.
더 정확한 정보를 알고 싶다면,
https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/
여기에 방문하면 된다.
SSL 인증서는 무엇을 포함하고, 어떤 역할을 하는가?
이제 SSL/TLS 암호화 과정을 알게 되었으니, 중간에서 전달되는 Certificate 인 SSL 인증서가
어떤 역할을 하는지 알아봐도 좋다고 생각한다.
SSL 인증서는 단일 데이터 파일에 이러한 정보들을 포함한다.
- 인증서가 발급된 대상 도메인 이름
- 발급 받은 사람 혹은 조직(회사) 혹은 장치
- 발급해준 인증 기관(CA)
- 인증 기관의 디지털 서명
- 관련 하위 도메인
- 인증서 발급 날짜
- 인증서 만료 날짜
- 공개 키 (개인 키는 비밀)
만약에 SSL/TLS 인증서가 제대로 효력을 발휘하지 않는다면,
브라우저에 "안전하지 않음" 이라는 경고문이 뜨며 사용자가 알아차릴 수 있다.
SSL 인증서 받는 법
나는 처음 도메인을 발급받을 때, 도메인 지정과 함께 SSL 인증서도 함께 받는 줄 알았다.
그런데, 그것이 아니고, 도메인 발급 후 해당 도메인으로 SSL 인증서를 발급해야 했다.
여기서, 클라이언트 브라우저에서 신뢰받는 웹으로 뜨고 싶다면, 인증 기관(CA) 에서 SSL 인증서를 발급받아야 한다.
물론, 도메인에도 수수료를 부과받지만, SSL 인증서에도 수수료가 부과된다는 점이다..
SSL 인증서가 발급되었다면, 이는 실제 웹 서버에 설치하고 활성화 시켜야 한다.
이러한 인증서는 httpd
나, nginx
와 같은 서버에서 인식하게 만들 수 있으며,
각 웹 서버는 컨벤션 된 위치나 공식 문서에서 말하는 위치에 배치하고,
설정 파일 EX-.conf
파일에서 SSL 인증서 파일의 경로를 제공하여 매칭시킬 수 있다.
무료 SSL/TLS 인증서 받는 법
나의 경우, Let's Encrypt 라는 사이트에 들어가서 ssl 인증서를 받는 법을 알게 되었다.
이 사이트에서는 무료로 ssl 을 얻을 수 있는 프로그램을 제공했는데, 이는 파이썬 기반이었던 것으로 기억한다.
무료로 받은 인증서에 대한 만료 기간을 설정하고, 또한 언제 또 새로 갱신할지에 대해서도 지정할 수 있었다.
아마 그 때 당시 서버의 cron job 을 통해 정각에 새로운 ssl 인증서를 받도록 설정했던 것으로 기억한다.
혹은, 내가 현재 읽고 있는 Cloudflare 공식 문서에서도 자사의 ssl 인증서를 무료로 제공한다고 말한다.
Cloudflare 사이트의 Universal SSL 공식 문서
이번 글을 작성하면서 배운 점
간단히 웹을 배포해 주는 프로그램이나 웹 사이트는 내부적으로 도메인과 ssl 인증서를 자동으로 보급 해 준다.
그러나, 이러한 무료 사이트는 특정 트래픽 이상, 혹은 특정 프로젝트 수 이상 을 달성한다면,
그 때 부터 요금이 붙기 시작한다.
물론, 개발 과정과 특정 스타트업의 성장 과정에서 이렇게 편리한 프로그램을 사용하는 것은,
개발 비용과 시간을 줄이는 것이라 매우 유용한 것이 사실이다.
나 또한, 웹을 프로덕션으로 놓는다면,
Github Pages 혹은 Vercel, Netlify 와 같은 정적 웹 페이지 serving 프로그램을 사용할 것이다.
개발 과정에서는 무료라고 봐도 무방하기 때문이다.
그러나, 실제 프로덕션 상황에 직면하고 보안이 더 중요해 질 때,
도메인 이름을 지정하고, 상황에 맞는 SSL 인증서를 발급하는 방법을 아는 것이 매우 중요하다고 생각된다.
요약하자면
웹 페이지를 개발하는 과정에서 편리한 사이트와 프로그램을 이용하여
클라이언트에게 페이지를 쉽게 서빙하더라도,
도메인 이름 커스텀과 그 적용 과정에서는 위와 같은 정보가 필요하다고 생각한다.
특히, 개발을 편하게 해 주는 서비스들은, 우리가 설정하지 않았으며,
모르는 과정을 인질잡아 언제 요금을 높일지 모르기 때문이다.
참고 사이트
한국인터넷정보센터(KRNIC) 의 "도메인이란?"
https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/resources/domainInfo/domainInfo.jsp
위키백과 (IP 주소)
https://ko.wikipedia.org/wiki/IP_%EC%A3%BC%EC%86%8C
위키백과 (IPv4)
https://ko.wikipedia.org/wiki/IPv4
위키백과 (IPv6)
https://ko.wikipedia.org/wiki/IPv6
Cloudfalre (DNS 란 무엇입니까?)
https://www.cloudflare.com/ko-kr/learning/dns/what-is-dns/
Cloudflare (SSL 인증서란 무엇입니까?)
https://www.cloudflare.com/ko-kr/learning/ssl/what-is-an-ssl-certificate/
Cloudflare (TLS 핸드셰이크의 원리는 무엇일까요?)
https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/