쿠버네티스 외부 노출 작업을 하다가 "TLS termination을 어디서 할지 정해야 한다"는 얘기가 나왔는데, 정작 나는 TLS가 뭔지부터 흐릿했다. HTTPS의 자물쇠 아이콘은 매일 보면서도 그 안에서 무슨 일이 벌어지는지는 한 번도 제대로 안 들여다봤던 거다. 그래서 HTTP와 HTTPS가 뭐가 다른지부터, TLS가 실제로 무엇을 해주는지까지 정리했...
쿠버네티스 외부 노출 작업을 하다가 "TLS termination을 어디서 할지 정해야 한다"는 얘기가 나왔는데, 정작 나는 TLS가 뭔지부터 흐릿했다. HTTPS의 자물쇠 아이콘은 매일 보면서도 그 안에서 무슨 일이 벌어지는지는 한 번도 제대로 안 들여다봤던 거다. 그래서 HTTP와 HTTPS가 뭐가 다른지부터, TLS가 실제로 무엇을 해주는지까지 정리했다.
HTTP로 주고받는 데이터는 평문이다. 암호화가 전혀 없다. 비유하자면 엽서를 부치는 것과 같다. 우체부도, 중간에 거치는 누구도 내용을 그대로 읽을 수 있다.
문제는 인터넷에서 내 요청이 목적지까지 가는 동안 여러 중간 지점(공유기, ISP, 중간 서버)을 거친다는 점이다. HTTP면 그 중간 어디서든 비밀번호, 카드번호, 응답 내용이 다 보인다. 가로채는 것도, 내용을 몰래 바꾸는 것도 가능하다.
HTTPS는 새로운 프로토콜이 아니다. HTTP를 TLS라는 보안 계층으로 한 번 감싼 것이다.
엽서 비유를 이어가면, HTTPS는 봉인된 봉투다. 받는 사람만 뜯어볼 수 있고, 중간에 누가 봉투를 바꿔치기하면 받는 쪽이 알아챈다.
TLS는 두 개의 다른 문제를 동시에 해결한다. 이 둘을 구분하는 게 중요하다.
암호화는 다음의 "자물쇠" 얘기로, 신원 확인은 "인증서" 얘기로 이어진다.
암호화에는 두 방식이 있다. TLS는 둘을 영리하게 섞어 쓴다.
대칭키 — 잠그는 열쇠와 여는 열쇠가 같다. 빠르다. 문제는 "그 열쇠를 어떻게 상대에게 안전하게 전달하느냐"다. 열쇠를 그냥 보내면 중간에서 가로채니까.
비대칭키 — 열쇠가 한 쌍이다. 공개키(public key)로 잠그면 개인키(private key)로만 열린다. 공개키는 아무에게나 줘도 된다. 누가 공개키로 잠가 보내도, 개인키를 가진 나만 열 수 있으니까. 대신 느리다.
TLS는 이렇게 조합한다.
느린 비대칭키는 "열쇠를 건네는 순간"에만 쓰고, 빠른 대칭키로 본 통신을 한다. 안전함과 빠름을 둘 다 가져가는 절충이다.
암호화는 됐는데, "내가 받은 공개키가 진짜 그 서버의 것"이라는 보장은 누가 해줄까? 여기서 인증서(certificate)가 등장한다.
인증서는 서버의 신분증이다. 안에 서버의 공개키와 "이 공개키는 my-service.com의 것이 맞다"는 보증이 들어 있다. 이 보증을 해주는 게 CA(Certificate Authority, 인증기관)다.
신원 보증의 흐름은 이렇다.
즉 신뢰의 뿌리는 "브라우저/OS가 미리 믿기로 한 CA들"이다. 그래서 아무 인증서나 만들어 붙인다고 되는 게 아니라, 신뢰받는 CA가 서명한 인증서여야 한다.
실제 데이터를 주고받기 전에, 클라이언트와 서버는 짧은 협상을 한다. 이걸 TLS handshake라고 한다. 대략 이런 순서다.
이 왕복 횟수를 줄이는 게 버전 발전의 핵심이었다. TLS 1.2는 왕복 2번(2-RTT)이 필요했는데, TLS 1.3은 왕복 1번(1-RTT)으로 줄여서 더 빠르고, 더 많은 부분을 암호화한다. 지금 새로 구성한다면 TLS 1.3을 기준으로 보면 된다.
여기가 인프라 작업에서 실제로 결정해야 하는 지점이다. TLS termination은 "암호화된 트래픽을 어디서 풀어서(복호화) 평문으로 바꾸느냐"를 말한다. 인증서는 바로 그 지점에 있어야 한다.
외부 트래픽이 Pod까지 닿는 경로에서 봤듯, 외부 요청은 보통 LoadBalancer → Ingress Controller → Service → Pod를 거친다. 봉투(TLS)를 뜯는 위치는 보통 둘 중 하나다.
어느 쪽이든 "인증서를 누가 들고, 누가 갱신하느냐"가 따라온다. 인증서는 유효기간이 있어서 주기적으로 갱신해야 하는데, 이 운영 부담을 어디에 둘지가 결정의 일부다.
내가 맡은 작업의 맥락은 이랬다. 그동안 외부 HTTPS 처리(봉투 뜯기 + 인증서)는 앞단의 API Gateway가 전부 해주고 있었다. 클라이언트 ↔ API Gateway 구간만 HTTPS였고, 그 안쪽(쿠버네티스 내부)은 평문 HTTP였다. 그래서 클러스터 안의 모든 경로가 HTTP로 되어 있었던 거다.
API Gateway를 걷어내면, 이 봉투 뜯는 역할을 LoadBalancer나 Ingress Controller가 넘겨받아야 한다. "외부로 열었다"는 곧 "인터넷에 평문으로 열면 안 된다"는 뜻이라, TLS termination 위치와 인증서 관리 방식을 반드시 정하고 넘어가야 한다.
테스트 단계에서는 사내 IP만 접근하도록 막아두고 평문 HTTP로 경로부터 검증할 수 있지만, 진짜 외부에 공개하는 순간 TLS는 선택이 아니라 필수가 된다.
자물쇠 아이콘 하나에 이렇게 여러 단계가 숨어 있는 줄 몰랐는데, 외부 노출을 직접 다뤄보니 왜 이게 매번 까다로운 결정이 되는지 알 것 같다.