A. Nginx as SERVER with mTLS
Trong hệ thống nội bộ, ca certificate thường dùng chung cả cho server và client.
Nhưng nếu bảo mật hơn, có thể tách riêng ra. Xem phần C.
Ở phần A này tôi sẽ dùng chung
1.1 Generate the CA Certificate and Key
openssl genpkey -algorithm RSA -out /etc/nginx/cert/ca.key
openssl req -days 3650 -new -x509 -key /etc/nginx/cert/ca.key -out /etc/nginx/cert/ca.crt -subj "/OU=CA-OrgUnit/CN=CA-MASTER"
openssl x509 -text -noout -in /etc/nginx/cert/ca.crt
1.2 Generate the Server Certificate and Key
openssl genpkey -algorithm RSA -out /etc/nginx/cert/server.key
openssl req -new -key /etc/nginx/cert/server.key -out /etc/nginx/cert/server.csr -subj "/OU=MyOrgUnit/CN=myserver.com.vn"
openssl x509 -req -days 3650 -in /etc/nginx/cert/server.csr -CA /etc/nginx/cert/ca.crt -CAkey /etc/nginx/cert/ca.key -CAcreateserial -out /etc/nginx/cert/server.crt
openssl x509 -text -noout -in /etc/nginx/cert/server.crt
1.3 Generate the Client Certificate and Key
openssl genpkey -algorithm RSA -out /etc/nginx/cert/client.key
openssl req -new -key /etc/nginx/cert/client.key -out /etc/nginx/cert/client.csr -subj "/OU=MyOrgUnit/CN=MyClient"
openssl x509 -req -days 3650 -in /etc/nginx/cert/client.csr -CA /etc/nginx/cert/ca.crt -CAkey /etc/nginx/cert/ca.key -CAcreateserial -out /etc/nginx/cert/client.crt
openssl x509 -text -noout -in /etc/nginx/cert/client.crt
2 Configure Nginx for SSL/TLS and mTLS
server {
listen 443 ssl;
# Server certificate and key
ssl_certificate /etc/nginx/cert/server.crt;
ssl_certificate_key /etc/nginx/cert/server.key;
# CA certificate for client verification
ssl_client_certificate /etc/nginx/cert/ca.crt;
ssl_verify_client optional;
location / {
default_type text/plain;
if ($ssl_client_verify != SUCCESS) {
return 403 'blocked access to mTLS-protected resource';
}
return 200 'access to mTLS-protected resource';
}
}
Reload nginx apply new config
nginx -s reload
3: Testing mTLS with cURL
curl -vk https://localhost
> blocked access to mTLS-protected resource
curl --cert /etc/nginx/cert/client.crt --key /etc/nginx/cert/client.key --cacert /etc/nginx/cert/ca.crt https://localhost
> access to mTLS-protected resource
openssl s_client -connect localhost:443 -cert /etc/nginx/cert/client.crt -key /etc/nginx/cert/client.key -CAfile /etc/nginx/cert/ca.crt
________________________________________
Refer: https:/medium.com/@mahernaija/new-2025-how-to-configure-mutual-tls-mtls-for-secure-nginx-206f983ba571
B. Nginx as CLIENT in mTLS
Chuẩn bị bộ client cert/key. Ngoài ra upstream_ca.crt chính là Ca-Certificate
server {
listen 80;
server_name my-gateway.local;
location / {
# 1. Đường dẫn tới Server backend yêu cầu mTLS
proxy_pass https://secure-upstream-server.local:443;
# 2. Bật các cấu hình SSL cho Proxy
proxy_ssl_server_name on; # Gửi SNI (Server Name Indication) nếu cần
# Định nghĩa tên miền sẽ gửi trong TLS Handshake đến Upstream
# Thường sử dụng biến $host (tên miền client gửi lên) hoặc một chuỗi cố định như 'backend.com'
proxy_ssl_name $host;
# 3. Gửi chứng chỉ và khóa của Nginx (đóng vai trò Client) lên Server
proxy_ssl_certificate /etc/nginx/certs/client.crt;
proxy_ssl_certificate_key /etc/nginx/certs/client.key;
# 4. Xác thực chứng chỉ của Server backend để đảm bảo an toàn
proxy_ssl_trusted_certificate /etc/nginx/certs/upstream_backend_ca.crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
# Các cấu hình proxy thông thường khác
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
C. Chia riêng rẽ ca certificate client/server
Không muốn dùng chung. Ta sẽ làm như sau
1. Tạo "Upstream CA" và chứng chỉ cho Upstream Server:*8443
mkdir -p /etc/nginx/certs && cd /etc/nginx/certs
# 1.1 Tạo Upstream CA (Dùng để ký cho Server)
openssl genrsa -out upstream_ca.key 4096
openssl req -new -x509 -days 3650 -key upstream_ca.key -out upstream_ca.crt -subj "/CN=UpstreamServerRootCA"
# 1.2 Tạo chứng chỉ cho Upstream Server (Sẽ cài trên máy chủ backend)
openssl genrsa -out upstream_server.key 2048
openssl req -new -key upstream_server.key -out upstream_server.csr -subj "/CN=secure-upstream.local"
openssl x509 -req -days 365 -in upstream_server.csr -CA upstream_ca.crt -CAkey upstream_ca.key -CAcreateserial -out upstream_server.crt
2. Tạo "Client CA" và chứng chỉ cho Nginx Client:80
mkdir -p /etc/nginx/certs && cd /etc/nginx/certs
# 2.1 Tạo Client CA riêng biệt (Dùng để ký cho các Client/Nginx)
openssl genrsa -out client_ca.key 4096
openssl req -new -x509 -days 3650 -key client_ca.key -out client_ca.crt -subj "/CN=MyClientInternalCA"
# 2.2 Tạo chứng chỉ cho Nginx Client (Sẽ cài trên Nginx Proxy)
openssl genrsa -out nginx_client.key 2048
openssl req -new -key nginx_client.key -out nginx_client.csr -subj "/CN=NginxProxyClient"
openssl x509 -req -days 365 -in nginx_client.csr -CA client_ca.crt -CAkey client_ca.key -CAcreateserial -out nginx_client.crt
Cấu hình nginx
1. Khối Server 1 (Nginx Client / Reverse Proxy): Nhận HTTP cổng 80 từ người dùng → Dùng mTLS truyền tiếp lên Backend.
2. Khối Server 2 (Upstream Server / Backend): Chạy HTTPS cổng 8443 → Yêu cầu mTLS và chỉ tin tưởng chứng chỉ từ Client CA.
Sơ đồ: client nginx:80 + Proxy pass Backend :8443 with mtls - Nginx:8443 with mtls
# ====================================================================
# VAI TRÒ 1: NGINX ĐÓNG VAI TRÒ CLIENT (REVERSE PROXY)
# ====================================================================
server {
listen 80;
server_name localhost;
location / {
# Chuyển tiếp tới Upstream Server chạy HTTPS cổng 8443
proxy_pass https://secure-upstream.local:8443;
proxy_ssl_server_name on; #send SNI
# ------------------------------------------------------------
# [A] XÁC THỰC SERVER: Nginx kiểm tra danh tính của Upstream Server
# ------------------------------------------------------------
proxy_ssl_verify on;
# CHỈ tin tưởng Server nếu chứng chỉ của nó do "Upstream CA" ký
proxy_ssl_trusted_certificate /etc/nginx/certs/upstream_ca.crt;
proxy_ssl_verify_depth 4;
# ------------------------------------------------------------
# [B] XÁC THỰC CLIENT: Nginx gửi chứng chỉ của mình lên Server
# ------------------------------------------------------------
# Chứng chỉ này được tạo và ký bởi "Client CA" riêng biệt, sẽ gửi sang server để verify
proxy_ssl_certificate /etc/nginx/certs/nginx_client.crt;
proxy_ssl_certificate_key /etc/nginx/certs/nginx_client.key;
# Các cấu hình header cơ bản
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# ====================================================================
# VAI TRÒ 2: UPSTREAM SERVER (GIẢ LẬP MÁY CHỦ BACKEND NHẬN KẾT NỐI mTLS)
# ====================================================================
server {
listen 8443 ssl;
server_name secure-upstream.local;
# Chứng chỉ của bản thân Server (Được ký bởi Upstream CA). Như 1 ssl bình thường nhưng phơi ra để client kiểm tra.
ssl_certificate /etc/nginx/certs/upstream_server.crt;
ssl_certificate_key /etc/nginx/certs/upstream_server.key;
# Cấu hình mTLS phía nhận: Bắt buộc phải có chứng chỉ Client hợp lệ
ssl_verify_client on;
# CHỈ chấp nhận chứng chỉ Client nếu nó được ký bởi "Client CA"
ssl_client_certificate /etc/nginx/certs/client_ca.crt;
ssl_verify_depth 2;
location / {
# Trả về phản hồi text nếu mTLS thành công tốt đẹp
add_header Content-Type text/plain;
return 200 "Chúc mừng! Kết nối mTLS giữa Nginx Client và Upstream Server thành công bằng 2 CA độc lập.\n";
}
}
Khi gọi trực tiếp vào 8443 sẽ bị lỗi
Đứng ở client ta phải cung cấp đủ 3 key mới gọi được
# curl --cacert /etc/nginx/certs/upstream_ca.crt --key /etc/nginx/certs/client_ca.key --cert /etc/nginx/certs/client_ca.crt https://secure-upstream.local:8443
Chúc mừng! Kết nối mTLS giữa Nginx Client và Upstream Server thành công bằng 2 CA độc lập.
# curl localhost:80
Chúc mừng! Kết nối mTLS giữa Nginx Client và Upstream Server thành công bằng 2 CA độc lập.