시작하면서
SSL/TLS/HTTPS 부터 알아보자.
- SSL (Secure Socket Layer): 클라이언트와 서버 간 보안 통신을 위한 프로토콜이다.
- TLS (Transport Layer Security): SSL 에서 발전된 프로토콜. SSL/TLS 로 묶어서 부르고 있음.
- HTTPS (HTTP Secure): SSL/TLS 위에서 통신하는 HTTP
결국은 셋 모두 ‘클라이언트와 서버가 주고받는 정보가 안전하게 만드는 프로토콜’ 이라는 것인데, 그럼 TLS 에서는 어떻게 정보를 안전하게 만드는 걸까? 이해한 대로 최대한 쉽게 풀어내 보려고 한다.
대부분의 내용은 Udemy CKA 강의를 바탕으로 정리했다.
시나리오 (1) 암호화, 비대칭 키
태초에 (?) 클라이언트와 서버는 다음과 같이 통신을 시작한다.
- 클라이언트가 서버에 접속한다.
- 서버는 클라이언트에게 사용자 정보 (ID, Password) 를 요청한다.
- 클라이언트는 사용자 정보를 서버에게 보낸다.
- 이제 서버는 클라이언트의 사용자를 확인할 수 있다.
이 과정에 아무런 보안이 적용되지 않는다면, 해커가 패킷을 수집해서 ID 와 패스워드를 들여다 볼 수 있다. 평문 (plain text) 으로 전달되기 때문이다. 그렇다면 이 평문을 알아볼 수 없게 해야 한다. 암호화/복호화 (encryption/decryption) 를 해야 한다.
서버는 암호화와 복호화가 가능한 키 (key) 를 만들어 뒀다고 가정하자.
- 서버는 클라이언트에게 키를 준다. ‘이걸로 암호화해서 줘’
- 클라이언트는 서버가 준 키를 가지고 사용자 정보를 암호화해서 보낸다.
- 서버는 암호화한 정보를 복호화해서 안전하게 (?) 사용자를 확인한다.
이 시나리오의 문제는? (2) 에서 키를 보내는 패킷은 암호화되지 않는다는 점이다. 이 키를 읽게 되면, (3) 에서 보낸 정보를 해커 역시 복호화 할 수 있게 된다. 그래서 나온 것이 비대칭 키 (asymmetric key) 이다. 오래전부터 사용된 RSA 같은 것들 말이다.
이번엔 서버가 공개 키와 비공개 키를 한 쌍 (public/private key pair) 만들어 뒀다고 가정하자.
- 서버는 클라이언트에게 공개 키를 준다. ‘이걸로 암호화해서 줘’
- 클라이언트는 서버가 준 공개 키를 가지고 사용자 정보를 암호화해서 보낸다.
- 서버는 암호화한 정보를 비공개 키로 복호화해서 안전하게 (?) 사용자를 확인한다.
여기서 주목할 점은, 공개 키는 암호화할 때 쓰고 비공개 키는 복호화 할 때만 쓴다는 점이다. 그러면 복호화에 필요한 비공개 키는 해커가 알 수 없으니 안전해 보인다.
시나리오 (2) 피싱, 그리고 인증서
이번엔 해커가 패킷을 수집하는 것을 포기하고, 클라이언트나 사용자를 속여서 피싱을 했다고 가정하자.
피싱 방법은 여러 가지인데, 사회공학적 기법으로 구별하기 어려운 URL 을 사용자에게 제공하거나, 클라이언트나 DNS를 해킹하는 방법이 필요하겠다. 아무튼 해커가 준비한 가짜 사이트로 들어가게 되면, 해커가 마련한 비대칭 키를 가지고 사용자 정보가 고스란히 넘어가게 된다.
이런 시나리오를 방지하기 위해서, 서버가 보내는 공개 키를 누군가가 보증해야 하며, ‘이 공개 키는 안전합니다! 안심하고 정보를 넘겨 주십시오’ 라는 뜻의 인증서가 필요하다.
- 서버는 클라이언트에게 공개 키가 담긴 인증서를 준다.
‘이거 인증 받은 공개키야, 이걸로 암호화해서 줘’- 클라이언트는 서버가 준 인증서가 진짜인지 확인한다. (사인해 준 곳에 가서 물어보거나..)
- 클라이언트는 서버가 준 공개 키를 가지고 사용자 정보를 암호화해서 보낸다.
- 서버는 암호화한 정보를 비공개 키로 복호화해서 안전하게 (?) 사용자를 확인한다.
이렇게 공개 키를 인증받고 교환하는 모든 과정을 공개 키 기반 구조 (Public Key Infrastructure, PKI) 이라고 부른다. 그리고 PKI 의 ITU 표준이 X.509 인 것이다.
간략히 말하자면, 이 인증서에는 (1) 공개 키 (2) 서버의 신원 (호스트네임, 기관이나 개인 이름 등) (3) 인증서에 사인을 해 준 기관 (Certificate Authority, CA) 이 포함되어 있다. (CA 로부터 사인받지 않았다면 self-signed 로 표시된다)
Root 와 Intermediate 의 차이는 CA 의 공개 키를 어디서 인증 받았는지 여부에 달렸다. Root Certificate 의 공개 키는 Self-signed 이고, Intermediate Certificate 의 공개 키는 는 다른 CA 가 사인해 준 것이다. CA 에서 발급받은 일반 인증서는 Leaf Certificate 라고 부른다. (링크)
일반적인 인터넷 환경이라면 이 차이를 굳이 알 필요가 없지만, Kubernetes Cluster 를 구축하거나 운영할 때는 master node 에 위치한 Root Certificate 부터 다룰 수 있어야 한다. (K8s Cluster 의 다른 서비스와 보안 통신을 하기 위해서!)
자, 이제 여기서 해커가 생각할 수 있는 건 무엇일까?
Self-signed 인증서를 보낸다면?
위의 피싱 시나리오에서, 해커가 혼자 사인한 (self-signed) 인증서로 감싸서 던지면 되지 않을까?
이제부터는 클라이언트 (좀 더 친숙한 표현으론, 웹 브라우저) 에서 경고를 뿜는다. “이 인증서를 받았는데, 발급 기관이 없는데요? (아니면 이상한데요?)” 라고 말이다. 쉽게 말하면, 주소창에 https://
로 시작하는 주소를 입력했는데, 자물쇠 모양이 빨갛게 보이는 경우다.
해커가 CA 를 만들어 사인을 받는다면?
아예 악의적인 CA 를 만들어서, 거기서 인증서를 사인해 주면 어떨까?
대부분의 웹 브라우저는 공인된 CA 의 공개 키를 이미 내장하고 있다. 이외의 CA 와 통신하고자 한다면 브라우저가 경고를 보낸다. “이 인증서가 진짜인지 확인하기 위해, 인증서가 가리키는 CA 와 통신하려고 하는데요.. 제가 모르는 곳인데 괜찮나요?” 라고 말이다.
정리: 결국 암호화
정리를 해 보니 결국 통신 암호화를 확실히 하기 위한 일련의 역사를 되짚은 느낌이다. 용어에 통일성이 없으니 들을 때마다 어색해지기 마련이었는데, 이렇게나마 나열해 보니 두려움이 조금 사라지긴 했다.
CKA 시험에는 CSR (Certificate Signing Request) 보내는 방법까지 배우긴 하는데 거기까진 여기서 다루지 않아도 될 듯하다.