SNI를 암호화하면 통제를 벗어날까 — 은닉이 끝나는 곳, CDN

SNI를 암호화하면 통제를 벗어날까 — 은닉이 끝나는 곳, CDN

요약 — 오리진 은닉과 ECH는 모두 경로 위의 관찰자를 상대하는 기술이다. ECH를 복호화하는 주체가 CDN 자신이므로, 종단인 CDN이 정책으로 거부하면 어떤 은닉도 소용없다. 트래픽을 CDN 뒤로 모을수록 관찰과 차단의 통제점은 CDN 한 곳으로 집중된다. 계층을 구분하면 진단과 설계가 모두 빨라진다.

"오리진 IP를 숨기고 SNI까지 암호화하면 그 트래픽은 아무도 통제할 수 없다." 인프라 설계 논의에서 가끔 듣는 말이다. 절반만 맞다. 이 명제는 "누가, 어디서 관찰하는가"라는 질문을 건너뛴다. 은닉 기술이 상대하는 것은 경로 위의 관찰자다. 요청을 받아 복호화하고 응답을 결정하는 종단은 처음부터 상대가 아니다. 그리고 현대 웹에서 그 종단은 대부분 CDN이다.

SNI는 무엇을 노출하나

SNI(Server Name Indication)는 TLS 핸드셰이크의 첫 메시지인 ClientHello에 담기는 접속 대상 도메인명이다. CDN처럼 하나의 IP가 수천 개 도메인을 서빙하는 구조에서, 서버는 이 값을 보고 올바른 인증서를 고른다. 문제는 전통적 TLS에서 이 필드가 평문이라는 점이다. 페이로드는 암호화돼도 목적지 도메인은 경로상의 네트워크 장비 누구나 읽을 수 있다. 기업 방화벽의 필터링과 통신사 장비의 정책 적용이 모두 이 지점에서 작동해 왔다.

ECH가 성립하는 두 가지 조건

ECH(Encrypted Client Hello)는 ClientHello 전체를, 특히 SNI를 암호화하는 TLS 1.3 확장이다. ESNI의 후속으로 2026년 3월 RFC 9849로 표준이 확정됐다.1

ECH가 실제로 동작하려면 두 요소가 모두 갖춰져야 한다.

  1. DNS 게시: 권위 DNS가 HTTPS(type65) 레코드에 ech= 공개키를 발행한다.
  2. 종단 복호화: 엣지(CDN)가 개인키로 Outer/Inner ClientHello를 분리해 처리한다.

둘 중 하나라도 없으면 브라우저는 평문 SNI로 폴백하거나 핸드셰이크가 어긋난다. 여기서 자주 헷갈리는 지점이 있다. Route 53 같은 DNS 서비스에 ech=가 담긴 HTTPS 레코드를 올리는 것은 (1)일 뿐이다. CloudFront 엣지가 (2)를 수행하지 않으면 ECH는 성립하지 않는다. 레코드 호스팅과 엣지 복호화는 별개의 기능이다.

클라이언트에서 오리진까지의 요청 경로 다이어그램. 경로 구간의 DNS 리졸버는 도메인 질의를 보고 DoH/DoT로 가려지며, 경로 중간 장비는 평문 SNI를 보고 ECH로 가려진다. 종단 구간의 CDN 엣지는 TLS를 종료하고 ECH를 복호화해 요청 전체를 본 뒤 451이나 403 같은 정책을 적용한다. 오리진은 CDN 뒤에 있어 IP가 노출되지 않는다.
암호화는 경로 위 관찰자의 눈을 가리지만, 종단인 CDN은 모든 것을 보고 결정한다.

제어는 어느 계층에서 일어나는가

콘텐츠 제어는 기업 필터링이든 지역 정책이든 법적 준수든 하나의 지점에서 일어나지 않는다. 계층마다 관찰 대상과 은닉 수단이 다르다.

계층위치관찰 대상암호화로 은닉되나
DNS리졸버도메인 질의DoH/DoT로 가능
SNI 검사경로 중간 장비평문 SNIECH로 가능
CDN/애플리케이션목적지 엣지요청 전체불가. 복호화의 주체가 종단이다

마지막 행이 이 글의 결론을 담고 있다. ECH를 복호화하는 열쇠는 CDN이 쥔다. CDN에게는 숨겨지는 것이 없다. 은닉 기술은 관찰자의 수를 줄이는 기술이지, 종단의 결정을 바꾸는 기술이 아니다.

451과 연결 리셋은 다른 말을 한다

계층 모델은 장애 진단에서 바로 힘을 낸다. 연결 실패는 계층마다 지문이 다르다.

  • DNS 계층: 이름 해석 자체가 실패한다. NXDOMAIN 같은 리졸버 응답이 남는다.
  • 경로 SNI 계층: TLS 핸드셰이크가 ClientHello 직후 끊긴다. HTTP 상태코드가 아예 없다. 브라우저에는 연결 리셋이나 연결 종료로 표시된다.
  • CDN 계층: TLS는 완성되고 HTTP 응답이 돌아온다. 정책 차단이면 451 Unavailable For Legal Reasons2, 보안 룰이면 403이다. 응답의 Server 헤더 같은 식별자가 단서가 된다.
Cloudflare가 반환한 HTTP 451 오류 페이지. 법적 사유로 이용 불가라는 제목 아래, 한국 정부의 법적 명령에 따라 한국 내 Cloudflare 서버를 통한 접근을 제한했다는 안내와 규제기관 문의 방법이 표시돼 있다. 식별 정보는 지웠다.
CDN 계층 정책의 실제 지문. TLS가 완성되고 451 응답 페이지가 돌아왔다(식별 정보는 지웠다).

핵심은 이것이다. HTTP 상태코드를 받았다는 사실 자체가 요청이 종단까지 도달했다는 증거다. 경로에서 끊겼다면 상태코드조차 받지 못한다. 451 하나로 "경로 문제인가, 종단 정책인가"의 1차 분류가 끝난다.

운영자 쪽에는 통제가 기록된다

방문자에게 451이 보인다면, 존을 운영하는 계정에는 같은 사건이 다른 형태로 남는다. Cloudflare는 계정 대시보드의 Abuse Reports에 신고 내역과 완화 조치를 기록한다. 실제 사례의 화면에서 구조가 그대로 드러난다.

Cloudflare 대시보드의 Abuse Report 화면. Cloudflare mitigations 탭에 Geo block 완화 조치가 Active 상태로 표시되고, 엔티티 타입은 URL이다. 계정 식별자, 리포트 ID, 도메인은 마스킹했다.
완화 조치는 Geo block이고 대상은 URL 패턴이다. 리포트 단위로 날짜·상태·엔티티가 관리된다(식별 정보는 마스킹).

두 가지가 눈에 띈다. 첫째, 조치가 Geo block이다. 종단은 요청의 출발지를 알기 때문에 특정 관할에서 오는 트래픽에만 정책을 적용할 수 있다. 경로 장비의 차단이 자기 앞을 지나는 트래픽 전부에 일률적으로 걸리는 것과 달리, 관할 단위의 선별 적용은 종단만이 할 수 있는 제어다. 둘째, 근거가 문서로 남는다. 접수 날짜, 조치 상태, 대상 엔티티가 리포트 단위로 관리되고, 운영자는 Trust & Safety 리뷰 요청이라는 이의 절차로 연결된다.

Abuse Report의 증거 섹션. Evidence URLs 목록과 Logs or other evidence of abuse 항목에 한국 정부가 위법 콘텐츠 카테고리를 지정했으며 법이 Cloudflare에게 재량을 주지 않는다는 문구가 기록돼 있다. URL과 카테고리명은 마스킹했다.
증거 URL과 로그. 규제기관이 지정한 카테고리가 그대로 인용되고, 법이 재량을 주지 않는다는 문장까지 남는다(식별 정보는 마스킹).

증거 항목에는 규제기관이 지정한 위법 카테고리가 그대로 인용되고, "법이 이 명령에서 벗어날 재량을 주지 않는다"는 문장까지 기록된다. 종단의 정책 차단은 CDN의 임의 판단이 아니라 법적 명령의 집행이라는 성격을 가지며, 그 근거와 범위가 운영자 관리 화면에 문서화된다. 앞서 말한 통제점의 집중이 실무에서 어떤 모습인지 보여주는 장면이다.

비슷한 과제를 다루고 계신가요?30분 무료 진단 받기

CDN마다 다른 ECH

같은 "CDN 뒤 호스팅"이라도 SNI 노출 특성은 CDN 선택에 따라 갈린다. 2026년 7월 기준 현황이다.

  • Cloudflare: 2025년 10월 전 플랜에 ECH를 GA했다.3 HTTPS 레코드에 ech= 키를 자동 게시하고 엣지에서 복호화까지 수행한다. 두 조건을 모두 채운 상태다.
  • AWS CloudFront: 뷰어(클라이언트) 측 ECH 지원 발표가 없다.4 최근의 CloudFront TLS 투자는 오리진 방향에 집중돼 있다(TLS 1.3 origin, mTLS origin). Route 53이 ech= 레코드를 호스팅할 수 있다는 사실이 이 공백을 가리기 쉽다.
  • 서버 진영: NGINX 1.29.4가 네이티브 ECH 지원을 실었다. 단 OpenSSL의 ECH feature branch가 필요하고, 안정판 편입은 OpenSSL 4.0으로 예고됐다.5

계층을 특정하는 진단

운영 중 만나는 연결 문제를 계층으로 분류하는, 재현 가능한 진단 절차다.

ECH 게시 확인. 도메인의 HTTPS 레코드에 ech=가 있는지 본다.

dig example.com type65 +short

결과는 이렇게 갈린다. ECH를 게시한 도메인은 HTTPS 레코드가 바이너리 블롭으로 돌아오고, 게시하지 않은 도메인은 빈 응답이다.

$ dig example-a.org type65 +short
\# 136 000100000100060268330268320004000868152384AC43DE92000500
       470045FE0D004165002000206D6ED8B048EDBCDA3DBCDE74FC3CF52E
       D8C6DB3F991F733282F117CDA36F8A6B0004000100010012636C6F75
       64666C6172652D6563682E636F6D0000000600202606470030360000
       0000000068152384260647003037000000000000AC43DE92

$ dig example-b.org type65 +short
$

블롭 안에 ech= 설정이 그대로 들어 있다. 셋째 줄 끝에서 넷째 줄로 이어지는 636C6F75 64666C6172652D6563682E636F6D 구간을 ASCII로 풀면 cloudflare-ech.com, Outer ClientHello에 실릴 public name이다. ECH의 조건 (1), 곧 공개키의 DNS 게시가 충족돼 있다는 증거다.

함정이 하나 있다. 일부 dig 버전은 dig -t HTTPSdig https를 "invalid type"으로 무시하고 A 레코드 조회로 폴백한다. 숫자형 type65가 안전하다. 리졸버가 HTTPS 레코드를 스트립하는지 의심되면 로컬 리졸버와 공개 리졸버(@1.1.1.1, @8.8.8.8)를 교차 비교한다.

끊기는 계층 확인. 같은 IP에 SNI 값만 바꿔 핸드셰이크를 비교한다.

openssl s_client -connect <IP>:443 -servername example.com

특정 SNI에서만 ClientHello 직후 연결이 끊기고 다른 SNI는 서버 응답까지 도달한다면, 경로의 장비가 SNI 값을 기준으로 작동하고 있다는 뜻이다. 두 경우의 출력은 첫 줄부터 다르다.

ClientHello 직후 끊긴 연결의 전체 출력
$ openssl s_client -connect <edge-ip>:443 -servername example-a.org
Connecting to <edge-ip>
CONNECTED(00000003)
error:0A000126:SSL routines::unexpected eof while reading:ssl/record/rec_layer_s3.c:703:
---
no peer certificate available
---
No client certificate CA names sent
Negotiated TLS1.3 group: <NULL>
---
SSL handshake has read 0 bytes and written 1552 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Protocol: TLSv1.3
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
error:0A000197:SSL routines:SSL_shutdown:shutdown while in init:ssl/ssl_lib.c:2804:

핵심은 세 줄이다. unexpected eof while reading, no peer certificate available, 그리고 read 0 bytes. ClientHello 1552바이트를 써 보냈는데 한 바이트도 돌아오기 전에 연결이 닫혔다. 인증서도, 암호군 협상도, HTTP 상태코드도 없다.

같은 명령이 서버까지 도달하면 첫 화면부터 인증서 체인이 쏟아진다.

서버까지 완주한 핸드셰이크의 전체 출력
$ openssl s_client -connect <edge-ip>:443 -servername example-b.com
Connecting to <edge-ip>
CONNECTED(00000003)
depth=3 C=US, O=Internet Security Research Group, CN=ISRG Root X2
verify return:1
depth=2 C=US, O=ISRG, CN=Root YE
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=YE1
verify return:1
depth=0 CN=example-b.com
verify return:1
---
Certificate chain
 0 s:CN=example-b.com
   i:C=US, O=Let's Encrypt, CN=YE1
   a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA384
   v:NotBefore: Jun 20 00:37:09 2026 GMT; NotAfter: Sep 18 00:37:08 2026 GMT
 1 s:C=US, O=Let's Encrypt, CN=YE1
   i:C=US, O=ISRG, CN=Root YE
   ...
---
Server certificate
-----BEGIN CERTIFICATE-----
(생략)
-----END CERTIFICATE-----
subject=CN=example-b.com
issuer=C=US, O=Let's Encrypt, CN=YE1
---
Peer signing digest: SHA256
Peer signature type: ecdsa_secp256r1_sha256
Negotiated TLS1.3 group: X25519MLKEM768
---
SSL handshake has read 4963 bytes and written 1620 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Verify return code: 0 (ok)
---

read 4963 bytes, 협상된 암호군 TLS_AES_256_GCM_SHA384, Verify return code: 0. 종단까지 완주한 연결의 지문이다. 앞의 출력과 나란히 놓으면, "어느 계층에서 끊겼나"가 명령 하나의 출력 차이로 판별된다.

판단

아키텍처 관점의 테이크어웨이는 네 가지다.

  1. 은닉은 통제 불가와 같은 말이 아니다. 오리진 IP 은닉과 SNI 은닉(ECH)은 제3자 관찰자를 상대한다. 목적지 CDN이 정책적으로 거부하기로 하면 두 기술 모두 무력하다.
  2. 통제점은 CDN으로 집중된다. 트래픽을 CDN 뒤로 모을수록 관찰·차단·컴플라이언스의 단일 통제점이 CDN이 된다. 오리진 보호라는 보안 이점인 동시에, 거버넌스와 가용성의 단일 실패점이기도 하다.
  3. 계층을 알면 진단이 빨라진다. 상태코드가 있느냐 없느냐만으로 경로 문제와 종단 정책의 1차 분류가 된다.
  4. ECH는 CDN 선택의 숨은 변수다. HTTPS 레코드 게시와 엣지 복호화 지원 여부가 CDN마다 달라, 서비스의 프라이버시와 노출 특성에 직접 영향을 준다.

이런 계층 구분 위에서 인프라의 통제·컴플라이언스 요구를 설계할 팀이 필요하다면 클라우드 & 인프라에서, 규제 대응을 포함한 전환 전략이 고민이라면 AX 컨설팅에서 시작할 수 있다.

참고 자료

Footnotes

  1. RFC 9849, "TLS Encrypted Client Hello" (2026-03). ESNI를 대체하는 표준. https://www.rfc-editor.org/rfc/rfc9849

  2. RFC 7725, "An HTTP Status Code to Report Legal Obstacles" (451). https://www.rfc-editor.org/rfc/rfc7725

  3. Cloudflare, "Encrypted Client Hello - the last puzzle piece to privacy". 전 플랜 ECH 제공(2025-10-03) 공지. https://blog.cloudflare.com/announcing-encrypted-client-hello/

  4. Amazon CloudFront 개발자 가이드, "Supported protocols and ciphers between viewers and CloudFront". 2026-07 확인 기준 뷰어 측 ECH 언급 없음. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html

  5. NGINX Community Blog, "Encrypted Client Hello Comes to NGINX" (NGINX 1.29.4). https://blog.nginx.org/blog/encrypted-client-hello-comes-to-nginx

이런 작업, 직접 맡기고 싶다면.

30분 무료 상담으로 방향부터 잡아드립니다.

이미 금융·헬스케어·미디어·공공의 팀들과 함께
이 주제로 30분 이야기하기
30분 무료 진단 받기