Trước khi bắt đầu
Bài viết này hướng dẫn cách thiết lập cân bằng tải Nginx chỉ với một chứng chỉ SSL trên máy cân bằng tải. Điều này sẽ giảm thiểu công việc quản lý SSL của bạn, vì các bản cập nhật OpenSSL và các khóa và chứng chỉ hiện đã có thể được quản lý từ chính máy cân bằng tải.
Nginx có thể được cấu hình như một máy cân bằng tải để phân phối lưu lượng vào từ nhiều máy chủ backend. Termination SSL là quá trình xảy ra trên máy cân bằng tải, nơi xử lý mã hóa/giải mã SSL để lưu lượng giữa máy cân bằng tải và máy chủ backend được chuyển đổi sang giao thức HTTP. Các backend phải được bảo mật bằng cách hạn chế truy cập vào địa chỉ IP của máy cân bằng tải, điều này sẽ được giải thích sau trong bài viết này.
Chuẩn bị môi trường cài đặt
Máy chủ Nginx (Frontend)
- Image: Ubuntu 22.04
- Hostname: loadbalancer
- Private IP: 172.16.6.69
Web server 1 (Backend)
- Image: Ubuntu 22.04
- Hostname: web1
- Private IP: 172.16.6.163
Web server 2 (Backend)
- Image: Ubuntu 22.04
- Hostname: web2
- Private IP: 172.16.6.214
Domain name – example.com
Cập nhật và nâng cấp phần mềm trên tất cả ba máy chủ.
sudo apt-get update && apt-get upgrade -y
Khởi động lại từng máy chủ để áp dụng các bản nâng cấp. Điều này rất quan trọng, vì OpenSSL cần phải ở phiên bản mới nhất để đảm bảo an toàn.
Chúng ta sẽ thiết lập một block server Nginx mới cho tên miền với mô-đun upstream để cân bằng tải các server backend.
Bạn có thể cài đặt nhanh chóng bằng apt-get:
sudo apt-get install nginx -y
sudo systemctl enable nginx
Trên hai máy chủ backend, cập nhật các kho lưu trữ và cài đặt Apache:
sudo apt-get install apache2 -y
sudo systemctl enable apache2
Cài đặt PHP trên 2 máy chủ backend
sudo apt install php8.1 libapache2-mod-php8.1 mcrypt -y
Tạo Khóa và Tạo Chứng chỉ SSL
Trong phần này, bạn sẽ thực hiện các bước cần thiết để tạo một chứng chỉ SSL. Bài viết này giải thích chi tiết về chứng chỉ SSL trên Nginx.
Tạo thư mục chứa chứng chỉ SSL và chuyển đến thư mục đó.
sudo mkdir -p /etc/nginx/ssl/example.com
cd /etc/nginx/ssl/example.com
Tạo Private Key
sudo openssl genrsa -des3 -out server.key 2048
Xóa passphrase của nó:
sudo openssl rsa -in server.key -out server.key
Tiếp theo, tạo yêu cầu ký chứng chỉ (certificate signing request – CSR):
sudo openssl req -new -key server.key -out server.csr
Lệnh này sẽ yêu cầu terminal hiển thị danh sách các trường cần được điền thông tin.
Dòng quan trọng nhất là “Common Name” (Tên thông thường). Nhập tên miền chính thức của bạn vào đây hoặc, nếu bạn chưa có, nhập địa chỉ IP của trang web của bạn. Để trống mật khẩu và tên công ty tùy chọn.

Sử dụng CSR này để nhận một chứng chỉ hợp lệ từ một cơ quan chứng chỉ hoặc tạo một chứng chỉ tự ký bằng lệnh sau:
sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Output
Certificate request self-signature ok
subject=C = VN, ST = Hanoi, L = Hanoi, O = ETC, OU = ETC, CN = 172.16.6.69, emailAddress = webmaster@awesomeinc.com
Sau khi hoàn thành, thư mục này sẽ chứa các tệp tin sau:
server.key – Khóa riêng tư (private key)
ca-certs.pem – Một tập hợp các chứng chỉ gốc và trung gian của CA của bạn. Chỉ tồn tại nếu bạn đã nhận một chứng chỉ hợp lệ từ một CA.
server.crt – Chứng chỉ SSL cho tên miền của bạn.
Tạo một tệp tin virtual host trong thư mục của Nginx
Tạo một tệp tin virtual host trong thư mục Nginx
sudo vi /etc/nginx/sites-available/example.com
Thêm mô-đun upstream chứa địa chỉ IP riêng của các máy chủ backend.
upstream mywebapp1 {
server 172.16.6.163;
server 172.16.6.214;
}
Bắt đầu khối server sau dòng này. Khối này chứa tên miền, tham chiếu đến các máy chủ upstream và các tiêu đề cần được chuyển tiếp đến backend.
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Hướng dẫn sử dụng chỉ thị proxy_set_header
để chuyển tiếp thông tin quan trọng về yêu cầu đến các máy chủ upstream.
Lưu tệp tin này và tạo một liên kết symbolic link đến thư mục sites-enabled.
Để tạo liên kết symbolic link, sử dụng lệnh sau:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
Thực hiện kiểm tra cấu hình để kiểm tra lỗi.
sudo service nginx configtest
Nếu không có lỗi được hiển thị, tải lại dịch vụ nginx.
sudo service nginx reload
Hiện tại, cân bằng tải đã được cấu hình cho giao thức HTTP.
Enable SSL
Thêm các chỉ thị sau vào tệp tin virtual host (/etc/nginx/sites-available/example.com) bên trong khối server {}. Các dòng này sẽ được hiển thị trong ngữ cảnh trong ví dụ tiếp theo.
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
Nó sẽ trông như thế này
server {
listen 80;
listen 443 ssl;
server_name example.com www.example.com;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Kiểm tra lỗi cấu hình và tải lại dịch vụ Nginx.
sudo service nginx configtest && service nginx reload
Bảo mật các máy chủ backend
Hiện tại, trang web được lưu trữ trên các máy chủ backend có thể được truy cập trực tiếp bởi bất kỳ ai biết địa chỉ IP công khai của nó. Điều này có thể được ngăn chặn bằng cách cấu hình các máy chủ web trên backend chỉ lắng nghe trên giao diện riêng. Các bước để làm điều này trong Apache như sau.
Chỉnh sửa tệp tin ports.conf.
sudo vi /etc/apache2/ports.conf
Tìm dòng sau:
Listen 80
Thay thế nó bằng địa chỉ IP riêng của máy chủ backend:
Listen 172.16.6.163:80
Thực hiện điều này trên tất cả các máy chủ backend và khởi động lại Apache.
sudo service apache2 restart
Bước tiếp theo là hạn chế truy cập HTTP chỉ cho địa chỉ IP riêng của máy cân bằng tải. Quy tắc tường lửa sau đây sẽ thực hiện điều này.
sudo iptables -I INPUT -m state --state NEW -p tcp --dport 80 ! -s 172.16.6.69 -j DROP
Thay thế “example” bằng địa chỉ IP riêng của máy cân bằng tải và thực hiện quy tắc này trên tất cả các máy chủ backend.
Kiểm tra quá trình cài đặt
Tạo một tệp PHP trên tất cả các máy chủ backend (web1 và web2 trong ví dụ này).
sudo vi /var/www/html/test.php
Tệp này sẽ in ra tên miền đã truy cập, địa chỉ IP của máy chủ, địa chỉ IP của người dùng và cổng đã truy cập.
<?php
header( 'Content-Type: text/plain' );
echo 'Host: ' . $_SERVER['HTTP_HOST'] . "\n";
echo 'Remote Address: ' . $_SERVER['REMOTE_ADDR'] . "\n";
echo 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
echo 'X-Forwarded-Proto: ' . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "\n";
echo 'Server Address: ' . $_SERVER['SERVER_ADDR'] . "\n";
echo 'Server Port: ' . $_SERVER['SERVER_PORT'] . "\n\n";
?>
Sau khi hoàn tất tạo tập test.php cho cả 2 máy chủ backend. Chúng ta mở trình duyệt và truy cập. Bạn sẽ mở 2 tab để thấy được rằng máy chủ Nginx sẽ phân phối đều request đến 2 máy chủ backend.
Tab 1: https://IP_loadbalancer/test.php

Tab 2: https://IP_loadbalancer/test.php

Cải thiện Cấu hình SSL
Phần này giải thích cách cấu hình SSL theo các tiêu chuẩn tốt nhất để loại bỏ các lỗ hổng với các cipher và giao thức cũ. Các dòng riêng lẻ được hiển thị trong phần này và tệp cấu hình hoàn chỉnh được hiển thị ở phần cuối của hướng dẫn này.
Bật bộ nhớ cache phiên SSL cải thiện hiệu suất của các trang web HTTPS. Các chỉ thị sau phải đặt sau ssl_trusted_certificate. Chúng kích hoạt việc chia sẻ bộ nhớ cache có kích thước 20MB với tuổi thọ cache là 10 phút.
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
Xác định các giao thức và cipher sẽ được sử dụng trong kết nối SSL. Ở đây, chúng ta đã bỏ qua SSLv2 và vô hiệu hóa các cipher không an toàn như MD5 và DSS.
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
Strict Transport Security (HSTS) chỉ thị tất cả các trình duyệt web hỗ trợ chỉ sử dụng HTTPS. Bật nó bằng chỉ thị add_header.
add_header Strict-Transport-Security "max-age=31536000";
Kiểm tra lỗi cấu hình và tải lại dịch vụ Nginx
sudo service nginx configtest && service nginx reload
Sau khi cấu hình và cải thiện việc SSL termination, tệp cấu hình hoàn chỉnh sẽ trông như sau:
/etc/nginx/sites-available/example.com
upstream mywebapp1 {
server 172.16.6.163;
server 172.16.6.214;
}
server {
listen 80;
listen 443 ssl;
server_name example.com www.emxaple.com;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
add_header Strict-Transport-Security "max-age=31536000";
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Tổng kết