HTTPS의 자물쇠 안에서 일어나는 일: TLS
TLS는 통신하는 두 끝점 사이에서 기밀성, 무결성과 인증을 제공하는 프로토콜이다. 웹에서 HTTPS는 HTTP를 TLS로 보호하는 방식으로 이해할 수 있다. 암호화가 도청을 어렵게 만들고, 인증은 통신 상대를 확인하며, 무결성은 전달 중 변경을 검출한다. 세 기능은 서로 연결되지만 같은 뜻은 아니다.
TLS는 인증된 끝점 사이의 통신을 보호하며 끝점 내부의 보안까지 대신하지는 않는다.
처음에는 어떻게 서로 믿을까
클라이언트와 서버는 핸드셰이크에서 지원하는 매개변수와 키 합의 정보를 교환한다. 일반적인 웹 연결에서는 서버가 인증서를 제시한다. 클라이언트는 인증서의 신뢰 경로, 유효 기간, 접속하려는 이름과의 일치 등을 확인해야 한다. 암호화 연결이 만들어졌다는 사실만으로 인증 검사를 생략해도 되는 것은 아니다.
TLS 1.3의 일반적인 인증서 기반 핸드셰이크에서는 키 합의와 서버의 서명, 핸드셰이크 내용에 대한 검증이 결합된다. 서버 인증서에 있는 공개키가 모든 응용 데이터를 그대로 암호화하는 단순 구조로 설명하면 실제 동작을 놓친다. 양쪽은 합의 결과로부터 통신용 키를 유도하고, 이후에는 효율적인 대칭키 암호로 레코드를 보호한다.
인증서는 도메인 이름과 키 사이의 신뢰할 수 있는 연결을 제공하는 데 쓰인다. 인증서가 유효해도 사이트의 사업이 정직하거나 게시된 내용이 정확하다는 뜻은 아니다. 또 클라이언트 인증서를 요구하지 않는 일반 웹 환경에서는 서버가 인증되었다고 사용자의 신원이 자동으로 증명되지 않는다. 로그인은 그 위의 별도 절차일 수 있다.
보호된 길의 양 끝에는 평문이 있다
응용 데이터는 TLS 레코드로 나뉘어 암호화되고 인증된다. 네트워크 중간에서 내용을 읽거나 몰래 바꾸기 어렵게 만들지만, 송신과 수신 끝점에서는 응용이 원래 내용을 처리한다. 악성 브라우저 확장, 침해된 서버, 잘못된 권한 설정처럼 끝점 내부의 문제는 TLS만으로 해결되지 않는다.
암호화된 통신에서도 관찰자가 연결의 IP 주소와 트래픽 양, 시점 같은 메타데이터를 볼 수 있다. 일부 이름 정보의 노출 여부는 사용하는 확장과 배치 조건에 따라 달라진다. TLS를 켜면 네트워크에서 모든 정보가 사라진다고 설명해서는 안 된다.
핸드셰이크에는 왕복 통신과 암호 연산의 비용이 있다. 세션 재개는 일부 비용을 줄일 수 있으나 재개 방식과 상태 관리가 중요하다. 특히 TLS 1.3의 0-RTT 데이터는 재전송 공격 가능성을 고려해야 하므로 어떤 업무 요청에도 무조건 사용해서는 안 된다. 결제처럼 반복 실행이 위험한 작업은 별도의 정책이 필요하다.
장애를 진단할 때는 TCP 연결이 안 되는 문제와 TLS 인증서 검증 실패, 프로토콜 협상 실패를 나눠 확인한다. 시계가 틀렸거나 접속 이름이 인증서와 다르면 올바른 서버처럼 보이는 곳에서도 검증이 실패할 수 있다. 실패를 없애려고 검증을 끄면 연결은 성공해 보여도 인증이라는 핵심 약속을 버릴 수 있다.
TLS를 이해할 때 가장 유용한 질문은 누가 누구를 인증하고, 어떤 데이터가 어디부터 어디까지 보호되는가이다. 중간 프록시에서 TLS를 종료하면 그 프록시는 보호 구간의 끝점이 된다. 이후 내부 서버로 가는 연결의 보호는 다시 설계해야 한다. 자물쇠 하나보다 신뢰 경계와 키의 소유자가 실제 보안의 범위를 설명해 준다.