Cấu hình HTTPS với nginx và Let's Enscrypt

Bạn vừa mua domain getsolution.pro trên GoDaddy với giá $0.99 trong năm đầu. Vài phút sau, bạn trỏ nó về một server ở Digital Ocean. Trên server này, bạn dùng nginx bắt các requests và forward đến port 5678, nơi có một Node.js process đang chạy Nuxt.js để render website của bạn.

Tại sao phải HTTPS?

Bỏ qua phần thiết lập trên GoDaddy và Digital Ocean. Chúng ta chỉ cần quan tâm tầng máy chủ web trở xuống. File cấu hình nginx của domain là /etc/nginx/sites-enabled/getsolution, lúc này đại khái trông như sau:

server {

  listen 80;

  server_name getsolution.pro;

  location / {
    proxy_pass http://127.0.0.1:5678;
    # other stuff
  }

}

Như vậy người dùng sẽ truy cập vào website của bạn theo đường dẫn http://getsolution.pro.

Website with HTTP protocol

Lúc này mọi dữ liệu trao đổi giữa máy khách với máy chủ của bạn đi qua giao thức HTTP và hoàn toàn không được mã hóa.

Để tăng cường bảo mật, giúp người dùng tin tưởng hơn, bạn nên tạo SSL Certificate cho domain getsolution.pro, sau đó cài đặt nginx tự điều hướng trang web của bạn về https://getsolution.pro.

Trước kia, muốn mua được SSL Certificate cũng khá tốn kém và đòi hỏi nhiều bước chứng thực. Còn bây giờ, Let's Enscrypt đã mang đến cho chúng ta một giải pháp hoàn toàn miễn phí, trình tự thao tác thực hiện cũng rất nhanh chóng, dễ dàng.

Thêm một lý do nữa, việc trang bị HTTPS thay cho HTTP còn có ý nghĩa về mặt thẩm mỹ và nâng cao đẳng cấp cho website của bạn. Web HTTP ngày nay bị xem như thành phần đáng ngờ, những công dân hạng hai trên internet. Chỉ có HTTPS mới được các trình duyệt xem trọng, vừa mở ra đã thấy chiếc khóa và chữ Secure màu xanh đầy cá tính! Có giả thiết cho rằng Google đánh thứ hạng kết quả từ những trang HTTPS cao hơn "tụi HTTP".

Secure signal

Nếu bạn chưa đủ quyết tâm thì vẫn còn 1 lý do quan trọng khác, đó là nếu bạn muốn làm Progressive Web Apps, bạn sẽ phải dùng đến Service Worker, mà bé chảnh này thì dứt khoát không chơi với HTTP, phải HTTPS mới chịu! Tất cả các loại đồ chơi hiện đại based trên Service Worker, như Workbox, UpUp... đều đòi hỏi HTTPS.

Vậy thì làm thôi!

Yêu cầu kỹ thuật

  • Ubuntu server 16.04 trở lên
  • nginx v1.9.x hoặc mới hơn

Các bước thực hiện

1. Cài đặt certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install certbot

Trong quá trình cài đặt, chương trình có thể sẽ yêu cầu lựa chọn các thông số, bạn cần theo dõi để đưa ra option phù hợp:

Choose timezone

Sau khi hoàn tất, trên máy sẽ có thêm 1 lệnh letsencrypt. Bạn thử kiểm tra lại bằng cách gõ letsencrypt --version. Đây là phần client của dịch vụ Let's Enscrypt.

2. Point domain tới 1 web tạm

Tạo SSL certificate cho getsolution.pro thực chất là sử dụng phần client của Let's Enscrypt - lệnh letsencrypt - để tương tác với phần server của nó. Hầu hết tiến trình diễn ra tự động. Chúng ta chỉ cần hiểu sơ sơ rằng, máy chủ Let's Enscrypt sẽ gửi request đến http://getsolution.pro để làm vài chuyện gì đó riêng nó biết!

Cho nên tạm thời chúng ta tạo 1 web tĩnh, trỏ getsolution.pro vào đó.

mkdir /var/www/html
touch /var/www/html/index.html
mkdir /var/www/html/.well-known

Bạn có thể thêm nội dung cho file index.html.

Thư mục .well-known là nơi Let's Enscrypt sẽ thử access. Bây giờ chúng ta cấu hình lại nginx để từ bên ngoài có thể truy cập đến http://getsolution.pro/index.htmlhttp://getsolution.pro/.well-known. Mở lại file cấu hình nginx phía trên, sửa lại thành:

server{

  listen 80;

  server_name getsolution.pro www.getsolution.pro;
  root /var/www/html;

  index index.htm index.html;

  charset utf-8;

  location / {
    try_files $uri $uri/ =404;
  }
  location ~ /.well-known {
     allow all;
  }
}

Load lại thiết lập nginx:

sudo service nginx reload

Nếu mọi thứ chính xác, reload lại trang http://getsolution.pro, chúng ta sẽ nhận được nội dung index.html:

Temp website with HTML only

Chú ý ở nơi quản lý domain bạn cần phải thêm CNAME để cấu hình www.getsolution.pro như alias của getsolution.pro, đâu đó như hình dưới:

CNAME config

Nếu không, ở bước sau letsencrypt sẽ báo lỗi:

Error with www

3. Tạo SSL Certificate files

Với lệnh như dưới:

sudo letsencrypt certonly -a webroot -w /var/www/html/ -d getsolution.pro -d www.getsolution.pro

Nếu thành công, letsencrypt sẽ hiển thị kết quả và chúc mừng:

Successfully generated

Bây giờ letsencrypt đã generate ra các key cho bạn, lưu trong /etc/letsencrypt/.

Kiểm tra với lệnh ls:

sudo ls -l  /etc/letsencrypt/live/getsolution.pro

Kết quả hiển thị:

Listing the keys

Chúng ta sẽ tạo một snippet của nginx tên là ssl-getsolution.pro.conf và đưa các khóa này vào để dễ quản lý:

sudo nano /etc/nginx/snippets/ssl-getsolution.pro.conf

Copy & paste:

ssl_certificate /etc/letsencrypt/live/getsolution.pro/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/getsolution.pro/privkey.pem;

Save file lại.

4. Tham số Diffie-Hellman

Diffie-Hellman parameters định nghĩa cách thức OpenSSL xử lý tác vụ trao đổi khóa Diffie–Hellman giữa máy khách và máy chủ. Tham số này đóng vai trò quan trọng trong việc đánh giá chất lượng SSL.

Để generate ra bộ tham số Diffie-Hellman mới cho server, chúng ta chạy lệnh:

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

Lệnh này chạy mất vài phút:

Generating Diffie-Hellman parameters

Chúng ta sẽ đưa khóa trong file /etc/ssl/certs/dhparam.pem này vào một snippet khác của nginx:

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

Dán vào nội dung sau:

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;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Save lại.

5. Cấu hình nginx lần nữa

Mọi thứ đã gần như hoàn tất, chúng ta đã có SSL certificate, bộ khóa Diffie-Hellman mới. Cả 2 đều đã chuẩn bị sẵn dưới dạng 2 snippets cho nginx.

Trở lại file cấu hình nginx của domain getsolution.pro. Vừa nãy chúng ta đã sửa nó để điều hướng về trang HTML tĩnh. Bây giờ mới là cấu hình về cổng Node.js process, kèm theo HTTPS.

sudo nano /etc/nginx/sites-enabled/getsolution

Nhập vào nội dung sau:

server {

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name getsolution.pro;

  charset utf-8;

  include snippets/ssl-getsolution.pro.conf;
  include snippets/ssl-params.conf;

  location / {
    proxy_pass http://127.0.0.1:5678;
    proxy_read_timeout 300;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_cache_bypass $http_upgrade;
  }
}

Chỉ có 2 điểm khác biệt với file cấu hình đầu tiên. Đó là chúng ta thiết lập lắng nghe ở cổng 443 và chèn 2 snippets ở trên để nginx đọc được.

Reload lại cấu hình nginx:

sudo service nginx reload

Xong, bây giờ chúng ta đã có thể truy cập bằng giao thức HTTPS:

HTTPS is already now

6. Thêm tự điều hướng

Lúc này trang web hỗ trợ cả 2 giao thức HTTP và HTTPS. Lại thêm 2 biến thể có www. nữa, thành ra tổng cộng 4 đường dẫn:

Theo kinh nghiệm của tôi, chúng ta nên chọn https://getsolution.pro làm đường dẫn chính, mấy cái còn lại thì tự động redirect về đó.

Để làm điều này, chỉ việc mở file cấu hình domain ra, thêm vào một đoạn ở đầu file, trở thành:

server {
  listen 80;
  listen [::]:80;
  server_name getsolution.pro www.getsolution.pro;
  return 301 https://$server_name$request_uri;
}

server {
  listen 443;
  listen [::]:443;

  include snippets/ssl-getsolution.pro.conf;
  include snippets/ssl-params.conf;

  server_name www.getsolution.pro;
  return 301 https://getsolution.pro$request_uri;
}

server {

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name getsolution.pro;

  charset utf-8;

  include snippets/ssl-getsolution.pro.conf;
  include snippets/ssl-params.conf;

  location / {
    proxy_pass http://127.0.0.1:5678;
    proxy_read_timeout 300;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_cache_bypass $http_upgrade;
  }
}

Reload nginx một lần nữa để nhận kết quả mong muốn.

7. Kiểm tra chất lượng

Để đánh giá chất lượng SSL/TLS của website, các bạn có thể dùng công cụ phân tích của SSLLabs.

Đây là kết quả cho getsolution.pro:

Estimate SSL quality

Sở dĩ được xếp hạng A phần lớn nhờ bước tạo tham số Diffie-Hellman. Các website không cập nhật giá trị này thường chỉ dừng lại ở hạng B.

Hạn chế của Let's Enscrypt

  • Chưa hỗ trợ wildcard, sub domain
  • Chưa hỗ trợ Extended Validation, nên không nhúng tên thương hiệu vào được. Chỉ có chữ "Secure".
  • 3 tháng hết hạn, phải nhớ chạy lệnh renew hoặc cài đặt cronjob tự động.

That's it.

Chúc các bạn chơi vui vẻ. Có gì thiếu sót vui lòng bổ sung thêm bên dưới :)

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Dong Nguyen

4 bài viết.
59 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
19 4
Khi nghiên cứu hay làm việc với JavaScript, các bạn hẳn có nhiều lúc bắt gặp thuật ngữ TC39. Lại có đôi lúc bạn thấy một pro viết rằng feature X củ...
Dong Nguyen viết 7 tháng trước
19 4
White
16 2
Lâu lâu lại thấy anh hùng trong thiên hạ post 1 bài có dạng "Switch to VIM...", điều này cho thấy sức quyến rũ của VIM là rất lớn, như một cô nàng ...
Dong Nguyen viết 28 ngày trước
16 2
White
4 2
Fix lỗi không đủ bộ nhớ Vấn đề Đôi khi do nhu cầu không cao nên chúng ta chỉ mua 1 cái droplet 512MB ram trên DigitalOcean hay tạo 1 image chừng...
Dong Nguyen viết hơn 1 năm trước
4 2
Bài viết liên quan
Male avatar
25 13
Vẫn theo khung sườn đã định trước từ phần 1, trong phần này tôi sẽ giới thiệu cách cấu hình nginx để thực hiện vai trò của một load balancer. Trư...
manhdung viết hơn 2 năm trước
25 13
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
4 bài viết.
59 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!