OpenSSL CLI: Debug lỗi HTTPS môi trường Production và xây dựng Private CA

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Cảnh báo Production lúc 2:14 sáng

Lúc 2:14 sáng, điện thoại của tôi rung bần bật trên kệ đầu giường. Bộ cân bằng tải (load balancer) đang báo lỗi 502 Bad Gateway, và log tràn ngập lỗi SSL_ERROR_BAD_CERT_DOMAIN. Đội ngũ frontend cam đoan rằng họ đã cập nhật chứng chỉ, nhưng trình duyệt thì lại báo khác. Trong những thời điểm như thế này, các bảng điều khiển giao diện (UI dashboard) thường đánh lừa bạn. Bạn cần những dữ liệu thô mà chỉ OpenSSL CLI mới có thể cung cấp.

Sau khi xử lý một loạt các cuộc tấn công brute-force vào SSH tháng trước, tôi đã ngừng tin vào câu nói “nó đáng lẽ phải hoạt động”. Tôi xác minh mọi thứ. OpenSSL không quan tâm đến các script cấu hình hay bảng điều khiển quản trị của bạn nói gì. Nó hiển thị chính xác những gì server trình diện trong quá trình handshake, biến nó thành công cụ tối thượng để loại bỏ các thông tin nhiễu.

Ba lý do khiến chứng chỉ bị lỗi

Hầu hết các lỗi kết nối đều gói gọn trong ba thủ phạm: chứng chỉ hết hạn, sự không khớp giữa private key và chứng chỉ công khai (public cert), hoặc thiếu chuỗi trung gian (intermediate chain). Tôi thường thấy các quản trị viên mới vào nghề sao chép chứng chỉ chính nhưng lại bỏ qua tệp bundle. Điều này có thể vẫn hoạt động trên một số trình duyệt có lưu cache chứng chỉ trung gian, nhưng sẽ thất bại thảm hại đối với người dùng di động hoặc các API client.

Kiến trúc Microservices càng làm mọi thứ rắc rối hơn. Khi bạn điều hướng lưu lượng qua Nginx, HAProxy và Traefik trên 20 subdomain khác nhau, chỉ cần một tệp .pem sai có thể kích hoạt cảnh báo “Kết nối của bạn không phải là riêng tư” cho hàng ngàn người dùng. Một lỗi đánh máy nhỏ trong đường dẫn cũng có thể làm sập một gateway đang chạy production.

Chọn công cụ Debug phù hợp

Các trình quét trực tuyến như SSL Labs rất tuyệt, nhưng chúng không thể nhìn xuyên qua tường lửa của bạn. Nếu bạn đang debug một môi trường staging hoặc một API nội bộ nằm sau VPN, những công cụ đó vô dụng. Bạn có thể thử curl -v, nhưng nó thường ẩn đi lý do cụ thể khiến quá trình handshake thất bại.

Sử dụng trực tiếp OpenSSL CLI là phương pháp đáng tin cậy nhất. Nó cho phép bạn mô phỏng một kết nối trình duyệt thực tế, kiểm tra các tệp trước khi chúng được triển khai, và thậm chí đóng vai trò như một Certificate Authority (CA) riêng cho các phòng lab nội bộ.

Giai đoạn 1: Debug các kết nối đang hoạt động (Live)

Khi một trang web bị sập, hãy bắt đầu bằng cách xem server thực sự đang gửi cái gì. Lệnh s_client là công cụ đắc lực nhất ở đây. Đừng quên cờ Server Name Indication (SNI). Nếu server của bạn host nhiều trang web trên một IP, server sẽ không biết phải hiển thị chứng chỉ nào nếu thiếu cờ -servername.

# Kiểm tra chứng chỉ của một server từ xa
openssl s_client -connect itfromzero.com:443 -servername itfromzero.com

Kiểm tra đầu ra ở các phần “Certificate chain” và “Verification”. Nếu bạn thấy “Verification error: unable to get local issuer certificate,” nghĩa là server của bạn đang thiếu tệp intermediate bundle. Để bỏ qua các khối văn bản dài dòng và chỉ xem ngày hết hạn, hãy chuyển đầu ra vào tiện ích x509:

# Chỉ trích xuất các ngày có hiệu lực
openssl s_client -connect google.com:443 -servername google.com 2>/dev/null | openssl x509 -noout -dates

Giai đoạn 2: Xác minh tệp tin trước khi triển khai

Trước khi bạn reload Nginx và mạo hiểm gây ra sự cố production, hãy xác minh các tệp tin cục bộ. Tôi đã thấy các kỹ sư dành bốn giờ để debug tệp cấu hình trong khi vấn đề chỉ đơn giản là cặp key không khớp nhau. Nếu chứng chỉ không khớp với private key, web server sẽ không thể khởi động hoặc từ chối mọi nỗ lực handshake.

Kiểm tra Metadata của chứng chỉ

Để xác nhận ai đã cấp chứng chỉ và kiểm tra Subject Alternative Names (SANs), hãy chạy lệnh này:

openssl x509 -in server.crt -text -noout

Kiểm tra khớp Modulus

Đây là bước kiểm tra bắt buộc trước mỗi lần triển khai. Public key bên trong chứng chỉ phải khớp hoàn toàn với private key. Bạn có thể xác minh điều này bằng cách so sánh mã hash MD5 của “modulus” của chúng. Nếu hai chuỗi này không giống hệt nhau, đừng triển khai chúng.

# Kiểm tra hash modulus của chứng chỉ
openssl x509 -noout -modulus -in server.crt | openssl md5

# Kiểm tra hash modulus của private key
openssl rsa -noout -modulus -in server.key | openssl md5

Giai đoạn 3: Xây dựng Private CA cho môi trường nội bộ

Hãy ngừng nhấp vào “Nâng cao -> Tiếp tục” trên các cảnh báo chứng chỉ tự ký (self-signed) trong môi trường phát triển của bạn. Cách tiếp cận chuyên nghiệp là xây dựng một Private CA. Bạn tạo một chứng chỉ Root, tin tưởng nó trên máy của các thành viên trong đội, và sau đó ký bao nhiêu chứng chỉ tùy thích cho việc kiểm thử local.

1. Tạo Root CA

Đầu tiên, tạo master key và chứng chỉ root. Hãy đối xử with key này như mật khẩu production của bạn; nếu ai đó lấy cắp được nó, họ có thể giả mạo bất kỳ trang web nào trong mạng của bạn.

# Tạo một RSA key 4096-bit
openssl genrsa -out MyInternalCA.key 4096

# Tạo Root Certificate (Có hiệu lực trong 10 năm)
openssl req -x509 -new -nodes -key MyInternalCA.key -sha256 -days 3650 -out MyInternalCA.pem

2. Tạo chứng chỉ cho dịch vụ

Nếu bạn có một trang web local tại api.dev.local, bạn sẽ cần một private key và một Yêu cầu ký chứng chỉ (CSR).

# Tạo service key
openssl genrsa -out api.dev.local.key 2048

# Tạo CSR
openssl req -new -key api.dev.local.key -out api.dev.local.csr

3. Ký yêu cầu với CA của bạn

Các trình duyệt hiện đại như Chrome và Safari yêu cầu Subject Alternative Name (SAN) để tin tưởng một chứng chỉ. Tạo một tệp cấu hình nhỏ tên là dev.ext để bao gồm thông tin này.

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = api.dev.local

Bây giờ, hãy ký chứng chỉ. Lưu ý rằng tôi đặt giới hạn là 825 ngày, vì macOS và iOS sẽ từ chối bất kỳ chứng chỉ nào có thời hạn dài hơn.

openssl x509 -req -in api.dev.local.csr -CA MyInternalCA.pem -CAkey MyInternalCA.key \
-CAcreateserial -out api.dev.local.crt -days 825 -sha256 -extfile dev.ext

Nhập MyInternalCA.pem vào kho lưu trữ tin cậy (trust store) của hệ điều hành. Sau khi hoàn tất, api.dev.local sẽ hiển thị biểu tượng ổ khóa xanh sạch sẽ, mô phỏng chính xác môi trường production của bạn.

Các thực hành tốt nhất về lâu dài

OpenSSL không nhất thiết phải là một mớ hỗn độn khó hiểu với các cờ lệnh kỳ quặc. Nếu bạn tuân theo một quy trình làm việc có hệ thống, bạn có thể giải quyết hầu hết mọi vấn đề TLS trong vài phút.

Luôn kiểm tra chuỗi tin cậy (chain of trust) bằng s_client, xác minh khớp modulus trước mỗi lần reload, và sử dụng Private CA cho đội ngũ của bạn để tránh tình trạng “nhờn cảnh báo chứng chỉ”.

Bảo mật là một thói quen. Cho dù bạn đang gia cố SSH hay đảm bảo quá trình handshake TLS diễn ra hoàn hảo, các công cụ bạn làm chủ sẽ định nghĩa độ tin cậy cho hạ tầng của bạn. Hãy làm quen với CLI, và những cảnh báo lúc 2 giờ sáng đó sẽ trở nên dễ xử lý hơn nhiều.

Share: