TLS는 무엇을 가리고 무엇을 남기나
주소창에 자물쇠가 떠 있으면 안전하다고 한다. 맞는 말인데 무엇이 안전한지를 정확히 아는 경우는 드물다.
그 자물쇠의 정체는 TLS다. https는 평소의 http를 TLS 위에 얹어 보낸다는 뜻이고 자물쇠는 그 잠금이 걸렸다는 표시다. 이 글은 그 표시가 실제로 무엇을 가리고 무엇을 남기는지를 본다.
TLS가 실제로 하는 일
셋이다.
내용을 가린다. 주고받는 바이트가 중간에서 읽히지 않는다.
고쳐진 것을 알아챈다. 누가 중간에서 바꿔치기하면 받는 쪽이 알아차린다.
상대가 누구인지 확인한다. 인증서로 그 서버가 자기가 주장하는 서버인지 검증한다.
셋 다 내 기기와 그 서버 사이에서만 성립한다. 서버에 도착한 뒤는 TLS의 영역이 아니다. 종단간 암호화와 갈리는 지점이 여기다.
세 번째는 한 겹 더 들여다볼 값이 있다. 인증서가 진짜인지는 무엇을 보고 판단하나. 기기에 미리 심어 둔 발급 기관 목록이다. 그 목록에 있는 기관이 서명한 인증서면 믿는다. 그러니 신뢰의 출처는 서버가 아니라 내 기기가 들고 있는 목록이다.
이 구조에서 따라오는 것이 있다. 기기를 관리하는 쪽이 그 목록에 자기 기관을 끼워 넣으면 그 기기가 보는 연결은 가운데서 풀렸다가 다시 잠길 수 있다. 회사가 준 기기에서 이야기가 달라지는 이유가 여기다.
1.3에서 인증서가 숨었다
TLS 1.2에서는 서버 인증서가 평문으로 나갔다. 인증서에는 도메인 이름이 적혀 있으니 중간에서 보는 쪽은 인증서만 보고도 어느 사이트인지 알았다.
연결을 열 때 양쪽이 주고받는 이 절차를 핸드셰이크(handshake)라고 부른다. 1.3은 그 순서를 바꿨다.
ClientHello. 클라이언트가 지원하는 버전과 암호 목록을 내밀면서 key share라고 부르는 열쇠 재료를 미리 하나 만들어 같이 보낸다. 어디에 접속하려는지도 여기 실린다.
ServerHello. 서버가 어느 방식을 쓸지 고르고 자기 key share를 실어 보낸다.
주고받은 것은 각자의 재료뿐인데 그 둘을 합치면 양쪽이 같은 비밀을 계산해 낼 수 있다. 비밀 자체는 선을 타고 흐르지 않는다. 그래서 ServerHello가 끝나는 순간 이미 열쇠가 있다.
그 뒤에 오는 것은 전부 암호문이다. 서버가 고른 확장(EncryptedExtensions)과 인증서(Certificate)와 끝났다는 신호(Finished)가 모두 그 안에 들어간다. 중간에서 보는 쪽에는 Hello 둘만 보이고 나머지는 뭉쳐진 덩어리다.
1.2는 순서가 반대였다. 먼저 어떤 방식을 쓸지 합의하고 그다음에 key share를 교환했다. 합의가 끝나야 재료를 고를 수 있으니 왕복이 한 번 더 필요했다. 1.3은 클라이언트가 서버의 선택을 미리 짐작해서 재료를 먼저 던지는 것으로 그 왕복을 없앴다. 짐작이 틀리면 서버가 다시 보내라고 한 번 돌려보낸다.
마지막 평문 조각은 SNI다
인증서가 숨었는데도 어느 사이트에 접속하는지는 여전히 드러난다. ClientHello에 목적지 이름이 실려 있기 때문이다. 이 값을 SNI(Server Name Indication)라고 부른다.
왜 평문이어야 하는지는 닭과 달걀이다. 서버 하나가 주소 하나로 여러 사이트를 맡는 일이 흔하다. 그러면 서버는 어느 사이트의 인증서를 내밀지 정해야 하는데 어느 인증서인지 정하려면 손님이 어디를 찾는지 먼저 알아야 한다. 그런데 그 시점에는 아직 암호화할 열쇠가 없다.
그래서 SNI는 TLS 1.3에서 평문으로 남은 값 가운데 가장 민감한 것이 되었다. 접속할 때마다 목적지 이름이 그대로 나간다.
평문으로 나가는 값이 SNI만은 아니다. 지원하는 버전과 암호 목록과 확장 항목이 ClientHello에 함께 실린다. 하나하나는 민감해 보이지 않는데 그 조합과 순서가 프로그램마다 달라서 지문 노릇을 한다. 어느 브라우저인지 어느 앱인지가 목적지를 몰라도 좁혀진다.
ECH가 덮으려는 것과 조건
이 마지막 조각을 덮으려는 것이 ECH다. 2026년 3월에 RFC 9849로 표준이 되었다. ClientHello를 안쪽과 바깥쪽으로 나눠서 진짜 목적지가 든 안쪽을 암호화해 보내는 방식이다.
그런데 조건이 둘 붙는다.
목적지 쪽이 설정을 DNS에 올려 두어야 한다. 브라우저는 접속하기 전에 그 설정을 받아 와야 안쪽을 잠글 수 있다. 설정이 없으면 예전처럼 평문 SNI로 되돌아간다.
DNS를 물어보는 경로도 잠겨 있어야 한다. 설정을 DNS로 받는 구조이니 그 질문이 평문으로 나가면 소용이 없다. 어디를 찾는지가 거기서 드러난다.
그래서 표준이 되었다는 것과 실제로 지켜진다는 것 사이에 간격이 있다. 브라우저 쪽은 준비되어 있지만 상대 쪽 설정과 DNS 경로가 함께 맞아야 작동한다.
그래도 남는 것
ECH가 다 맞아떨어져도 지워지지 않는 것이 있다. 먼저 연결하는 상대의 IP 주소다.
배달을 하려면 봉투 겉면은 읽혀야 한다. 어느 주소로 가는 짐인지 모르면 옮길 수가 없다. 공공 와이파이에서 무슨 말을 했는지는 몰라도 어디에 접속했는지는 보인다고 적은 이유가 여기 있다.
한 가지가 따라온다. 큰 서비스 여럿이 한 주소 뒤에 모여 있으면 주소만으로는 구별하기 어렵다. 반대로 한 서비스가 자기 주소를 따로 쓰면 주소가 곧 이름이 된다.
주소 말고도 지워지지 않는 것이 있다. 얼마나 크고 언제 오갔는지다. 내용을 잠가도 덩어리의 크기와 시각은 그대로 보인다. 짧은 것이 자주 오가면 대화이고 큰 것이 한 번에 가면 파일이다. 암호화가 다루는 층이 아니라서 잠가도 남는다.
자주 묻는 질문
SSL과 TLS는 다른 건가요
같은 계보다. SSL이 옛 이름이고 지금 쓰이는 것은 전부 TLS다. 인증서를 SSL 인증서라고 부르는 것처럼 이름만 습관으로 남았다.
https면 그 사이트를 믿어도 되나요
https는 연결이 잠겼다는 뜻이지 그 사이트가 믿을 만하다는 뜻이 아니다. 가짜 사이트도 인증서를 받아 자물쇠를 달 수 있다. 자물쇠는 상대가 그 주소의 주인이라는 것까지만 말해 준다.
VPN을 쓰면 목적지가 가려지나요
보는 사람이 바뀐다. VPN은 TLS를 풀지 않고 터널 안으로 그대로 통과시키므로 사업자도 내용은 읽지 못한다. 다만 SNI는 평문이라 어디에 접속하는지는 그쪽에 보인다. 가려진 것이 아니라 보는 자리가 옮겨진 것이다.
ECH는 제가 켤 수 있나요
브라우저 쪽은 대체로 준비되어 있다. 남은 조건이 본문에서 본 둘이다. 접속하려는 쪽이 설정을 올려 두어야 하고 DNS를 잠긴 경로로 물어봐야 한다.