Khi bạn gõ https://, có một cuộc đàm phán diễn ra trước khi HTTP nói được câu nào — cuộc bắt tay TLS. Bài keep-alive đã đo nó tốn ~1–2 RTT; bài này mở nó ra xem từng bước làm gì: thỏa thuận phiên bản giao thức, chọn thuật toán mã hóa (cipher), trao khóa tạm để cùng tính ra khóa chung, và server chứng minh nó đúng là ai bằng chứng chỉ. Công cụ tuyệt vời để soi là openssl s_client. Đo thật với openssl 3.0 trên một kết nối HTTPS thật.

TLS làm ba việc

Trước khi HTTP chạy, TLS thiết lập một kênh với ba bảo đảm:

  • Bí mật (confidentiality): dữ liệu được mã hóa — kẻ nghe lén trên đường truyền chỉ thấy byte ngẫu nhiên.
  • Toàn vẹn (integrity): mọi sửa đổi trên đường truyền bị phát hiện.
  • Xác thực (authentication): chứng chỉ chứng minh server đúng là tên miền nó tuyên bố — chống mạo danh (chi tiết bài sau về X.509).

Các bước bắt tay TLS 1.3

TLS 1.3 (chuẩn từ 2018) rút gọn còn một vòng khứ hồi (1-RTT), so với 2-RTT của TLS 1.2. Luồng message:

Client -> Server  ClientHello   (phiên bản, danh sách cipher, khóa tạm)
Server -> Client  ServerHello   (chọn cipher, khóa tạm của server)
                  EncryptedExtensions, Certificate, CertificateVerify, Finished
Client -> Server  Finished

Sau Finished của cả hai, hai bên đã cùng suy ra khóa chung (qua trao đổi Diffie-Hellman đường cong elliptic) và dữ liệu HTTP mã hóa bắt đầu chạy.

openssl s_client -connect host:443 -servername host   # bắt tay + in thông tin
openssl s_client ... -msg               # in các handshake message
openssl s_client ... -alpn h2,http/1.1  # thỏa thuận giao thức ứng dụng
openssl s_client ... -tls1_2 / -tls1_3  # ép phiên bản để so

Ảnh chụp đoạn mã nền tối giải thích TLS handshake thỏa thuận khóa và xác thực trước khi gửi dữ liệu, TLS làm ba việc trước khi HTTP chạy bí mật mã hóa dữ liệu kẻ nghe lén chỉ thấy rác, toàn vẹn phát hiện sửa đổi trên đường truyền, xác thực chứng chỉ chứng minh server đúng là ai nó nói, các bước bắt tay TLS 1.3 một vòng khứ hồi Client gửi Server ClientHello phiên bản cipher hỗ trợ khóa tạm, Server gửi Client ServerHello chọn cipher khóa tạm của server EncryptedExtensions Certificate CertificateVerify Finished, Client gửi Server Finished sau Finished hai bên đã có khóa chung dữ liệu HTTP mã hóa chạy TLS 1.3 chỉ 1-RTT TLS 1.2 cần 2-RTT nhanh hơn hẳn, xem bằng openssl s_client -connect host 443 -servername host, -msg in các handshake message, -alpn h2 http/1.1 thỏa thuận giao thức app, -tls1_2 -tls1_3 ép phiên bản

Hình 1: TLS bảo đảm bí mật, toàn vẹn, xác thực. Bắt tay TLS 1.3 gồm ClientHello → ServerHello + Certificate + Finished → Finished, chỉ 1-RTT. openssl s_client -msg cho xem từng message.

Đo thật: từng handshake message

Chạy openssl s_client -msg tới một host HTTPS thật, lọc các dòng handshake:

Ảnh chụp bảng kết quả đo thật nền tối chạy openssl 3.0 openssl s_client -connect coffeecode.vn 443, phần một các handshake message openssl -msg TLS 1.3 mũi tên ra ClientHello client gửi, mũi tên vào ServerHello server chọn cipher và khóa, mũi tên vào EncryptedExtensions, mũi tên vào Certificate server gửi chứng chỉ, mũi tên vào CertificateVerify ký để chứng minh giữ khóa riêng, mũi tên vào Finished, mũi tên ra Finished xong dữ liệu mã hóa chạy, phần hai kết quả thỏa thuận New TLSv1.3 Cipher is TLS_AES_256_GCM_SHA384 Server public key is 256 bit Verify return code 0 ok ALPN protocol http/1.1, phần ba TLS 1.3 vs 1.2 chuỗi chứng chỉ TLS 1.3 TLS_AES_256_GCM_SHA384 TLS 1.2 ECDHE-ECDSA-AES256-GCM-SHA384 chuỗi CN coffeecode.vn nhỏ hơn Let's Encrypt YE1 nhỏ hơn ISRG Root YE

Hình 2: Các handshake message thật của TLS 1.3: ClientHello (client gửi) → ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished (server) → Finished (client). Kết quả: TLSv1.3, cipher TLS_AES_256_GCM_SHA384, verify OK, ALPN http/1.1; chuỗi chứng chỉ 3 tầng.

Đọc kết quả:

  • Luồng message khớp lý thuyết: >>> ClientHello, <<< ServerHello, <<< EncryptedExtensions, <<< Certificate, <<< CertificateVerify, <<< Finished, >>> Finished. Điểm hay của TLS 1.3: từ sau ServerHello, mọi message (kể cả chứng chỉ) đã được mã hóa — TLS 1.2 gửi chứng chỉ dạng rõ, TLS 1.3 giấu đi.
  • Kết quả thỏa thuận: TLSv1.3, cipher TLS_AES_256_GCM_SHA384, khóa công khai server 256-bit (đường cong elliptic), Verify return code: 0 (ok) — chứng chỉ hợp lệ. CertificateVerify là bước server ký để chứng minh nó giữ khóa riêng ứng với chứng chỉ (không chỉ có bản sao chứng chỉ công khai).
  • ALPN: http/1.1 — đây là nơi HTTP/2 được thỏa thuận (nếu server bật): ngay trong bắt tay TLS, -alpn h2,http/1.1 cho client và server chọn giao thức ứng dụng. Host này chọn http/1.1.
  • TLS 1.3 vs 1.2: cùng server, ép -tls1_3 cho cipher TLS_AES_256_GCM_SHA384 (tên gọn, TLS 1.3 chuẩn hóa danh sách cipher rất ngắn); ép -tls1_2 cho ECDHE-ECDSA-AES256-GCM-SHA384 (tên dài, mô tả cả cách trao khóa ECDHE và ký ECDSA).

Đánh đổi và lưu ý

-servername (SNI) là bắt buộc với virtual hosting. Như bài Host đã nói, một IP phục vụ nhiều tên miền. TLS cần biết bạn hỏi tên miền nào ngay trong ClientHello để gửi đúng chứng chỉ — đó là SNI (Server Name Indication). Quên -servername với openssl là dễ nhận nhầm chứng chỉ mặc định và tưởng server cấu hình sai.

TLS 1.3 nhanh hơn và an toàn hơn — nên tắt hẳn 1.0/1.1. TLS 1.0/1.1 đã lỗi thời (nhiều lỗ hổng), TLS 1.2 vẫn ổn nhưng chậm hơn (2-RTT) và cho phép cipher yếu. Cấu hình server nên chỉ bật TLS 1.2 + 1.3. Kiểm nhanh bằng openssl s_client -tls1_1 — nếu kết nối được là server còn hở.

s_client là dao đa năng khi debug HTTPS. Nó cho biết chính xác phiên bản, cipher, chuỗi chứng chỉ, ngày hết hạn, SNI, ALPN — thứ mà lỗi trình duyệt "kết nối không an toàn" giấu đi. Khi HTTPS hỏng trên production, openssl s_client thường lộ nguyên nhân trong một lệnh.

Ba ý mang về

  1. TLS bắt tay trước khi HTTP chạy để lập kênh bí mật + toàn vẹn + xác thực: đo thật luồng TLS 1.3 gồm ClientHello → ServerHello/Certificate/CertificateVerify/Finished → Finished, chỉ 1-RTT (TLS 1.2 cần 2-RTT), và mọi message sau ServerHello đã được mã hóa.
  2. openssl s_client cho xem tận mắt: -msg in từng handshake message, kết quả cho TLSv1.3 + cipher + Verify return code: 0 + ALPN; -tls1_2/-tls1_3 để so (tên cipher TLS 1.3 gọn hơn hẳn).
  3. Nhớ SNI và tắt giao thức cũ: -servername (SNI) bắt buộc với virtual hosting để nhận đúng chứng chỉ; chỉ bật TLS 1.2 + 1.3, kiểm hở bằng cách thử ép phiên bản cũ.

Nguồn

Phần sau ta soi kỹ thứ vừa xuất hiện trong bắt tay: chứng chỉ X.509 — cấu trúc, chuỗi tin cậy từ chứng chỉ lá tới CA gốc, SAN, và cách openssl x509 đọc chúng.