Sau bài này bạn làm được: đọc thông tin cert bằng opensslcurl; giải thích chuỗi CA và tại sao thiếu intermediate làm một số client lỗi; cấu hình đúng SNI khi hosting nhiều domain trên một IP.


TLS làm gì — ba tính chất

Transport Layer Security cung cấp:

  1. Mã hóa (Encryption): dữ liệu trên đường truyền không đọc được nếu bị chặn.
  2. Xác thực server (Authentication): client chắc chắn đang nói chuyện với đúng server (không bị man-in-the-middle).
  3. Toàn vẹn (Integrity): dữ liệu không bị thay đổi trên đường truyền.

Bài này tập trung xác thực — phần hay gây incident nhất.


Chứng chỉ và chuỗi tin cậy

Chứng chỉ TLS (X.509) chứa:

  • Public key của server.
  • Tên hợp lệ (CN và SAN — Subject Alternative Name).
  • Thời hạn (not before / not after).
  • Chữ ký của CA ký chứng chỉ này.

Chuỗi tin cậy (Chain of Trust):

[Root CA]  ──── ký ────▶  [Intermediate CA]  ──── ký ────▶  [Leaf cert của server]
                                                                 └── chứa public key
                                                                 └── SAN: api.example.com
Client tin Root CA
  → Root CA ký Intermediate → tin Intermediate
  → Intermediate ký Leaf → tin Leaf
  → Server xác thực thành công

Root CA được OS/trình duyệt cài sẵn (Mozilla, Apple, Microsoft). Bạn không tự đăng ký root CA; thay vào đó, mua cert từ CA có root đã được tin hoặc dùng Let’s Encrypt (free, root được hầu hết OS/browser tin từ 2021+).

Thiếu Intermediate trong cấu hình server:

Server chỉ gửi: [Leaf cert]  (thiếu Intermediate)

Firefox/Chrome: có cache intermediate → vẫn verify được
curl / mobile app cũ: không có cache → ERR_CERT_AUTHORITY_INVALID

→ Luôn cấu hình server gửi full chain (leaf + tất cả intermediate).


SAN — Subject Alternative Name

Ngày nay tên hợp lệ của cert nằm trong SAN, không phải CN (CN bị deprecated cho tên miền):

X509v3 Subject Alternative Name:
    DNS:example.com
    DNS:www.example.com
    DNS:api.example.com
    DNS:*.staging.example.com  ← wildcard chỉ cover một level

Wildcard *.example.com:

  • Cover: www.example.com, api.example.com
  • Không cover: example.com (apex), a.b.example.com (hai cấp)
  • Phải thêm riêng apex vào SAN nếu cần.

SNI — Server Name Indication

Vấn đề: một server có một IP:443 nhưng host nhiều tên miền, mỗi tên cần cert khác nhau. TLS handshake xảy ra trước HTTP request — server cần biết tên để chọn cert ngay từ đầu.

Giải pháp: SNI — client gửi tên host trong ClientHello (bước đầu TLS):

Client → Server: ClientHello {
  server_name: "api.example.com"   ← SNI extension
  supported_versions: TLS 1.3
  ...
}

Server nhận SNI → chọn cert phù hợp → gửi cert trong ServerHello

Góc DevOps:

  • NGINX: server_name trong từng server {} block → SNI routing tự động.
  • Kubernetes Ingress: spec.rules[].host → Ingress controller chọn TLS secret theo SNI.
  • Nếu LB không truyền SNI xuống upstream → upstream luôn trả cert mặc định → mismatch.

ECH — Encrypted Client Hello

SNI truyền tên miền ở dạng plaintext trong ClientHello — ISP, proxy, mạng công cộng đều đọc được. Đây là lỗ hổng privacy lớn: kẻ quan sát vẫn biết bạn vào vietcombank.com.vn hay github.com dù traffic đã mã hoá.

ECH (Encrypted Client Hello, RFC 9460) mã hoá toàn bộ ClientHello (kể cả SNI) bằng public key mà DNS publish trong bản ghi HTTPS/SVCB:

dig HTTPS crypto.example.com
# 1 . alpn="h2,h3" port=443 ipv4hint=... ech=AEH+DQB...

Hỗ trợ 2025:

  • Cloudflare bật ECH mặc định cho domain dùng hạ tầng của họ (2023+).
  • Firefox bật mặc định từ 118; Chrome flag chrome://flags/#encrypted-client-hello.
  • NGINX mainline + BoringSSL có patch; Envoy đang tiến tới GA.

Góc vận hành: ECH cần zone HTTPS record trên DNS authoritative và cấu hình key rotation trên LB — dễ nhất là dùng CDN đã managed.


Hậu lượng tử — thuật toán hybrid

Máy tính lượng tử (khi có đủ quy mô) sẽ phá key exchange cổ điển (RSA, ECDH). Nguy cơ “harvest now, decrypt later” — attacker lưu traffic TLS hôm nay, giải mã sau — là lý do các CA/browser đang gấp rút triển khai:

  • ML-KEM (Kyber) được NIST chuẩn hoá 8/2024 (FIPS 203) làm thuật toán key encapsulation hậu lượng tử.
  • X25519MLKEM768 là hybrid key exchange kết hợp X25519 (cổ điển) và ML-KEM-768 (hậu lượng tử) — an toàn nếu một trong hai còn vững.
  • Chrome bật mặc định từ 124 (4/2024); Cloudflare và AWS đã hỗ trợ server-side.

Thực tế 2025: nếu bạn vận hành TLS terminator (NGINX, Envoy) phiên bản cũ chỉ hỗ trợ X25519, bạn có thể thấy:

Client (Chrome 124+) offer: X25519MLKEM768, X25519
Server (NGINX cũ):         chọn X25519  ← fallback, vẫn hoạt động

Không phải lo ngay, nhưng trong roadmap 1–2 năm nên cân nhắc nâng OpenSSL ≥ 3.5 / BoringSSL mới để hỗ trợ hybrid. Chứng chỉ ký bằng thuật toán hậu lượng tử (ML-DSA) còn xa hơn — tạm thời vẫn RSA/ECDSA.


Các lỗi TLS thường gặp

LỗiNguyên nhânKiểm tra
ERR_CERT_AUTHORITY_INVALIDSelf-signed hoặc thiếu intermediateopenssl s_client -showcerts
ERR_CERT_DATE_INVALIDCert hết hạn hoặc đồng hồ máy saiopenssl x509 -dates
ERR_CERT_COMMON_NAME_INVALIDTên truy cập không trong SANopenssl x509 -text | grep DNS
SSL_ERROR_RX_RECORD_TOO_LONGHTTP trên cổng 443 (không có TLS)Kiểm tra cấu hình port

Công cụ kiểm tra cert

# Xem cert server đang gửi (cả chain)
openssl s_client -connect api.example.com:443 -showcerts 2>/dev/null \
  | openssl x509 -noout -text | grep -E "Subject|DNS|Not"

# Kiểm tra ngày hết hạn
echo | openssl s_client -connect api.example.com:443 2>/dev/null \
  | openssl x509 -noout -dates

# curl hiện thông tin TLS
curl -vI https://api.example.com 2>&1 | grep -E "SSL|expire|subject|issuer"

# Kiểm tra SNI cụ thể (dùng khi test qua IP thẳng)
openssl s_client -connect 1.2.3.4:443 -servername api.example.com

Tóm tắt

  • Chuỗi cert đầy đủ (leaf + intermediate) là điều kiện để mọi client verify được, không chỉ browser.
  • SAN là nơi khai báo tên hợp lệ — wildcard có giới hạn.
  • SNI cho phép nhiều domain trên một IP:443 — cần LB và proxy truyền SNI đúng.
  • openssl s_client -showcerts + curl -v là bộ đôi debug TLS hiệu quả nhất.

Câu hỏi hay gặp

Wildcard *.example.com mà truy cập example.com (apex) báo lỗi cert — sửa sao?

Trả lời: Wildcard không khớp apex example.com. Cần thêm example.com vào SAN (hoặc cert riêng cho apex).

LB forward theo IP, backend nhiều cert theo domain — chọn cert đúng thế nào?

Trả lời: Dùng SNI: client (hoặc LB ở chế độ SSL passthrough / re-encrypt) phải gửi Server Name trong TLS ClientHello. Backend (hoặc LB terminate TLS) chọn cert theo server_name. Nếu LB chỉ forward IP mà không truyền SNI, backend thường trả cert mặc định — dễ sai.

openssl verify OK nhưng Chrome báo hết hạn — vì sao?

Trả lời: Khác thời gian đồng hồ máy client, cache OCSP/stapling, hoặc Chrome kiểm tra CT log / pinning khác CLI. Cũng có thể bạn s_client tới IP/cert khác với tab Chrome (SNI/host khác).


Bài tiếp theo (Giai đoạn II): Checklist debug mạng từ DNS tới HTTP — tổng hợp 4 bài giao thức vào một quy trình debug có hệ thống.