Mười một phần trước mỗi phần đo một lát cắt của bảo mật kết nối, và điểm chung của cả sê-ri không phải là một kết luận mà là một thói quen: đo trước khi tin. Mọi con số dưới đây đến từ việc chạy mã thật trên cùng một cặp máy ảo aarch64, không trích từ tài liệu hay blog nào. Phần cuối này gom chúng thành một checklist để dùng khi dựng một dịch vụ mới, sắp theo ba nhóm quyết định: cấu hình TLS nên đặt gì, danh tính và vòng đời chứng chỉ xử lý ra sao, và những lớp phòng thủ vận hành quanh secret, mật khẩu, token, timeout. Mỗi mục đi với con số đã đo để bạn biết vì sao, và để đối chiếu khi đo lại trên máy của mình.
Checklist theo ba nhóm quyết định

Hình 1: Checklist bảo mật kết nối chia ba nhóm, mỗi mục kèm con số đo thật từ các phần tương ứng.
Cấu hình TLS tối thiểu, từ phần 1, 3 và 4. Dùng TLS 1.3 với chứng chỉ ECDSA P-256: chuỗi server gửi 860 byte so với 1.908 byte của RSA, bắt tay 0,54 so với 1,34 ms, và chữ ký ECDSA rẻ hơn RSA bốn lần ở phía server. Để Go tự chọn cipher suite thay vì cố định: AES-GCM đạt 4.523 MB/s khi CPU có lệnh phần cứng và chỉ 168 MB/s khi không, chênh 26 lần, và Go tự thương lượng ChaCha20 cho client không có lệnh AES. Giữ key exchange mặc định X25519 và P-256 ở quanh 200 µs; P-521 đắt gấp 4,6 lần mà không mua được an toàn tương xứng, còn Kyber mặc định tốn thêm 70 µs nhưng không thêm vòng đi về. Hai điều nên tránh: đừng cố định CipherSuites cho TLS 1.2 mà bỏ ChaCha20, vì client không có lệnh AES sẽ kẹt với AES chậm; và đừng dùng RSA key exchange, vì nó không có forward secrecy và Go đã tắt mặc định.
mTLS và xoay chứng chỉ, từ phần 5 và 7. Bật mTLS khi các dịch vụ cần xác thực lẫn nhau: nó chỉ thêm 100 µs cho server và 533 byte cho mỗi bắt tay, rẻ, và nên chọn chứng chỉ ECDSA cho client vì RSA đẩy chi phí ký sang client thêm 770 µs. Xoay chứng chỉ server và CA bằng GetCertificate cùng GetConfigForClient: đo được 2.000 kết nối đang mở không rơi cái nào, và nên gia hạn khi chứng chỉ còn một phần ba vòng đời để có ngân sách cho job gia hạn hỏng rồi thử lại. Lùi NotBefore ít nhất một giờ: client lệch đồng hồ 30 giây mất 80% thời gian nếu chứng chỉ không lùi, và 0% nếu lùi. Một bẫy cần nhớ: TLS 1.3 báo lỗi chứng chỉ client ở lần Read đầu tiên chứ không ở Handshake, nên health check phải gửi một byte và đọc lại mới phát hiện được chứng chỉ client sai.
Secret, mật khẩu, token, timeout, từ phần 8, 9, 10 và 11. Với secret, dùng kiểu Redacted cho log, không truyền qua tham số dòng lệnh, và đặt ulimit -c 0 vì một core dump 118 MB giữ mọi secret tiến trình từng cầm; nhớ rằng biến môi trường lộ qua docker inspect bất kể ứng dụng làm gì. Với mật khẩu, ngưỡng 250 ms một lần băm là bcrypt cost 12 hoặc Argon2id t=3 m=128 MB; ở ngưỡng đó, kẻ tấn công với 10 lõi chỉ thử được 9 đến 29 lần mỗi giây, so với 70 triệu lần của sha256. Với JWT, ghim thuật toán bằng WithValidMethods để chặn cả alg=none lẫn nhầm loại khoá, và nhớ verify HS256 nhanh 313.000 lần mỗi giây so với RS256 30.000, con số quyết định vì verify chạy mỗi request. Với timeout, luôn đặt ReadHeaderTimeout và IdleTimeout, vì slowloris chỉ cần 6,4 Kbit mỗi giây để hạ một server để trống các trường này.
Một con số chủ đạo mỗi phần

Hình 2: Một con số chủ đạo của mỗi phần, nhóm theo chi phí TLS, danh tính, và phòng thủ vận hành.
Nhìn lại cả sê-ri qua một con số mỗi phần, ba chủ đề nổi lên. Chi phí TLS phần lớn nằm ở bất đối xứng và một lần mỗi kết nối. Bắt tay TLS 1.3 là một vòng đi về với ClientHello 1.474 byte vì Kyber bật mặc định trong Go 1.23; mười nghìn kết nối tốn thêm 24,5 KB mỗi kết nối chủ yếu ngoài heap; một lõi làm 4.350 bắt tay ECDSA mỗi giây nhưng chỉ 1.060 với RSA, chênh 4,1 lần; và sau bắt tay, mã hoá dữ liệu bằng AES-GCM gần như miễn phí khi CPU có lệnh phần cứng, 4.523 MB/s, nhưng chậm 26 lần khi không. Đặt TLS trong ứng dụng với keep-alive gần như không tốn gì; mỗi hop proxy thêm 110 µs và một vòng đi về nếu ở máy khác.
Danh tính là nơi vận hành khó hơn mật mã. mTLS về CPU rất rẻ, 100 µs mỗi bắt tay, nhưng phải quản vòng đời chứng chỉ cho mọi client; xoay được 2.000 kết nối mở không rơi cái nào nhờ hai callback của Go, với điều kiện lùi NotBefore để client lệch giờ không bị từ chối. Chứng chỉ hết hạn không giết kết nối đang mở, chúng sống 68 giây sau hạn trong phép đo, mà chặn kết nối mới đúng bằng số giây gia hạn trễ. Mật khẩu và token thì đã có thư viện làm đúng: bcrypt 12 hay Argon2id ép kẻ tấn công xuống vài chục lần thử mỗi giây, và golang-jwt v5 chặn cả hai lỗ hổng JWT kinh điển khi ta ghim thuật toán.
Phòng thủ vận hành rẻ nhưng dễ quên. Secret lộ không phải qua mật mã yếu mà qua log %+v, core dump, biến môi trường trong docker inspect, những chỗ mà một kiểu Redacted và ulimit -c 0 chặn được bằng vài dòng. Và một server Go không đặt timeout bị một client gửi 6,4 Kbit mỗi giây làm tê liệt, một lỗ hổng không cần mật mã nào để khai thác và chỉ cần một dòng ReadHeaderTimeout để vá. Số tuyệt đối trong cả sê-ri đo trên một vCPU aarch64 ảo hoá dùng chung, nên sẽ khác trên máy của bạn; cái mang đi được là tỉ lệ, ECDSA rẻ hơn RSA bốn lần, AES-GCM phụ thuộc lệnh CPU, hàm băm chậm nghẽn băng thông RAM, và quan trọng hơn tất cả, thói quen đo trước khi tin.
Đọc tiếp cả sê-ri
Mười hai phần theo thứ tự, mỗi phần một phép đo độc lập và dùng lại được:
- Bắt tay TLS 1.3 đọc từng byte, 1-RTT, session ticket và 0-RTT.
- Chi phí TLS trên 10.000 kết nối: RAM, CPU bắt tay, resumption.
- Chứng chỉ và chuỗi tin cậy: tự dựng CA rồi làm hỏng từng thứ.
- Key exchange và cipher suite: đường cong, chữ ký, AEAD theo CPU.
- mTLS: xác thực client, chi phí và xoay không downtime.
- TLS termination ở đâu: trong app, ở proxy, hay sidecar.
- Hết hạn chứng chỉ: phát hiện, cảnh báo, xoay tự động.
- Secret trong tiến trình: env, file, mount và những chỗ rò rỉ.
- Băm mật khẩu: bcrypt, scrypt, Argon2id với tham số đo thật.
- Token JWT: HS256, RS256, EdDSA và thu hồi.
- Timeout và slowloris: giữ server bằng kết nối chậm.
- Tổng kết: checklist này.
Ba ý mang về
- Mặc định của Go nghiêng về đúng, trừ timeout. TLS 1.3, Kyber, cipher tự chọn, RSA key exchange đã tắt, JWT v5 chặn lỗ hổng khi ghim thuật toán; nhưng
http.Server{}không có timeout nào, và đó là lỗ hổng vận hành phổ biến nhất của cả sê-ri. - Chọn ECDSA ở mọi nơi có thể. Chuỗi nhỏ hơn hai lần, bắt tay nhanh hơn bốn lần so với RSA, ở cả chứng chỉ server, chứng chỉ client, và khoá ký token; EdDSA còn tốt hơn cho JWT.
- Đo trên máy của mình, đọc theo tỉ lệ. Mọi con số ở đây là của một vCPU ảo hoá; dùng chúng để biết cái gì đắt tương đối với cái gì, rồi chạy lại trên phần cứng thật trước khi đặt tham số sản xuất.
Nguồn
- Go
crypto/tls— toàn bộ cấu hình dùng trong sê-ri: https://pkg.go.dev/crypto/tls - Go Security — mô hình bảo mật và các
GODEBUGliên quan: https://go.dev/security/ - Mozilla — Server Side TLS, cấu hình khuyến nghị theo mức tương thích: https://wiki.mozilla.org/Security/Server_Side_TLS
- OWASP — Transport Layer Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3: https://www.rfc-editor.org/rfc/rfc8446
- Cloudflare — A Detailed Look at RFC 8446 (a.k.a. TLS 1.3): https://blog.cloudflare.com/rfc-8446-aka-tls-1-3/