Reading Time: 12 minutes

TLS (Transport Layer Security) và tiền thân của nó SSL (Secure Sockets Layer) là các giao thức web hay dùng để bảo vệ và mã hóa lưu lượng truy cập web. Nhờ các công nghệ này, máy chủ có thể gửi dữ liệu một cách an toàn tới client (và ngược lại) mà các bên sợ bị các bên nào khác đọc được.

Tạo chứng chỉ SSL tự ký cho Nginx

Hệ thống chứng chỉ đóng vai trò giúp người dùng xác minh danh tính của các trang web mà họ đang kết nối ở trường hợp này.

Trong bài hướng dẫn này, chúng ta sẽ tìm hiểu cách thiết lập một chứng chỉ SSL tự ký (self-signed) để sử dụng với web server Nginx trên một server Ubuntu.

Lưu ý: Chứng chỉ tự ký sẽ mã hóa giao tiếp giữa server của bạn và bất kỳ client nào. Tuy nhiên, vì nó không được ký bởi các Tổ chức phát hành chứng chỉ (CA) đáng tin cậy, vốn được tích hợp sẵn trong các trình duyệt web. Do đó người dùng không thể tự động dùng các chứng chỉ này để xác thực danh tính server của bạn.

Chứng chỉ tự ký có thể không phù hợp để dùng nếu bạn không có tên miền liên kết với server và trong các trường hợp giao diện web được mã hóa không được thiết kế cho người dùng cuối. Nếu bạn có một tên miền, sử dụng chứng chỉ do CA cấp là lựa chọn tốt hơn trong phần lớn các trường hợp.

Tạo chứng chỉ SSL tự ký cho Nginx trên Ubuntu

Điều kiện tiên quyết

Để làm theo hướng dẫn này, bạn cần:

  • Một server Ubuntu đã được thiết lập một firewall và thêm một người dùng không phải root với quyền sudo.
  • Web server Nginx. Có thể được cài đặt riêng lẻ hoặc theo cả một stack như LEMP (Linux, Nginx, MySQL, PHP).

Bước 1: Tạo chứng chỉ SSL

TLS/SSL hoạt động bằng cách kết hợp một public certificate (chứng chỉ công khai) và một private key (khóa bí mật). Khóa SSL được giữ bí mật trên server. Nó được dùng để mã hóa nội dung gửi đến client. Chứng chỉ SSL thì được chia sẻ công khai với bất kỳ bên nào muốn yêu cầu nội dung từ máy chủ. Nó có thể được sử dụng để giải mã nội dung đã được ký bởi SSL khóa tương ứng.

Bạn có thể tạo một cặp khóa và chứng chỉ tự ký bằng OpenSSL với một lệnh duy nhất như sau:

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

Giải thích chi tiết:

  • sudo: Lệnh sudo cho phép các thành viên của nhóm sudo tạm thời nâng quyền của mình lên thành của người dùng khác (mặc định là superuser, hay người dùng root). Điều này là cần thiết trong trường hợp này vì chúng ta đang tạo cặp chứng chỉ và khóa trong thư mục /etc/ssl, nơi chỉ có người dùng root hoặc các tài khoản có quyền cao khác mới có thể truy cập.
  • openssl: Đây là công cụ dòng lệnh cơ bản để tạo và quản lý các chứng chỉ, khóa và các file OpenSSL khác.
  • req: Lệnh con này chỉ định rằng chúng ta muốn sử dụng quản lý yêu cầu ký chứng chỉ (CSR) X.509. Đây là một tiêu chuẩn hạ tầng khóa công khai mà SSL và TLS tuân thủ để quản lý khóa và chứng chỉ. Chúng ta muốn tạo một chứn chỉ X.509 mới, vì vậy chúng ta sử dụng lệnh con này.
  • -x509: Tùy chọn này bổ sung cho lệnh con trước đó, để yêu cầu nó tạo một chứng chỉ tự ký thay vì chỉ là một yêu cầu ký chứng chỉ như thông thường.
  • nodes: Tùy chọn này yêu cầu OpenSSL bỏ qua việc bảo vệ chứng chỉ bằng mật khẩu (passphrase). Chúng ta cần Nginx có thể đọc file mà không cần sự can thiệp của người dùng khi server khởi động. Mật khẩu sẽ ngăn cản điều này vì chúng ta sẽ phải nhập nó sau mỗi lần khởi động lại.
  • -days 365: Tùy chọn này đặt khoảng thời gian mà chứng chỉ còn hợp lệ. Ở đây, chúng ta đặt là một năm.
  • -newkey rsa:2048: Tùy chọn này chỉ định rằng chúng ta muốn tạo cả một chứng chỉ mới và một khóa mới cùng một lúc. Chúng ta chưa tạo khóa cần thiết để ký chứng chỉ ở bước trước, vì vậy chúng ta sẽ cần tạo nó cùng với chứng chỉ. Phần rsa:2048 yêu cầu tạo một khóa RSA dài 2048 bit.
  • -keyout: Dòng này chỉ định nơi OpenSSL sẽ đặt file khóa riêng tư mà chúng ta sẽ tạo.
  • -out: Dòng này cho OpenSSL biết nơi để đặt chứng chỉ mà chúng ta sẽ tạo.

Như đã nêu trước đó, các tùy chọn này sẽ tạo cả file khóa và file chứng chỉ. Sau khi chạy lệnh này, bạn sẽ được hỏi một vài câu về server của mình để nhúng thông tin chính xác vào chứng chỉ.

Hãy điền vào các thông tin một cách thích hợp. Dòng quan trọng nhất là yêu cầu Common Name (e.g. server FQDN or YOUR name). Bạn cần nhập tên miền liên kết với server của mình, hoặc hay xảy ra hơn là địa chỉ IP công khai của server**.**

Toàn bộ các thông báo sẽ trông giống như sau:

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
Organizational Unit Name (eg, section) []:Ministry of Water Slides
Common Name (e.g. server FQDN or YOUR name) []:server_IP_address
Email Address []:admin@your_domain.com

Cả hai file bạn đã tạo sẽ được đặt trong các thư mục con thích hợp trong /etc/ssl.

Khi sử dụng OpenSSL, bạn cũng nên tạo một nhóm mã hóa Diffie-Hellman mạnh để đàm phán Perfect Forward Secrecy (cơ chế bảo mật chuyển tiếp tuyệt đối) với các client. Bạn có thể làm điều này bằng cách chạy lệnh sau:

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

Quá trình này sẽ mất một thời gian. Sau khi hoàn tất, bạn sẽ có một nhóm DH mạnh tại /etc/nginx/dhparam.pem và nó sẽ được sử dụng trong quá trình cấu hình.

Bước 2: Cấu hình Nginx để sử dụng SSL

Sau khi các file khóa và chứng chỉ của bạn trong thư mục /etc/ssl đã được tạo, bạn sẽ cần sửa đổi cấu hình Nginx của mình để sử dụng chúng.

Đầu tiên, tạo một đoạn cấu hình chứa thông tin về vị trí của file SSL khóa và chứng chỉ. Sau đó, bạn sẽ tạo một đoạn khác với các thiết lập SSL mạnh có thể được sử dụng với bất kỳ chứng chỉ nào trong tương lai. Cuối cùng, bạn sẽ điều chỉnh các khối server của Nginx bằng hai đoạn cấu hình đã tạo để các yêu cầu SSL có thể được xử lý đúng cách.

Phương án cấu hình Nginx này sẽ cho phép bạn giữ cho các khối server gọn gàng và đặt các phân đoạn cấu hình chung vào các module có thể tái sử dụng.

Tạo một đoạn cấu hình trỏ đến khóa và chứng chỉ SSL

Đầu tiên, sử dụng một editor bất kì (ở đây ta dùng nano) để tạo một đoạn cấu hình Nginx mới trong thư mục /etc/nginx/snippets. Để phân biệt rõ mục đích của file này, hãy đặt tên nó là self-signed.conf:

sudo nano /etc/nginx/snippets/self-signed.conf

Trong file này, đặt directive ssl_certificate trỏ đến file chứng chỉ của bạn và ssl_certificate_key trỏ đến khóa tương ứng. Cấu hình sẽ trông giống như sau:

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

Khi bạn đã thêm các dòng đó, hãy lưu file và thoát khỏi editor. Nếu sử dụng nano, nhấn CTRL + X, sau đó là Y, và ENTER.

Tạo một đoạn cấu hình với các thiết lập mã hóa mạnh

Tiếp theo, tạo một đoạn khác để định nghĩa một số cài đặt SSL. Điều này sẽ thiết lập Nginx với một bộ mật mã SSL mạnh và kích hoạt một số tính năng nâng cao giúp giữ cho server của bạn an toàn.

Các tham số bạn đặt có thể được tái sử dụng trong các cấu hình Nginx trong tương lai, vì vậy bạn có thể đặt cho file này một cái tên chung:

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

Để thiết lập Nginx SSL một cách an toàn, chúng ta sẽ điều chỉnh các khuyến nghị từ Cipherlist.eu. Đây là một nguồn tài nguyên hữu ích và dễ hiểu để nắm bắt các cài đặt mã hóa được sử dụng cho các phần mềm phổ biến.

Lưu ý: Các cài đặt được đề xuất từ Cipherlist.eu cung cấp độ bảo mật tương đối mạnh mẽ. Tuy nhiên, đôi khi điều này phải đánh đổi bằng khả năng tương thích với client. Nếu bạn cần hỗ trợ các client cũ hơn, có một danh sách thay thế bạn có thể truy cập bằng cách nhấp vào liên kết trên trang web đó với tiêu đề “Yes, give me a ciphersuite that works with legacy / old software.” Nếu muốn, bạn có thể thay thế danh sách đó bằng nội dung của khối mã ví dụ dưới đây.

Việc lựa chọn cấu hình nào để sử dụng sẽ phụ thuộc phần lớn vào những gì bạn cần hỗ trợ. Phương án nào cũng sẽ cung cấp độ bảo mật tốt.

Trong trường hợp của chúng ta, hãy sao chép toàn bộ các cài đặt được cung cấp. Nhưng trước tiên, bạn sẽ cần thực hiện một vài sửa đổi nhỏ.

Đầu tiên, thêm DNS resolver (máy chủ phân giải DNS) bạn cần cho các yêu cầu upstream (têu cầu chuyển đến máy chủ kế tiếp). Chúng ta sẽ sử dụng Google (8.8.8.88.8.4.4) cho bài hướng dẫn này.

Thứ hai, bỏ dấu comment ở dòng thiết lập header cho Strict Transport Security. Trước khi làm điều này, bạn nên dành chút thời gian để tìm hiểu về HTTP Strict Transport Security, hay HSTS, và đặc biệt là về chức năng “preload”. Preload HSTS giúp tăng cường bảo mật, nhưng cũng có thể gây ra những vấn đề lớn nếu bị vô tình kích hoạt hoặc kích hoạt không chính xác.

Thêm đoạn sau vào file cấu hình ssl-params.conf của bạn:

ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem; 
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_ecdh_curve secp384r1;
ssl_session_timeout  10m;
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 strict transport security for now. You can uncomment the following
# line if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

Vì ta đang sử dụng chứng chỉ tự ký, SSL stapling (tính năng đính kèm SSL) sẽ không được sử dụng. Nginx sẽ cho ra một cảnh báo và vô hiệu hóa stapling cho chứng chỉ tự ký của bạn, nhưng sau đó nó vẫn sẽ tiếp tục hoạt động bình thường.

Lưu và đóng file khi bạn hoàn tất.

Điều chỉnh cấu hình Nginx để sử dụng SSL

Bây giờ bạn đã có các đoạn cấu hình của mình, bạn có thể điều chỉnh cấu hình Nginx để kích hoạt SSL.

Chúng ta sẽ giả định bạn đang sử dụng một file cấu hình khối server tùy chỉnh trong thư mục /etc/nginx/sites-available. Hướng dẫn này cũng tuân theo các quy ước thông thường và sử dụng /etc/nginx/sites-available/your_domain cho ví dụ này. Hãy thay thế bằng tên file cấu hình của bạn khi cần.

Trước khi tiếp tục, hãy sao lưu file cấu hình hiện tại của bạn:

sudo cp /etc/nginx/sites-available/your_domain /etc/nginx/sites-available/your_domain.bak

Bây giờ, mở file cấu hình để thực hiện các điều chỉnh:

sudo nano /etc/nginx/sites-available/your_domain

Bên trong đó, khối server của bạn có thể bắt đầu tương tự như sau:

server {
    listen 80;
    listen [::]:80;

    server_name your_domain www.your_domain.com;

    root /var/www/your_domain.com/html;
    index index.html index.htm index.nginx-debian.html;

    . . .
}

File của bạn có thể có thứ tự khác, và thay vì các directive rootindex, bạn có thể có một số location, proxy_pass, hoặc các câu lệnh cấu hình tùy chỉnh khác. Điều này không có vấn đề gì vì bạn chỉ cần cập nhật các directive listen và kèm vào các đoạn SSL của mình. Sau đó, chỉnh sửa khối server hiện có này để phục vụ lưu lượng SSL trên cổng 443, và tạo một khối server mới để phản hồi trên cổng 80 và tự động chuyển hướng lưu lượng truy cập đến cổng 443.

Lưu ý: Sử dụng lệnh chuyển hướng 302 cho đến khi bạn đã xác minh mọi thứ hoạt động bình thường. Sau đó, bạn sẽ đổi nó thành lệnh chuyển hướng 301 một cách vĩnh viễn.

Trong file cấu hình hiện có, cập nhật hai câu lệnh listen để sử dụng cổng 443ssl, sau đó thêm vào hai file cấu hình mà chúng ta đã tạo ở các bước trước:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    server_name your_domain.com www.your_domain.com;

    root /var/www/your_domain.com/html;
    index index.html index.htm index.nginx-debian.html;

    . . .
}

Tiếp theo, thêm một khối server thứ hai vào file cấu hình sau dấu ngoặc đóng (}) của khối đầu tiên:

. . .
server {
    listen 80;
    listen [::]:80;

    server_name your_domain.com www.your_domain.com;

    return 302 https://$server_name$request_uri;
}

Đây là một cấu hình tối thiểu để lắng nghe trên cổng 80 và thực hiện chuyển hướng đến HTTPS. Lưu và đóng file khi bạn hoàn tất việc chỉnh sửa.

Bước 3: Điều chỉnh firewall

Nếu đã bật chương trình firewall ufw, bạn sẽ cần điều chỉnh các cài đặt để cho phép lưu lượng SSL kết nối. May mắn là Nginx có tạo sẵn một vài profile với ufw khi cài đặt.

Bạn có thể xem lại các profile có sẵn bằng cách chạy lệnh sau:

sudo ufw app list

Một danh sách như sau sẽ xuất hiện trong output:

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

Bạn cũng có thể kiểm tra cài đặt hiện tại bằng cách gõ:

sudo ufw status

Nó có thể sẽ hiện output như sau, có nghĩa là chỉ có lưu lượng HTTP được phép đến web server:

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 HTTPS, bạn có thể cập nhật quyền cho profile “Nginx Full”:

sudo ufw allow 'Nginx Full'

Sau đó, xóa quyền cho phép của profile “Nginx HTTP” mà ta không cần tới nữa:

sudo ufw delete allow 'Nginx HTTP'

Sau đó chạy sudo ufw status, bạn sẽ nhận được output sau:

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)

Nó xác nhận rằng các điều chỉnh cho firewall của bạn đã hoạt động thành công và bạn đã sẵn sàng để kích hoạt các thay đổi cấu hình trong Nginx.

Bước 4: Kích hoạt các thay đổi cấu hình trong Nginx

Sau khi đã hoàn thành các thay đổi và điều chỉnh cho firewall, bạn có thể khởi động lại Nginx để áp dụng các thay đổi mới.

Đầu tiên, kiểm tra xem có lỗi cú pháp nào trong các file của chúng ta không bằng cách chạy lệnh sau:

sudo nginx -t

Nếu mọi thứ thành công, bạn sẽ nhận được kết quả như sau:

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

Lưu ý cảnh báo ở dòng đầu. Như đã đề cập trước đó, cài đặt này tạo ra một cảnh báo vì chứng chỉ tự ký của bạn không thể sử dụng SSL stapling. Điều này là hoàn toàn bình thường và server của bạn vẫn có thể mã hóa các kết nối một cách đúng đắn.

Nếu output kiểm tra của bạn giống như trên, file cấu hình của bạn không có lỗi cú pháp và bạn có thể khởi động lại Nginx để áp dụng các thay đổi một cách an toàn:

sudo systemctl restart nginx

Bây giờ hệ thống đã được khởi động lại với các thay đổi mới, bạn có thể tiến hành các bước kiểm tra.

Bước 5: Kiểm tra mã hóa

Bây giờ, hãy kiểm tra server SSL. Mở trình duyệt web và gõ https:// vào trước tên miền hoặc IP của server vào thanh địa chỉ:

https://server_domain_or_IP

Trình duyệt của bạn có thể sẽ hiện một cảnh báo do chứng chỉ bạn tạo không được ký bởi một trong những tổ chức phát hành chứng chỉ đáng tin cậy:

Thông báo về chứng chỉ SSL tự ký cho Nginx

Cảnh báo này là bình thường và được dự kiến trước. Chúng ta chỉ quan tâm đến khía cạnh mã hóa của chứng chỉ, không phải là việc xác thực danh tính máy chủ của chúng ta từ bên thứ ba. Nhấp vào ADVANCED và sau đó là liên kết được cung cấp để tiếp tục đến máy chủ của bạn:

Cách bỏ qua thông báo về chứng chỉ SSL tự ký cho Nginx

Sau đó, bạn sẽ được đưa tới trang web của mình. Thanh địa chỉ của trình duyệt sẽ hiển thị một ổ khóa có dấu “x” trên đó. Điều này có nghĩa nó không thể xác thực được chứng chỉ, dù trình duyệt vẫn sẽ dùng nó để thực hiện mã hóa kết nối của bạn. Lưu ý rằng biểu tượng này có thể khác nhau tùy thuộc vào trình duyệt của bạn.

Nếu bạn đã cấu hình Nginx với hai khối server để tự động chuyển hướng nội dung HTTP sang HTTPS, bạn cũng có thể kiểm tra xem việc chuyển hướng có hoạt động chính xác không bằng đi tới địa chỉ sau:

http://server_domain_or_IP

Nếu trình duyệt hiện cùng một biểu tượng, việc chuyển hướng của bạn đã hoạt động chính xác.

Bước 6: Cấu hình để việc chuyển hướng trở thành vĩnh viễn

Nếu việc chuyển hướng đã hoạt động chính xác và bạn chỉ muốn cho phép lưu lượng đã mã hóa, bạn nên sửa đổi cấu hình Nginx để làm cho việc chuyển hướng mang tính vĩnh viễn.

Mở lại file cấu hình khối server của bạn:

sudo nano /etc/nginx/sites-available/your_domain.com

Tìm return 302 và đổi nó thành return 301:

return 301 https://$server_name$request_uri;

Lưu và đóng file. Kiểm tra cấu hình của bạn để tìm lỗi cú pháp:

sudo nginx -t

Khi đã sẵn sàng, khởi động lại Nginx để làm cho việc chuyển hướng không còn tính tạm thời:

sudo systemctl restart nginx

Sau khi khởi động lại, các thay đổi sẽ được áp dụng và việc chuyển hướng của bạn giờ đã là vĩnh viễn.

Kết luận

Bạn đã cấu hình server Nginx của mình để sử dụng mã hóa mạnh với chứng chỉ SSL tự ký cho các kết nối từ client. Điều này sẽ cho phép bạn phục vụ các request một cách an toàn và ngăn chặn các bên thứ ba đọc lưu lượng truy cập của bạn. Một giải pháp thay thế bạn có thể tìm hiểu là sử dụng chứng chỉ SSL từ Let’s Encrypt, một tổ chức phát hành chứng chỉ TLS/SSL miễn phí, và sau đó kích hoạt mã hóa HTTPS trên web server của mình.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất