Cách bảo mật Nginx bằng Let's Encrypt trên Ubuntu 20.04

Giới thiệu

Let’s Encrypt là Tổ chức phát hành chứng chỉ (CA) cung cấp cách dễ dàng để lấy và cài đặt chứng chỉ TLS / SSL miễn phí, do đó cho phép HTTPS được mã hóa trên máy chủ web.

Trong hướng dẫn này, chúng ta sẽ sử dụng Certbot để lấy chứng chỉ SSL miễn phí cho Nginx trên Ubuntu 20.04 và thiết lập tự động gia hạn chứng chỉ.

Hướng dẫn này sẽ sử dụng file cấu hình máy chủ Nginx riêng biệt thay vì file mặc định (default). Cũng khuyến khích anh em nên tạo các file cấu hình Nginx riêng biết cho từng tên miền, vì nó giúp anh em tránh các lỗi thường gặp và tránh ảnh hưởng tới nhau khi anh em sử dụng để cấu hình nhiều tên miền.

Bước 1 - Cài đặt Certbot

Bước đầu tiên để sử dụng Let’s Encrypt để lấy chứng chỉ SSL là cài đặt phần mềm Certbot.

Cài đặt Certbot và plugin Nginx:

$ sudo apt update
$ sudo apt install certbot python3-certbot-nginx

Bước 2 - Xác nhận cấu hình của Nginx

Certbot cần có khả năng tìm thấy khối máy chủ chính xác trong cấu hình Nginx để có thể tự động định cấu hình SSL. Cụ thể, nó thực hiện điều này bằng cách tìm kiếm lệnh server_name khớp với domain mà anh em đã yêu cầu chứng chỉ.

Để kiểm tra, hãy mở file cấu hình Nginx cho domain:

$ sudo nano /etc/nginx/sites-available/example.com

Tìm dòng server_name trong file cấu hình:

...
server_name example.com www.example.com;
...
/etc/nginx/sites-available/example.com

Tải lại Nginx để nhận cấu hình mới nếu có thay đổi:

$ sudo systemctl reload nginx

Bước 3 - Cho phép HTTPS thông qua tường lửa

Anh em có thể xem cài đặt hiện tại bằng cách nhập:

$ sudo ufw status
Output
Status: active

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

Để cho phép lưu lượng truy cập HTTPS, hãy cho phép cấu hình Nginx Full:

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

Kiểm tra lại kết quả:

$ sudo ufw status
Output
Status: active

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

Bước 4 - Lấy chứng chỉ SSL

Certbot cung cấp nhiều cách khác nhau để lấy chứng chỉ SSL thông qua các plugin. Plugin Nginx sẽ xử lý việc định cấu hình lại Nginx và tải lại cấu hình bất cứ khi nào cần thiết:

$ sudo certbot --nginx -d example.com -d www.example.com

Chúng ta vừa chạy certbot với plugin --nginx, sử dụng -d để chỉ định các domain mà anh em muốn cấp chứng chỉ.

Nếu đây là lần đầu tiên anh em chạy certbot, sẽ được nhắc nhập địa chỉ email và đồng ý với các điều khoản dịch vụ. Sau khi làm như vậy, certbot sẽ giao tiếp với máy chủ Let’s Encrypt, sau đó chạy pháp lý để xác minh rằng anh em kiểm soát domain mà anh em đang yêu cầu chứng chỉ.

Nếu điều đó thành công, certbot sẽ hỏi muốn định cấu hình cài đặt HTTPS của mình như thế nào.

Output
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Chọn rồi nhấn ENTER thôi. Cấu hình sẽ được cập nhật và Nginx sẽ tải lại để chọn cài đặt mới. Certbot sẽ kết thúc bằng một thông báo cho biết quá trình xác minh đã thành công và nơi lưu trữ chứng chỉ:

Output
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2020-08-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Vậy là đã tạo xong 2 file cert rồi. Tuy nghiên, Certbot sẽ hỗ trợ tự động cấu hình Nginx sử dụng SSL cho anh em, nhưng hãy cứ vào kiểm tra lại nhé, nếu chưa được tự động cấu hình thì vào tự cấu hình thôi là xong :))

Bước 5: cấu hình Nginx sử dụng SSL

Quay trở lại file cấu hình Nginx, việc đầu tiên là thêm 1 block mới lên đầu file:

server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name example.com www.example.com; # Your website's domain name
	return 301 https://$host$request_uri; # Redirect
}

Việc này sẽ giúp tên miền được tự động điều hướng từ PORT 80 sang PORT 443, hay nói cách khác là tự động điều hướng tên miền từ giao thức HTTP sang HTTPS.

Ở block cũ thứ 2, tìm dòng listen 80 default_server; và chỉnh sửa thành listen 443 ssl default_server;

listen 80 default_server;
listen [::]:80 default_server;

// Chỉnh sửa thành

listen 443 ssl default_server;
listen [::]:443 ssl default_server;
Block cũ thứ 2

Tiếp theo, sau dòng server_name example.com www.example.com; thêm đoạn cấu hình cho 2 file cert đã được tạo ở trên:

...
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
...
Block cũ thứ 2

Dưới đây là ví dụ nội dung đầy đủ của file cấu hình Nginx:

server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name example.com www.example.com; # Your website's domain name
	return 301 https://$host$request_uri; # Redirect
}

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

	server_name example.com www.example.com;
	ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

	error_log  /var/log/nginx/error.log;
        access_log /var/log/nginx/access.log;

	root /var/www/html;

	# Add index.php to the list if you are using PHP
	index index.php index.html index.htm index.nginx-debian.html;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files $uri $uri/ /index.php?$query_string;
	}

	# pass PHP scripts to FastCGI server
	
	location ~ \.php$ {
		try_files $uri =404;
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
		fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
		fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
	}
}
/etc/nginx/sites-available/example.com

Kiểm tra lại cấu hình Nginx xem đã chuẩn chưa:

$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Để server nhận các tùy chỉnh vừa mới thay đổi, anh em cần khởi động lại máy chủ NGINX.

$ sudo systemctl reload nginx

// Hoặc

$ sudo systemctl restart nginx

Cuối cùng hãy kiểm tra xem website của anh em đã chuyển từ HTTP sang HTTPS chưa nhé. Nếu anh em thấy có phần https kèm theo một ổ khóa ở đầu thanh URL của trình duyệt thì anh em đã thành công rồi đấy!

Bước 6 - Xác minh tự động gia hạn Certbot

Chứng chỉ của Let’s Encrypt chỉ có giá trị trong 90 ngày. Điều này nhằm khuyến khích người dùng tự động hóa quy trình gia hạn chứng chỉ của họ. Gói certbot mà anh em đã cài đặt sẽ giải quyết vấn đề này bằng cách thêm bộ hẹn giờ systemd sẽ chạy hai lần một ngày và tự động gia hạn bất kỳ chứng chỉ nào trong vòng 30 ngày kể từ ngày hết hạn.

Anh em có thể truy vấn trạng thái của bộ hẹn giờ với systemctl:

$ sudo systemctl status certbot.timer
Output
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Mon 2020-05-04 20:04:36 UTC; 2 weeks 1 days ago
    Trigger: Thu 2020-05-21 05:22:32 UTC; 9h left
   Triggers: ● certbot.service

Để kiểm tra quá trình gia hạn, anh em có thể thực hiện chạy thử nghiệm với certbot:

$ sudo certbot renew --dry-run

Nếu không thấy lỗi gì xảy ra, tức là đã hoàn tất. Khi cần thiết, Certbot sẽ gia hạn chứng chỉ và tải lại Nginx để nhận các thay đổi. Nếu quá trình gia hạn tự động không thành công, Let’s Encrypt sẽ gửi thông báo đến email của anh em đã điền và được chỉ định tại file cert, cảnh báo cho anh em khi chứng chỉ của bạn sắp hết hạn.

Kết thúc

Bài viết này mình xin góp chút kiến thức nhỏ giới thiệu và hướng dẫn anh em cách chúng ta cấu hình bảo mật cho Nginx bằng Let's Encrypt trên Ubuntu version 20.04.

Nếu có điều gì cần góp ý cho mình, anh em vui lòng để lại comment nhé.
Cảm ơn anh em đã dành thời gian đọc bài viết. Hẹn gặp lại !

Tài liệu tham khảo: