Sunday, 29 May 2016

SNI - giải pháp chạy nhiều SSL/TLS cert trên cùng 1 IP

Câu hỏi: có thể chạy nhiều trang web (khác domain) dùng HTTPS trên cùng 1 host không?
Câu chuyện: nhà nghèo phải host nhiều site trên cùng 1 host mà mỗi site cần một SSL/TLS cert thì phải làm sao?
Trả lời: SNI - Server Name Indication
Làm sao dùng được SNI:
kiểm tra xem webserver có hỗ trợ SNI không, phiên bản OpenSSL đã hỗ trợ SNI chưa.

Tại thời điểm hiện tại thì câu trả lời cơ bản là có:
# nginx -V
nginx version: nginx/1.7.9
built by gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
TLS SNI support enabled
...
các phiên bản openssl từ 0.9.8j trở lên đều mặc định hỗ trợ SNI. Với Ubuntu 14.04, không cần phải lo nghĩ về chuyện này:
$ openssl version
OpenSSL 1.0.1f 6 Jan 2014
SNI là gì? sao lại cần?


Khi một web browser request đến một domain, nếu website đó được cấu hình sử dụng virtual host (apache) hay server blocks (NGINX), web server sẽ kiểm tra domain được yêu cầu là gì và match với config tương ứng, từ đó trả về kết quả tương ứng với domain được yêu cầu.

client ----[Header: domain.tld]---- DNS--> IP --> HTTP server --  dựa vào header này để chọn khổi config (server block) tương ứng --- response ---> client

Nhưng khi muốn sử dụng HTTPS hay còn gọi là HTTP over SSL/TLS, trước khi request được web server chọn match với phần config nào, nó phải thực hiện bước "SSL/TLS handshake". Để biết cert của server có đúng không, HTTP client (web browser,...) sẽ kiểm tra server name trong certificate mà web server trả về khi thực hiện handshake có trùng với tên domain trong URL được request không.
Webserver khi nhận được yêu cầu SSL/TLS handshake sẽ trả về certificate mặc định nó được cấu hình, do nó không biết client đang yêu cầu truy cập đến domain name nào. Thông tin domain name trong HTTP header chỉ tồn tại sau khi quá trình SSL/TLS handshake thực hiện thành công.

Để TLS client biết tên server nó sẽ connect đến, và phía server chọn cert phù hợp để trả về, người ta mở rộng TLS sử dụng extension có tên Server Name Indicator - SNI (xem RFC), cho phép chỉ định server mà client đang connect đến khi thực hiện TLS handshake.

Để sử dụng SNI, cần sự kết hợp giữa cả 2 phía client-server. Các browser hiện đại đều hỗ trợ SNI, các webserver cũng vậy.

Tham khảo:
http://nginx.org/en/docs/http/configuring_https_servers.html#sni