부제: 21세기에 HTTP를 쓰는, HTTPS가 HTTP보다 무겁고 느리다고 믿는 웹 서버 관리자들에게 고함

크로미움 개발 팀이 향후 공개될 크롬 62 버전부터는 HTTP로 사이트에 접속했을 때 시크릿 모드에서는 항상 "안전하지 않음"으로 표시하고 일반 모드와 시크릿 모드 모두 데이터를 입력하려 할 때 "안전하지 않음"을 띄우겠다고 발표했습니다.

많이 알려진 대로 HTTP는 해커의 공격 및 스니핑에 매우 취약한 프로토콜입니다. 복잡한 중간자 공격(MITM)을 할 필요도 없고, DNSSEC이 적용되지 않은 도메인에 대해 다른 IP 주소를 반환하여 사용자를 해커가 만든 가짜 사이트에 보내도 HTTPS를 사용하지 않으면 이 사이트가 진짜인지 가짜인지 판별하기 어려운 경우가 많습니다. 이를 해결하기 위해 HTTPS(HTTP + Secure)라는 프로토콜이 등장하고 이는 HTTP 프로토콜에 SSL/TLS 레이어를 입힌 형태로 구현되었습니다. 그리고 이러한 간단한 구현은 서버와 클라이언트 모두에게 몇몇 문제를 낳았습니다.

암호화 비용

HTTPS는 실제 통신이 이루어지기 전에 적으면서도 많은 과정이 필요했습니다. handshake라고 불리는 이 과정은 다음과 같은 형태로 나타낼 수 있습니다. 아래 이미지에 대한 설명은 http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html 를 참고하시기 바랍니다.

실제 통신이 이루어지기 전에 서버와 클라이언트 모두 사용할 수 있는 암호화 알고리즘을 교환하고 상응하는 키를 교환한 후에 데이터가 안전하게 교환될 수 있으며 요즘에는 주로 DHE-RSA 방식(RSA: 서명, Diffie-Hellman: 키 교환)이 이용됩니다. 또한 이러한 과정 뿐 아니라 OCSP(Online Certificate Status Protocol)라 불리는 인증서 검증 프로토콜을 통해 실제로 내가 받은 인증서 및 루트 인증 기관이 현재 유효한지에 대한 확인까지 진행하게 됩니다.

다행인 점은 위 과정이 모두 마친 후의 실제 데이터 통신은 (매우 빠른)대칭키로 암호화하여 진행된다는 점입니다. 여기에 Keep-Alive를 이용하면 세션이 유지될테니 암호화 비용이 약간 줄어들겠죠.

암호화에 시간이 오래 걸리는 부분은 암호학적으로 "더 안전하다" 라고 표현할 수 있는 부분입니다. 하지만 웹은 성능을 중요시 합니다. 매 요청마다 이런 handshake를 진행하고 통신을 한다면 서버와 클라이언트 모두 큰 부하가 발생할 수 밖에 없습니다. 과거에는 이러한 부분이 HTTP 서버를 HTTPS로 전환하는데 매우 큰 걸림돌이 되었으며 이는 아직까지 많은 서버 개발자 및 관리자의 머릿속에 "HTTPS를 느리고 서버 부하가 크다"라고 이미지를 박아넣는 원인이 되었습니다.

HTTPS 적용 사례

하지만 2010년 이후로는 이야기가 좀 다릅니다. HTTPS 암호화에 쓰이는 TLS는 크게 변한 것이 없는데 반해, 클라이언트와 서버에 쓰이는 CPU와 메모리 모두 성능이 과거와는 비교할 수 없을 정도로 매우 좋아졌습니다. 다음 비공식적인 RSA 벤치마크를 확인해보겠습니다. (openssl speed rsa 명령어, multi 사용X)

Intel XEON 5130 (Mac Pro 2007, i5-3570K와 유사한 성능)

                  sign    verify    sign/s verify/s
rsa  512 bits 0.000148s 0.000010s   6778.9  96769.7
rsa 1024 bits 0.000499s 0.000029s   2005.4  34371.6
rsa 2048 bits 0.003225s 0.000100s    310.1  10036.3
rsa 4096 bits 0.023140s 0.000367s     43.2   2727.1

Intel Core i7-2600 (2011)

sign    verify    sign/s verify/s
rsa  512 bits 0.000054s 0.000004s  18556.8 267823.0
rsa 1024 bits 0.000158s 0.000010s   6317.2  99584.9
rsa 2048 bits 0.001123s 0.000034s    890.4  29142.7
rsa 4096 bits 0.008168s 0.000124s    122.4   8035.9

CPU는 충분히 빨라졌습니다. 세대가 진화할수록, 새로운 공정이 사용될수록 과거와 비교해 성능차가 점점 커지고 있고 이는 통신 암호화에 더 유리한 환경을 조성하는데 큰 기여를 한 부분이 됐습니다. 이에 대해서 각 회사의 엔지니어들은 다음과 같이 말합니다.

On our production frontend machines, SSL/TLS accounts for less than 1% of the CPU load, less than 10 KB of memory per connection and less than 2% of network overhead. Many people believe that SSL/TLS takes a lot of CPU time and we hope the preceding numbers will help to dispel that. -- Adam Langley, Google

"우리가 사용하는 프론트엔드 장비에서, SSL/TLS는 1% 이하의 CPU 사용량과 연결당 10KB 이하의 메모리 그리고 2% 이하의 네트워크 오버헤드를 가졌습니다. 많은 사람들이 SSL/TLS가 많은 CPU 사용을 요구한다고 믿고 있지만 우리는 앞서 보여준 숫자들이 그들의 편견을 떨쳐버리는데 도움이 됐으면 좋겠습니다."

We have deployed TLS at a large scale using both hardware and software load balancers. We have found that modern software-based TLS implementations running on commodity CPUs are fast enough to handle heavy HTTPS traffic load without needing to resort to dedicated cryptographic hardware. -- Dough Beaver, Facebook

"우리는 하드웨어와 소프트웨어 로드밸런서를 이용해 큰 스케일의 TLS 스택을 배포했습니다. 우리는 요즘의 소프트웨어 기반 TLS 구현이 실제로 판매되고 있는 CPU 위에서는 많은 HTTPS 트래픽을 암호화를 위해 만들어진 하드웨어를 사용할 필요 없이 처리하기에 충분히 빠르다는 것을 발견했습니다."

Elliptic Curve Diffie-Hellman (ECDHE) is only a little more expensive than RSA for an equivalent security level… In practical deployment, we found that enabling and prioritizing ECDHE cipher suites actually caused negligible increase in CPU usage. HTTP keepalives and session resumption mean that most requests do not require a full handshake, so handshake operations do not dominate our CPU usage. We find 75% of Twitter’s client requests are sent over connections established using ECDHE. The remaining 25% consists mostly of older clients that don’t yet support the ECDHE cipher suites. -- Jacob, Hoffman-Andrews, Twitter

"ECDHE는 동등한 암호화 수준에서 RSA보다 아주 약간 더 높은 비용을 요구합니다. 실제 배포에서 우리는 ECDHE를 처리하는데 무시해도 될 정도의 CPU 사용량을 보인 부분을 발견했습니다. HTTP Keep-Alive와 세션 재개(session resumption)는 대부분의 요청이 모든 핸드셰이크 과정을 요구하지 않는다는 것을 의미하며, 따라서 핸드셰이크 과정은 CPU 사용량을 차지하지 않는 것과 다름없습니다. 우리는 75%의 트위터 클라이언트 요청이 ECDHE로 성립된 연결로부터 전송되었다는 부분을 알게 되었습니다. 나머지 25%는 아직 ECDHE 를 지원하지 않는 오래된 클라이언트가 대부분입니다."

구글의 경우 2010년 Overclocking SSL 이라는 글을 내면서 위와 같이 말했으며 이 글에서는 다음 내용을 강조하고 있습니다:

SSL/TLS is not computationally expensive any more. (SSL/TLS는 더 이상 값비싼 부분이 아닙니다.)

대용량 파일 전송에서의 암호화 비용

많은 사람들은 대용량 파일을 HTTPS로 전송하면 서버 부하가 매우 커 HTTPS로 파일에 대한 해시값만 전송하고 HTTP로 파일을 서빙하는 방식을 고려하기도 합니다. 하지만 생각해봐야 할 게 있습니다. 네 Python은 느립니다, 하지만 저는 신경쓰지 않습니다 글에서 보여줬듯 CPU는 네트워크/디스크에 비하면 충분히 빠릅니다. 단순히 계산해봅시다. 대부분의 서버는 아무리 커봐야 10Gbps 수준의 백본에 연결되어 있습니다. (더 큰 백본에 연결돼있는 서버가 있을 수도 있겠지만 10Gbps 백본을 쓴다는 것 부터가 이미 성공한 서비스라는 것을 나타내는 지표죠) 여기서 의미하는 것은 대용량 파일을 클라이언트에게 전송하기 이전에 HDD의 파일 읽는 속도가 네트워크 대역폭을 따라가지 못하며 혹시나 따라갈 수 있는 시스템을 구축해두었더라 해도 네트워크 대역폭이 같은 시간동안 CPU가 처리할 수 있는 암호화 속도를 따라갈 수가 없습니다. 결과적으로 한 서버에 PCI Express 10Gbps SFP+ NIC와 PCI Express SSD를 달아두어도 CPU 사용량에는 큰 영향을 끼치지 않습니다. 단순 숫자 계산으로만 봐도 10Gbps 어댑터에 100Mbps 100명이 붙어도 겨우 "100개"의 동시 연결이니까요.

HTTPS로 해시를 전송하고 HTTP로 파일을 서빙하는 방법이 HTTPS로만 파일을 서빙하는 것보다 비효율적인 또 다른 이유는 바로 서로 다른 프로토콜로 인해 2개의 TCP 연결을 성립시켜야 한다는 점입니다. 서로 붙는 것까지 생각하면 정확히는 4개의 TCP 연결이 되겠죠. 이는 HTTPS로만 서빙하는 것보다 2배 더 많은 RTT를 필요로 하고 더불어 TCP overhead 또한 2배라는 것을 의미합니다. 윗 문단에서 이야기한 100개의 파일 다운로드 요청이라면 200개의 TCP 연결이 필요하다는 것이고 이는 총 600 RTT를 만들어냅니다.

대용량 파일 전송을 이야기하기 앞서 네트워크 대역폭과 하드디스크 속도에 대해 이야기하는 사람들은 거의 없습니다. 단순히 대용량 파일 암호화를 CPU가 해야 하니까 느릴 거다, 부하가 클 거다 라고 이야기하는 것은 깊은 생각 보다는 얕은 생각과 지식에서 나온 말 밖에 되지 않습니다. Google Drive, Dropbox, iCloud, OneDrive, CloudFlare 등 여러 클라우드, CDN 서비스는 이미 오래 전부터 작은 파일부터 대용량 파일까지 HTTPS를 통해 서빙하고 있으며 이는 네트워크 대역폭에 빗대어 볼 때 CPU의 속도는 충분히 빠르다는 것을 증명하는 셈입니다.

구글의 큰 그림, SPDY and HTTP/2

구글은 2012년에 SPDY라는 새로운 네트워킹 프로토콜을 공개 발표했습니다. 이 프로토콜은 본질적으로 다중화(multiplexing), 우선 순위(prioritizing)를 이용해 한 TCP 연결 하에 웹 페이지 로드 속도를 더 빠르게 하기 위한 프로토콜로 공개되었습니다. 이후 이 프로토콜은 HTTP/2의 기반이 되어 2015년 3월 14일, RFC 7540 표준으로 오르게 되었습니다.

HTTP/2는 이름 자체가 암시하듯 본래 암호화되지 않은 프로토콜(HTTP) 위에서도 작동하도록 되어있습니다. 하지만 다양한 웹 브라우저가 HTTP/2 지원을 추가하면서 암호화된 프로토콜에서만 HTTP/2가 작동할 수 있도록 구현을 했으며 이는 웹 브라우저 개발 팀들이, HTTP/2는 HTTPS를 지원(power)하기 위해 만들어졌다는 것을 암시하기도 합니다.

더 빠른 웹을 위한 HTTP/2는 정말로 HTTPS를 위해 만들어진 것처럼 보입니다. HTTP/1.1은 plaintext transfer protocol이었지만 HTTP/2는 binary transfer protocol로 변경되었고, 한 연결 하에 통신을 하는 방식은 HTTP보다 HTTPS에게 더 큰 효과를 가져오는 방식이기 때문입니다.

실제 HTTP/2가 오늘날 적용된 이후 많은 웹 변화를 이루어냈습니다. HTTPS를 지원하는 웹 사이트가 많아지는 변화 말이죠. 2017년 5월 W3Techs가 공개하고 있는 바에 따르면 상위 1000만 개 웹 사이트 중에 13.8%의 웹 사이트가 HTTP/2를 지원중에 있습니다. 이 성장 폭은 점점 더 커지고 있으며 CloudFlare, MaxCDN, Fastly 등 세계적인 CDN 회사들의 지원으로 누구나 쉽게 많은 곳에서 HTTP/2를 이용할 수 있게 되었습니다.

HTTP의 문제

2월, 크롬이 업데이트 되면서 네이버가 안전하지 않은 웹 사이트로 나타나는 문제가 있었습니다. 이에 대해 네이버는 "메인 페이지에는 개인정보가 들어가 있지 않고 공개된 정보가 대부분으로, 로그인 창과 검색창에는 https를 적용하고 있다"라고 밝혀 논란이 됐었습니다. 무엇이 문제인지 알아봅시다.

요즘 시대에 DNS 또한 논란이 되고 있는 이유이기도 합니다. DNS는 개발 당시에 필요에 따라 그저 간단하게 "도메인을 요청(A)하면 아이피를 보내줘!"에 맞춰 개발됐습니다. 따라서 암호화는 전혀 고려되지 않은 부분이었고 이는 DNS 스푸핑 등 해커들의 공격으로 이어지기도 했습니다. 요즘은 DNSSEC 기술을 통해 클라이언트가 받아온 DNS 정보가 실제 정보인지 검증하는 방법이 생겨났지만 암호화가 되지 않는 근본적인 문제는 해결되고 있지 않습니다.

개인정보를 주고 받는 것도 아닌데 왜 암호화를 해야할까요? 이 문제는 수많은 국가들이 시행하고 있는 인터넷 검열(internet censorship) 문제로 이어집니다. 대부분의 국가는 DPI(deep packet inspection)를 통해 인터넷 검열을 하고 있으며, 암호화되지 않은 모든 HTTP 통신을 가로채 Host 헤더를 보고 차단 여부를 판단하는 방식을 가장 많이 사용하고 있습니다. 근본적인 문제는 여기서 시작됩니다. 각 국가의 정부 또는 ISP는 사용자가 어느 사이트에 접속하는지 어떤 행동을 하는지 모두 감시할 수 있으며, 이를 이용해 어떤 사용자가 news.naver.com 이라는 도메인 요청을 보냈었고 news.naver.com에서 어느 뉴스를 보고 있는지를 통해 해당 사용자를 구분하고 활동을 감시할 수 있게 됩니다. DNS 요청 또한 중간에서 들여다보아 처음에는 a.example.com에 있다가 어느 시점에 b.example.com에 접속을 시도했다는 것을 알 수 있게 되죠. 즉, 근본적인 문제는 인터넷 검열입니다. 모든 사용자의 행동 및 정보는 보호받아야 할 권리가 있으며 누군가가 이를 들여다볼 수 있는 여지가 생기면 안됩니다.

개인정보가 포함되지 않은 사이트라도 HTTPS를 적용해야 하는 이유는 바로 위에서 언급한 내용대로입니다. 네이버는 "메인 페이지에는 개인정보가 들어가 있지 않고 공개된 정보가 대부분.."이라 밝혔지만 메인 페이지에서 이어질 수 있는 하위 뉴스 페이지, 블로그 페이지 등 또한 모두 암호화되지 않고 HTTP로 통신되고 있으며 이는 위에서 언급한 대로 각 나라의 정부 또는 ISP가 사용자의 행동(behavior) 및 패턴을 파악하는데 매우 중요한 힌트를 주게 됩니다. 또한 메인 페이지에서 로그인 페이지로 이동할 수 있는 부분(과거 네이버는 크롬에서는 메인 페이지에 바로 로그인 폼을 보여주지 않았습니다)으로 볼 때 해커가 중간에 페이지를 가로채 가짜 로그인 페이지로 보낼 수 있는 확률도 존재합니다.

DNS 문제

위에서 언급한대로 DNS는 암호화되지 않는 통신입니다. 이 문제를 해결하기 위해 DNSCrypt, Google Public DNS의 DNS-over-HTTPS (IETF Draft)등의 기술이 나와있지만 아직 실제 적용은 되지 않은 상태입니다. 혹시나 사용해보고 싶은 분들은 DNSCrypt를 직접 설치해서 사용하거나 DNS-over-HTTPS를 구현한 secureoperator 등을 이용해 직접 사용해보실 수 있습니다.

HTTPS 인증서 비용

서버 관리자들이 HTTPS 도입을 꺼려하는 가장 많은 이유 중 하나는 HTTPS 인증서에 대한 비용입니다. 과거에는 HTTPS 인증서를 발급받기 위해 신뢰할 수 있는 루트 인증 기관인 Comodo, VeriSIgn, Symantec, GeoTrust, Thawte 등을 이용해야 했지만, 이러한 고충을 잘 알고있고 HTTPS의 빠른 보급을 원하는 Cisco, Google, Mozilla, Fastly 등의 재단 및 회사들은 Let's Encrypt라는 이름의 무료로 HTTPS 인증서를 보급해주는 기관을 만들었습니다. 이 기관을 통해 다양한 개발자 및 관리자들은 손쉽게 무료로 HTTPS 인증서를 발급받을 수 있는 수단을 얻을 수 있게 됐고 이는 2017년 현재 HTTPS 보급에 가장 큰 공을 세우고 있습니다.

또한ACME(Automatic Certificate Management Environment)의 공개로 손쉽게 인증서를 발급받을 수 있는 certbot이 등장하는 한편, Go에는 Let's Encrypt가 내장되기도 하였으며, 간단힌 서버 설정만 하면 Let's Encrypt로 알아서 인증서를 등록해주는 Caddy와 같은 웹 서버도 등장하게 되었습니다. 즉 ACME로 인해 기존의 복잡하고 번거로웠던 HTTPS 인증서 발급 방식 대신 모든 사용자가 손쉽게 HTTPS 인증서를 발급받을 수 있게 되었으며 이는 더 이상 "HTTPS 인증서 발급이 어렵다", "HTTPS 인증서 비용이 걱정된다"와 같은 말을 할 수 없게 만들었습니다.

HTTPS로 전환하기

아직도 믿지 못할 분이 계실까봐 벤치마크를 가져왔습니다. Let's Encrypt에서 만든 HTTP vs HTTPS Test입니다. https://www.httpvshttps.com/ 에서 테스트해보실 수 있습니다. HTTP/2를 지원하는 브라우저라면 HTTPS의 결과가 눈에 띌 정도로 훨씬 좋을 겁니다. 한 번 테스트해본 후에 새로고침을 하여 다시 테스트를 할 경우 속도가 더 빠른 부분도 확인할 수 있을텐데 이는 HTTP/2에서 지원하는 session resumption 기능의 효과입니다. 다시 접속했을 때 1RTT를 다시 성립할 필요 없이 이미 handshake가 끝났던 세션을 다시 잡고 키만 다시 교환하여 페이지를 처리합니다. Go 언어 공식 사이트에도 HTTP2 테스트 페이지가 존재합니다. 이곳에서는 조금 다른 테스트로 각 링크별로 이미지 블록의 latency가 정해져 있어 latency 별로 테스트를 해볼 수 있습니다. 여기서도 마찬가지로 HTTP/2를 지원한다면 HTTPS가 더 빠른 결과를 보여줍니다. 그렇습니다. 이 테스트는 실제로는 HTTP vs HTTPS가 아닌 HTTP/1.1 vs HTTP/2 입니다. 하지만 모든 브라우저에서 HTTP/2는 SSL/TLS에서만 지원한다는 부분을 다시 한 번 새겨주셨음 합니다.

HTTPS로 전환하는 과정에서 크게 복잡한 부분은 없습니다. 다만 꼭 참고해야 할 부분은 웹 브라우저 policy로 인해 HTTPS에서 HTTP로 날리는 일부 요청은 제한된다는 부분입니다. 특히 HTTPS 페이지에서 HTTP 프로토콜 페이지에 있는 스크립트를 불러올 때는 무조건 요청이 제한되며 웹 소켓 연결 또한 제한됩니다. 이를 위해 HTTPS 전환은 충분한 검토 및 테스트 후에 이루어져야 합니다. 2017년 현재 대부분의 웹 서버가 HTTP/2를 거의 완전히 지원하고 있습니다. Apache는 2.4.12 버전부터 mod_h2 모듈을 통해 지원하고 있고, nginx는 1.9.5(아래 버전은 SPDY 사용)부터, node.js는 5.0부터 지원하고 있습니다. 적용 방법은 각 서버별로 상이하니 찾아보시면 되겠습니다.

Akamai, Cloudflare, AWS CloudFront, Fastly 등의 CDN을 이용하고 있다면 별도의 과정이 필요 없습니다. HTTPS를 이용하는 경우 바로 HTTP/2를 사용할 수 있습니다.

다행히 네이버는 2017년 페이지 개편 후부터 메인 페이지도 HTTPS로 서빙하고 있습니다. (2017.05.21 추가: HTTP/2도 지원하고 있습니다) 어쩌면 네이버의 자의가 아닌 구글에 의한, 타의로 적용한 셈이겠지만 구글의 지적에 적극적으로 대응하는 모습은 높이 평가할 부분입니다.


HTTPS(TLS)는 빠르고 느리고의 문제가 아닙니다. 선택이 아닌 필수입니다. 시대는 변하고 있습니다. Google, Facebook, Twitter는 물론 로그인하지 않았을 때 개인정보가 새어나갈 걱정이 없는 Airbnb, Github, Booking.com, YouTube 조차 모든 페이지에 HTTPS를 적용하여 운영하고 있습니다.

In January this year (2010), Gmail switched to using HTTPS for everything by default. Previously it had been introduced as an option, but now all of our users use HTTPS to secure their email between their browsers and Google, all the time. In order to do this we had to deploy no additional machines and no special hardware.

"2010년 1월, Gmail은 HTTPS를 기본 프로토콜로 변경했습니다. 전에는 옵션이었는데 지금은 모든 사용자들이 브라우저와 구글간의 통신에서 항상 안전을 보장받을 수 있도록 HTTPS를 제공합니다. 우리는 이것을 실현하기 위해 그 어떠한 추가적인 서버나 특별한 하드웨어도 필요하지 않았습니다."

-- Overclocking SSL, 25 Jun 2010, Google

References: