Sự cố lúc 2 giờ sáng: Khi các truy vấn hợp lệ trả về kết quả sai
Vào lúc 2:15 sáng thứ Ba, hệ thống cảnh báo on-call của chúng tôi đồng loạt reo chuông. Giám sát ghi nhận lỗi sai lệch chứng chỉ SSL bất thường trên ba subdomain thanh toán. Lưu lượng truy cập hợp lệ từ khách hàng đang bị trỏ về một địa chỉ IP lạ (203.0.113.84) đặt tại khu vực khác. Trong khi đó, các web server của chúng tôi vẫn hoạt động bình thường, quy tắc tường lửa không đổi và log xác thực không ghi nhận bất kỳ phiên đăng nhập SSH trái phép nào.
Một lệnh kiểm tra nhanh từ bên ngoài đã ngay lập tức vạch trần vấn đề:
dig @8.8.8.8 api.example.com +short
Truy vấn trả về 203.0.113.84 thay vì IP của edge proxy thực tế là 198.51.100.25. Bộ nhớ cache của các public recursive resolver đã bị đầu độc (cache poisoned). DNS truyền thống hoạt động qua cổng UDP 53 mà không hề có cơ chế xác thực.
Do các truy vấn thông thường dựa vào transaction ID 16-bit rất dễ đoán, kẻ tấn công có thể gửi ồ ạt các gói tin phản hồi giả mạo tới resolver. Nếu một gói tin giả mạo đến trước câu trả lời từ authoritative server, resolver sẽ lưu nó vào bộ nhớ đệm. Suốt 3.600 giây tiếp theo, mọi người dùng sử dụng resolver đó đều bị chuyển hướng sang máy chủ do kẻ tấn công kiểm soát. Giải pháp triệt để duy nhất cho vấn đề này là DNSSEC (Domain Name System Security Extensions).
Các khái niệm cốt lõi: Cách chữ ký mã hóa bảo vệ DNS
DNS tiêu chuẩn vận hành dựa trên sự tin tưởng tuyệt đối. Resolver gửi truy vấn, tiếp nhận phản hồi và mặc định rằng các gói tin không bị can thiệp trên đường truyền. DNSSEC chuyển đổi mô hình bảo mật từ tầng truyền tải mạng sang cơ chế xác thực mật mã. Authoritative server sẽ tạo chữ ký số cho từng tập bản ghi (record set), còn validating resolver sẽ xác minh các chữ ký đó qua một chuỗi tin cậy công khai (public chain of trust).
Các thành phần kiến trúc chính
- Zone Signing Key (ZSK): Dùng để ký các bản ghi tài nguyên thông thường (A, AAAA, MX). Quản trị viên zone thường xuyên xoay vòng (rotate) khóa này, phổ biến là từ 30 đến 90 ngày một lần.
- Key Signing Key (KSK): Chỉ ký riêng tập bản ghi DNSKEY. KSK hiếm khi được thay đổi (thường từ 1 đến 2 năm một lần) vì mỗi lần cập nhật đều đòi hỏi phải cấu hình lại tại registrar của zone cha.
- RRSIG (Resource Record Signature): Chữ ký gắn liền với mỗi tập bản ghi. Bản ghi này chứa mốc thời gian hiệu lực rõ ràng (thường từ 14 đến 30 ngày) nhằm ngăn chặn các cuộc tấn công phát lại (replay attacks).
- DNSKEY: Chứa các public key được công bố trong zone. Resolver sẽ truy xuất bản ghi này để xác thực các bản ghi RRSIG. Cờ (flag) 256 đại diện cho ZSK, trong khi cờ 257 đánh dấu KSK.
- DS (Delegation Signer): Mã băm SHA-256 fingerprint của KSK, được lưu trữ tại zone cha (ví dụ:
.com). Đây là cầu nối mật mã giữa registrar và nameserver. - NSEC / NSEC3: Bằng chứng mật mã chứng minh một bản ghi không hề tồn tại. NSEC3 băm tên miền kèm theo salt và qua nhiều vòng lặp để ngăn kẻ tấn công thu thập toàn bộ dữ liệu file zone thông qua kỹ thuật zone walking.
Thực hành: Ký một Zone trong BIND9
Các bước thiết lập dưới đây được thực hiện trên hệ điều hành Debian 12 / Ubuntu 22.04 LTS chạy BIND 9.18+. Nameserver này đã được cấu hình sẵn một authoritative zone cho tên miền example.com.
Bước 1: Bật các chỉ thị DNSSEC trong BIND
Mở file cấu hình chính của BIND:
sudo nano /etc/bind/named.conf.options
Đảm bảo các tùy chọn sau đã được khai báo bên trong khối options { ... };:
options {
directory "/var/cache/bind";
dnssec-validation auto;
auth-nxdomain no;
listen-on-v6 { any; };
};
Kiểm tra cú pháp của file cấu hình:
sudo named-checkconf
Nếu lệnh không trả về bất kỳ thông báo nào, cú pháp của bạn hoàn toàn hợp lệ.
Bước 2: Tạo khóa ZSK và KSK
Lưu trữ các khóa mã hóa trong một thư mục riêng biệt với quyền truy cập được giới hạn:
sudo mkdir -p /etc/bind/keys
cd /etc/bind/keys
sudo chown -R bind:bind /etc/bind/keys
sudo chmod 750 /etc/bind/keys
Trước khi triển khai hạ tầng mật mã, hãy rà soát lại thông tin xác thực quản trị của bạn. Nếu cần mật khẩu mạnh cho các bảng điều khiển quản trị hoặc tài khoản triển khai mới, hãy tạo chúng cục bộ. Tiện ích ngoại tuyến tại toolcraft.app/vi/tools/security/password-generator tạo các chuỗi có độ hỗn loạn (entropy) cao ngay trong trình duyệt mà không gửi bất kỳ dữ liệu nào qua mạng.
Tạo Zone Signing Key (ZSK) sử dụng Thuật toán 13 (ECDSA P-256 với SHA-256):
sudo dnssec-keygen -a ECDSAP256SHA256 -n ZONE example.com
Thuật toán 13 chỉ tạo ra chữ ký có kích thước 64 byte. Để so sánh, RSA 2048-bit tạo ra chữ ký tới 256 byte. Kích thước chữ ký nhỏ gọn giúp dung lượng phản hồi luôn nằm dưới giới hạn bộ đệm EDNS0 tiêu chuẩn (1.232 byte), tránh tình trạng phân mảnh gói tin UDP.
Tiếp theo, tạo Key Signing Key (KSK) với cờ -f KSK:
sudo dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE example.com
Lệnh này sẽ tạo ra bốn file: hai file đuôi .key chứa public key và hai file đuôi .private chứa dữ liệu khóa bí mật dùng để ký.
Bước 3: Cấu hình tự động ký với Inline Signing
Việc ký lại thủ công bằng lệnh dnssec-signzone rất dễ gián đoạn mỗi khi bản ghi có thay đổi. Thay vào đó, hãy để BIND tự động quản lý quá trình ký bằng tính năng inline-signing. Cập nhật định nghĩa zone trong /etc/bind/named.conf.local:
zone "example.com" {
type master;
file "/var/lib/bind/db.example.com";
key-directory "/etc/bind/keys";
auto-dnssec maintain;
inline-signing yes;
};
Sao chép file zone vào /var/lib/bind/. Tiến trình BIND cần quyền ghi tại đây để tự động tạo các file zone đã ký .signed và các file nhật ký hoạt động (journal):
sudo cp /etc/bind/db.example.com /var/lib/bind/db.example.com
sudo chown -R bind:bind /var/lib/bind
sudo rndc reload
BIND sẽ ngay lập tức tạo file db.example.com.signed chạy ngầm mà không làm thay đổi file zone gốc của bạn.
Bước 4: Trích xuất bản ghi DS cho Registrar
Hiện tại máy chủ của bạn đã ký các bản ghi ở mức cục bộ. Tuy nhiên, các public resolver sẽ không bắt buộc xác thực DNSSEC cho tới khi zone cha của registrar ủy quyền chính thức. Xác định KSK bằng cách tìm file key nào có chứa cờ 257:
grep "257" /etc/bind/keys/Kexample.com.*.key
Tạo bản ghi Delegation Signer (DS) từ file KSK tương ứng đó:
cd /etc/bind/keys
sudo dnssec-dsfromkey Kexample.com.+013+02371.key
Lệnh sẽ in ra kết quả theo định dạng chuẩn để nhập vào registrar:
example.com. IN DS 2371 13 2 4B79A63D78E0E84F99881829D64A12B268B96464019AA1D389920DF120489AB1
Truy cập vào trang quản trị DNSSEC của nhà đăng ký tên miền (registrar) và điền bốn trường thông tin:
- Key Tag:
2371 - Algorithm:
13(ECDSA Curve P-256 with SHA-256) - Digest Type:
2(SHA-256) - Digest:
4B79A63D78E0E84F99881829D64A12B268B96464019AA1D389920DF120489AB1
Bước 5: Xác minh chuỗi tin cậy
Thay đổi tại registrar thường mất từ 15 đến 60 phút để lan truyền tới các root server. Trước tiên, hãy kiểm tra quá trình tạo chữ ký ngay trên localhost:
dig @localhost example.com A +dnssec +multiline
Bạn sẽ thấy bản ghi RRSIG xuất hiện ngay bên dưới bản ghi A. Tiếp theo, hãy kiểm tra quá trình xác thực đầu cuối thông qua DNS resolver 1.1.1.1 của Cloudflare bằng công cụ delv (DNS Lookup and Validation):
delv @1.1.1.1 example.com A
Khi ủy quyền tại zone cha và các khóa cục bộ khớp hoàn toàn với nhau, delv sẽ hiển thị:
; fully validated
example.com. 300 IN A 198.51.100.25
example.com. 300 IN RRSIG A 13 2 300 ...
Nếu gặp lỗi validation failure, hãy kiểm tra lại giá trị DS digest tại registrar trước khi đào sâu vào log nội bộ của BIND.
Tổng kết vận hành
Nếu không có DNSSEC, tường lửa biên và chứng chỉ TLS không thể ngăn chặn việc upstream resolver lưu vào bộ nhớ cache các IP giả mạo. Việc triển khai khóa ECDSA Thuật toán 13 cùng tính năng inline signing của BIND9 sẽ giải quyết triệt để rủi ro này: chữ ký luôn được làm mới tự động, kích thước gói tin nhỏ gọn và phía client có thể xác minh dữ liệu xuyên suốt từ các root server đến tận từng bản ghi host của bạn.

