https và SSL

Tổng quan

Http và https là 2 protocol chúng ta thường gặp khi truy cập vào một trang web. Hầu hết chúng ta đều hiểu https bảo mật hơn http. Hôm nay mình sẽ giải thích bản chất, cơ chế và cách config một trang web https.

Http và https

  • http là tên viết tắt của HyperText Transfer Protocol (giao thức truyền tải siêu văn bản), là một giao thức cơ bản dùng cho World Wide Web (www) để truyền tải dữ liệu dưới dạng văn bản, hình ảnh, video, âm thanh và các tập tin khác từ Web server đến các trình duyệt web và ngược lại.
  • https là viết tắt của từ HyperText Transfer Protocol Secure và chính là giao thức HTTP có sử dụng thêm các chứng chỉ SSL (Secure Sockets Layer) giúp mã hóa dữ liệu truyền tải nhằm gia bảo mật giữa Web sever đến các trình duyệt web. Nói cách khác https là phiên bản httpnhưng an toàn hơn, bảo mật hơn. Việc bảo mật thông tin riêng tư, cá nhân là rất quan trọng. Do đó có rất nhiều website đã sử dụng https thay http. Các trình duyệt web như Firefox, Chrome và IE như hiện nay đều hiển thị biểu tượng ổ khóa ở thanh địa chỉ để cho biết giao thức https có hoạt động trên trang web bạn truy cập vào hay không.

Cơ chế của SSL ứng dụng trong HTTPS.

SSL là gì?

Việc kết nối giữa một Web browser tới bất kỳ điểm nào trên mạng Internet đi qua rất nhiều các hệ thống độc lập mà không có bất kỳ sự bảo vệ nào với các thông tin trên đường truyền. Không một ai kể cả người sử dụng lẫn Web server có bất kỳ sự kiểm soát nào đối với đường đi của dữ liệu hay có thể kiểm soát được liệu có ai đó thâm nhập vào thông tin trên đường truyền.

Để bảo vệ những thông tin mật trên mạng Internet hay bất kỳ mạng TCP/IP nào, SSL đã kết hợp những yếu tố sau để thiết lập được một giao dịch an toàn:

  • Xác thực: đảm bảo tính xác thực của trang mà khách hàng sẽ làm việc ở đầu kia của kết nối. Cũng như vậy, các trang Web cũng cần phải kiểm tra tính xác thực của người sử dụng.
  • Mã hoá: đảm bảo thông tin không thể bị truy cập bởi đối tượng thứ ba. Để loại trừ việc nghe trộm những thông tin “nhạy cảm” khi nó được truyền qua Internet, dữ liệu phải được mã hoá để không thể bị đọc được bởi những người khác ngoài người gửi và người nhận.
  • Toàn vẹn dữ liệu: đảm bảo thông tin không bị sai lệch và nó phải thể hiện chính xác thông tin gốc gửi đến.Với việc sử dụng SSL, các Web site có thể cung cấp khả năng bảo mật thông tin, xác thực và toàn vẹn dữ liệu đến người dùng. SSL được tích hợp sẵn vào các browser và Web server, cho phép người sử dụng làm việc với các trang Web ở chế độ an toàn.

Giao thức SSL là gì?

SSL được phát triển bởi Netscape, ngày nay giao thức SSL đã được sử dụng rộng rãi trên World Wide Web trong việc xác thực và mã hoá thông tin giữa client và server. Tổ chức IETF (Internet Engineering Task Force ) đã chuẩn hoá SSL và đặt lại tên là TLS (Transport Layer Security). Mặc dù là có sự thay đổi về tên nhưng TSL chỉ là một phiên bản mới của SSL. Phiên bản TSL 1.0 tương đương với phiên bản SSL 3.1. Tuy nhiên SSL là thuật ngữ được sử dụng rộng rãi hơn

SSL được thiết kế như là một giao thức riêng cho vấn đề bảo mật có thể hỗ trợ cho rất nhiều ứng dụng. Giao thức SSL hoạt động bên trên TCP/IP và bên dưới các giao thức ứng dụng tầng cao hơn như là HTTP, IMAP và FTP.

SSL không phải là một giao thức đơn lẻ, mà là một tập các thủ tục đã được chuẩn hoá để thực hiện các nhiệm vụ bảo mật sau:

  • Xác thực server: Cho phép người sử dụng xác thực được server muốn kết nối. Lúc này, phía browser sử dụng các kỹ thuật mã hoá công khai để chắc chắn rằng certificate và public ID của server là có giá trị và được cấp phát bởi một CA (certificate authority) trong danh sách các CA đáng tin cậy của client. Điều này rất quan trọng đối với người dùng. Ví dụ như khi gửi mã số credit card qua mạng thì người dùng thực sự muốn kiểm tra liệu server sẽ nhận thông tin này có đúng là server mà họ định gửi đến không.

  • Xác thực Client: Cho phép phía server xác thực được người sử dụng muốn kết nối. Phía server cũng sử dụng các kỹ thuật mã hoá công khai để kiểm tra xem certificate và public ID của server có giá trị hay không và được cấp phát bởi một CA (certificate authority) trong danh sách các CA đáng tin cậy của server không. Điều này rất quan trọng đối với các nhà cung cấp. Ví dụ như khi một ngân hàng định gửi các thông tin tài chính mang tính bảo mật tới khách hàng thì họ rất muốn kiểm tra định danh của người nhận.

  • Mã hoá kết nối: Tất cả các thông tin trao đổi giữa client và server được mã hoá trên đường truyền nhằm nâng cao khả năng bảo mật. Điều này rất quan trọng đối với cả hai bên khi có các giao dịch mang tính riêng tư. Ngoài ra, tất cả các dữ liệu được gửi đi trên một kết nối SSL đã được mã hoá còn được bảo vệ nhờ cơ chế tự động phát hiện các xáo trộn, thay đổi trong dữ liệu. (đó là các thuật toán băm – hash algorithm).

Giao thức SSL bao gồm 2 giao thức con:

  • Giao thức SSL record: xác định các định dạng dùng để truyền dữ liệu.
  • Giao thức SSL handshake: sử dụng SSL record protocol để trao đổi một số thông tin giữa server và client vào lấn đầu tiên thiết lập kết nối SSL

Một số thuật toán dùng trong SSL

Các thuật toán mã hoá và xác thực của SSL được sử dụng bao gồm:

  • DES (Data Encryption Standard): là một thuật toán mã hoá có chiều dài khoá là 56 bit.
  • 3-DES (Triple-DES): là thuật toán mã hoá có độ dài khoá gấp 3 lần độ dài khoá trong mã hoá DES.
  • DSA (Digital Signature Algorithm): là một phần trong chuẩn về xác thực số đang được được chính phủ Mỹ sử dụng.
  • KEA (Key Exchange Algorithm): là một thuật toán trao đổi khoá đang được chính phủ Mỹ sử dụng.
  • MD5 (Message Digest algorithm): được phát thiển bởi Rivest.
  • RSA: là thuật toán mã hoá công khai dùng cho cả quá trình xác thực và mã hoá dữ liệu được Rivest, Shamir, and Adleman phát triển.
  • RSA key exchange: là thuật toán trao đổi khoá dùng trong SSL dựa trên thuật toán RSA.
  • RC2 and RC4: là các thuật toán mã hoá được phát triển bởi Rivest dùng cho RSA Data Security.
  • SHA-1 (Secure Hash Algorithm): là một thuật toán băm đang được chính phủ Mỹ sử dụng.

Khi một client và server trao đổi thông tin trong giai đoạn bắt tay (handshake), họ sẽ xác định bộ mã hoá mạnh nhất có thể và sử dụng chúng trong phiên giao dịch SSL.

Cách hoạt động giữa client và server sử dụng SSL.

Đơn giản chúng ta có ví dụ: A cần bán hàng cho anh B sẽ có các thủ tục sau:

  1. B yêu cầu A gửi cho mình chứng minh thư
  2. A đưa chứng minh thư cho B
  3. B mang lên cơ quan công an nhờ xác nhận xem có phải là đúng là ông A không?
  4. Nếu xác nhận ok, thì B báo cho A biết là ok
  5. A gửi cho B một key
  6. B và A sẽ dùng key này để mã hóa thông tin trao đổi với nhau

Qua ví dụ trên thì:

  • A là server, B là client
  • Chứng minh thư là chính chỉ SSL
  • Cơ quan công an là tổ chức CA (Certification Authority); là một tổ chứng mà 2 ông A, B đều tin cậy, là người cấp SSL
  • Nếu ông C mà nghe lén được thông tin của A, B thì cũng không giải mã được vì không có key

Có 2 cách tạo SSL:

  • Nhờ một tổ chức CA cấp, là tổ chức có độ tin cậy cao, được quyền cấp và chứng nhận SSL. Tất nhiên là chúng ta phải mất tiền để mua chứng chỉ SSL.
  • Self-signed SSL: là tự server cấp, tự kí, tự xác thực (ko an toàn và tin tưởng bằng nhờ bên thứ 3)

Phần demo mình tạo self-signed SSL trên môi trường Nginx và Ubuntu 16.04.

Cấu hình HTTPS

Step 1: Tạo một chứng chỉ SSL

TLS/SSL hoạt động dựa vào sự kết hợp giữa một public certificate và một private key. SSL key được giữ bí mật ở trên server. Nó được sử dụng để mã hóa nội dung gửi tới clients.
Còn SSL certificate được chia sẻ rộng rãi với bất cứ ai yêu cầu nội dung. Nó được sử dụng để giải mã nội dung được ký bởi SSL key.

Chúng ta sẽ tạo một self-signed key và một cặp chứng chỉ với câu lệnh OpenSSL:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

Chắc hẳn sẽ có một số câu hỏi về đống loằng ngoằng kia là cái gì vậy? Mình sẽ giải thích ngay và luôn:

  • openssl là một command để tạo vào quản lý chứng chỉ OpenSSL , keys và các file khác.
  • req là một subcommand chỉ định rõ chúng ta mún sử dụng X.509 CSR (certificate signing request) : chứng chỉ yêu cầu ký. X.509 là một chuẩn public key của SSL và TLS.
  • nodes chỉ rõ OpenSSL bỏ qua việc bảo mặt chứng chỉ của chúng ta bằng một chuỗi mật khẩu (passphrase). Nếu để mật khẩu này thì nginx của chúng ta luôn phải nhập mật khẩu này mỗi khi khởi động nên rất là bất tiện.
  • days 365 là tham số xác định thời hạn sử dụng chứng chỉ là 365 ngày (1 năm).
  • newkey rsa:2048 là tham số chỉ định chúng ta muốn sinh ra một chứng chỉ mới và một key mới tại cùng câu lệnh với key RSA có độ dài 2048 bít.
  • keyout chỉ định nơi chứng ta lưu trữ private key được sinh ra lúc tạo
  • out chỉ định nơi chứng chỉ được lưu trữ sau khi tạo

Khi chúng ta sử dụng câu lệnh ở trên, nó sẽ tạo ra 2 file : 1 file key và một file chứng chỉ. Sẽ có một số câu hỏi về server để thêm đúng thông tin vào chứng chỉ. Chúng ta cần điền đầy đủ các thông tin như sau: Chú ý là dòng Common Name (e.g. server FQDN or YOUR name) chúng ta cần nhập đúng tên domain hoặc IP của server.

Country Name (2 letter code) [AU]: VN
State or Province Name (full name) [Some-State]: Ha Noi
Locality Name (eg, city) []: Ha Noi
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test company
Organizational Unit Name (eg, section) []: Test company 
Common Name (e.g. server FQDN or YOUR name) []: IP hoặc test.com
Email Address []:[email protected]

Cả 2 file được tạo trong thư mục /etc/ssl Để tăng tính bảo mật, chúng ta cũng nên tạo một Diffie-Hellman group:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Kết thúc chúng ta sẽ có một group DH đủ mạnh trong tại file /etc/ssl/certs/dhparam.pem.

Step 2: Cấu hình Nginx để sử dụng SSL

Bước tiếp theo là chúng ta sẽ config lại nginx. Đầu tiên chúng ta sẽ tạo một Nginx configuration snippet tên là self-signed.conf trong thư mục /etc/nginx/snippets. Cấu hình ssl_certificatessl_certificate_key có đường dẫn tới certificate và key chúng ta đã tạo.

  • sudo nano /etc/nginx/snippets/self-signed.conf
# /etc/nginx/snippets/self-signed.conf
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

Chúng ta tạo thêm một file snippet khác, định nghĩa vài cài đặt SSL. Nó sẽ tăng tính bảo mật của SSL.

  • sudo nano /etc/nginx/snippets/ssl-params.conf

Chúng ta sẽ sử dụng mã hóa được recommend trên trang https://cipherli.st/. Ở đây chúng ta chọn cấu hình cho Nginx. Setting được gợi ý ở trang này tạo ra sự bảo mật tốt nhất cho từng web server. Chúng ta sẽ sửa lại vài chỗ trong cấu hình này cho phù hợp:

  • Thêm preferred DNS resolver cho upstream request là DNS của Google. Thêm ssl_dhparam tới file Diffie-Hellman đã được tạo ra từ bước trước.
  • Chúng ta sẽ tắt chức năng preload HSTS vì hơi phức tạp để hiểu và cấu hình.
# /etc/nginx/snippets/ssl-params.conf
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;

Cấu hình Nginx sử dụng SSL

  • Trước khi cấu hình, chúng ta cần backup lại config default của nginx - sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
  • Mở file cấu hình nginx lên và chỉnh sửa: - sudo nano /etc/nginx/sites-available/default

Ban đầu nội dung file sẽ như thế này:

# /etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
  • Trước hết, chúng ta sẽ bắt các request http sẽ redirect về https. Nghĩa là khi người dùng truy cập bằng http thì server tự động chuyển sang https.
# /etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;
}

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
  • Tiếp theo chúng ta cấu hình SSL listen ở cổng 443 vào block thứ 2. Thêm cấu hình 2 file snippets vào như sau:
# /etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;
}

server {

    # SSL configuration

    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;
}

Chúng ta đã cấu hình xong Nginx SSL. Tiếp đến cần bật firewall cho HTTPS.

Step 3: Chỉnh sửa Firewall

Nếu ufw firewall được bật, thì chúng tá sẽ cần chỉnh sửa cài đặt cho phép SSL (HTTPS). Xem danh sách các profiles firewall:

  • sudo ufw app list
Output
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

Xem trạng thái settings hiện tại thì dùng command:

  • sudo ufw status Chúng ta có thể thấy chỉ có HTTP được cho phép.
Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Để thêm HTTPS traffic, chúng ta cần cho phép Nginx Full profile và xóa Nginx HTTP profile:

sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

Xem lại trạng thái firewall:

  • sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Step 4: Cấu hình Nginx

Để kiểm tra lõi cũ pháp trong cấu hình nginx thì dùng command sau:

  • sudo nginx -t

Nếu config ok thì sẽ get được kết quả như sau:

nginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Nếu không bị lỗi gì, thì restart lại nginx:

  • sudo systemctl restart nginx

Step 5: Test Encryption

Vậy là chúng ta đã cấu hình xong SSL cho domain. Mở trình duyệt và đánh https để kiểm tra. Kết quả chúng ta sẽ thấy có cái biểu tượng khóa ở trên trình duyệt:

  • https://server_domain_or_IP
  • Kết quả sẽ có warning như hình dưới:

Tổng kết

Cơ chế của https và SSL tương đối dễ hiểu và có tính thực tiễn cao. Nếu là các trang web cần bảo mât thông tin thì chúng ta nên sử dụng https.