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

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:

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ừ sauServerHello, 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, cipherTLS_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ệ.CertificateVerifylà 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.1cho client và server chọn giao thức ứng dụng. Host này chọnhttp/1.1. - TLS 1.3 vs 1.2: cùng server, ép
-tls1_3cho cipherTLS_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_2choECDHE-ECDSA-AES256-GCM-SHA384(tên dài, mô tả cả cách trao khóaECDHEvà 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ề
- 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. openssl s_clientcho xem tận mắt:-msgin từng handshake message, kết quả choTLSv1.3+ cipher +Verify return code: 0+ ALPN;-tls1_2/-tls1_3để so (tên cipher TLS 1.3 gọn hơn hẳn).- 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
- MDN — TLS và A typical TLS 1.3 handshake: https://developer.mozilla.org/en-US/docs/Web/Security/Transport_Layer_Security
- RFC 8446 (TLS 1.3): https://www.rfc-editor.org/rfc/rfc8446
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.