[Architecture] API Gateway & TLS: Đừng rớt đài vì bảo mật "nửa mùa" trong mạng nội bộ
Lời mở đầu: Ảo tưởng về chiếc "Ổ khóa xanh" Anh em làm Backend chắc không lạ gì quy trình chuẩn: Mua domain, cài chứng chỉ SSL/TLS (Let's Encrypt cho tiết kiệm), trỏ vào API Gateway/Load Balancer. Thế là app của chúng ta có HTTPS, dữ liệu từ App/Web của người dùng gửi lên server được mã hóa an toàn.
Sếp vỗ tay, khách hàng yên tâm.
Nhưng hãy nhìn sâu vào hệ thống. Sau khi API Gateway nhận request (đã giải mã HTTPS thành HTTP), nó làm gì tiếp theo? Nó forward cái request đó đến các Microservices (Backend) nằm sâu bên trong. Và ở 90% các dự án mình từng review, luồng giao tiếp từ Gateway -> Backend này lại chạy bằng HTTP plaintext (không mã hóa).
Tư duy "Mạng nội bộ (VPC) nhà mình đóng kín rồi, an toàn lắm, không cần mã hóa" là tư duy của thập kỷ trước. Trong thời đại Zero Trust Architecture, không tin bất kỳ ai, kể cả các node nằm chung một mạng.
Hôm nay, chúng ta sẽ mổ xẻ cách thiết lập TLS cho Data in Transit ở luồng backend, dựa trên kiến trúc chuẩn của API Gateway.
1. Bức tranh toàn cảnh: Khi Gateway đóng vai trò "Client"
Hãy nhìn vào sơ đồ kiến trúc bên dưới (dựa trên tài liệu chuẩn của API Gateway):

Chúng ta thường chỉ rành đoạn bên trái. Nhưng hôm nay, ta nói về đoạn bên phải.
Khi API Gateway kết nối với Backend qua TLS, nó chuyển vai trò trở thành một TLS Client. Lúc này, Gateway sẽ:
- Chủ động khởi tạo một kết nối bảo mật (Handshake).
- Yêu cầu Backend trình ra chứng chỉ (Server Certificate).
- Xác minh (Verify) xem chứng chỉ đó có hợp lệ không, có do một CA (Certificate Authority) uy tín cấp không.
Chỉ khi bước xác minh thành công, một kênh mã hóa (encrypted channel) mới được thiết lập. Điều này đảm bảo dữ liệu (như thông tin thẻ tín dụng, mật khẩu) dù đang bay trong mạng LAN nội bộ cũng không bị ai nghe lén.
2. 3 Điểm nghẽn sinh tử khi setup TLS cho Backend
Dựng HTTPS cho public domain thì dễ, nhưng dựng TLS cho giao tiếp nội bộ thì nhiều khê hơn bạn tưởng. Theo cẩm nang kiến trúc, bạn phải handle 3 vấn đề cốt lõi sau:
A. Quản lý Trust Stores (Kho lưu trữ niềm tin) Khi Backend trình chứng chỉ ra, làm sao Gateway biết chứng chỉ đó là "hàng auth" hay "hàng pha-ke"? Nó phải tra cứu trong Trust Store.
- Nếu Backend dùng chứng chỉ Public (như Let's Encrypt), Trust Store mặc định của hệ điều hành trên Gateway thường đã tự nhận diện được.
- Thực tế Enterprise: Các công ty lớn không xài Public Cert cho service nội bộ (vì tốn kém và giới hạn rate limit). Họ tự dựng một Internal CA (Private PKI) để cấp chứng chỉ cho các microservices. Lúc này, bạn PHẢI import cái Root CA nội bộ đó vào Trust Store của API Gateway. Nếu quên bước này, Gateway sẽ báo lỗi
x509: certificate signed by unknown authorityngay lập tức.
B. Xử lý Certificate Revocation và Renewal (Gia hạn và Thu hồi) Chứng chỉ TLS luôn có hạn sử dụng (ví dụ 90 ngày hoặc 1 năm).
- Renewal: Bạn phải có cơ chế auto-renew (như certbot) cho hàng chục cái backend. Nếu 1 cái backend hết hạn cert, Gateway sẽ từ chối kết nối, kéo theo Service Outage.
- Revocation: Nếu private key của backend bị lộ, bạn phải "thu hồi" chứng chỉ đó ngay. Gateway cần được cấu hình để check CRL (Certificate Revocation List) hoặc OCSP để biết chứng chỉ nào đã bị tước quyền.
C. Vũ khí tối thượng: Mutual TLS (mTLS) TLS thông thường chỉ là bảo mật một chiều: Client (Gateway) xác minh Server (Backend). Nhưng nhỡ có một con mã độc nằm trong mạng nội bộ cố tình gọi API đến Backend của bạn thì sao?
Lúc này ta cần mTLS (Xác thực hai chiều). Trong mTLS, không chỉ Backend phải trình chứng chỉ, mà bản thân API Gateway cũng phải trình ra một "Client Certificate" cho Backend xem. Backend check thấy: "À, đúng là chứng chỉ của anh Gateway nhà mình rồi, em mới cho gọi API". Nó block hoàn toàn mọi luồng truy cập trái phép trực tiếp vào Backend.
3. Cấu hình Thực chiến: TLS to a Backend with Public Certificate
Lý thuyết nhiều rồi, giờ xem code. Nếu Backend của bạn đang host ở một dịch vụ bên thứ 3 hoặc được bọc bởi một Public Certificate (được cấp bởi CA uy tín), việc cấu hình trên API Gateway cực kỳ đơn giản.
Như trong tài liệu mô tả, giả sử bạn đang dùng một Gateway định tuyến bằng cấu trúc XML (như các hệ thống Enterprise cũ hoặc WSO2), bạn chỉ cần đổi target URL sang https://:
<api port="2000">
<target url="https://api.predic8.de"/>
</api>
Heavyweight Tip cho anh em dùng Nginx / Kong Gateway: Nếu hệ thống của bạn dùng Nginx làm API Gateway, cấu hình tương đương sẽ như thế này:
location /api/ {
# Định tuyến sang backend dùng HTTPS
proxy_pass https://backend_service:443;
# Bắt buộc Nginx (Gateway) phải xác minh chứng chỉ của Backend
proxy_ssl_verify on;
# Trỏ đến file Trust Store chứa Root CA
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
# Đảm bảo tên miền khớp với tên trong chứng chỉ của Backend
proxy_ssl_server_name on;
}
Tóm lại
"Zero Trust" không phải là một buzzword (từ khóa chém gió) để lòe sếp. Nó bắt đầu từ những việc cấu hình rất nhỏ như thiết lập TLS cho mọi kết nối phía sau API Gateway.
Dù tốn thêm chút CPU để mã hóa/giải mã (TLS Termination overhead), nhưng đổi lại, bạn có một giấc ngủ ngon mà không lo một ngày đẹp trời dữ liệu nội bộ bị phơi bày trên dark web.
Anh em trong dự án hiện tại đang dùng HTTP chay hay đã ốp mTLS cho các microservices rồi? Comment chia sẻ nỗi đau setup chứng chỉ nội bộ nhé!
All rights reserved