Mở rộng quy mô DNS không còn là nỗi lo
Hạ tầng DNS là xương sống thầm lặng của mạng máy tính. Nó vô hình cho đến khi một đợt lưu lượng tăng đột biến hoặc một cuộc tấn công DDoS cục bộ đẩy các trình phân giải đệ quy (recursive resolvers) của bạn lên mức 100% CPU. Tôi đã dành nhiều năm vật lộn với việc chuyển đổi dự phòng (failover) thủ công và khắc phục lỗi DNS trước khi đưa dnsdist vào môi trường thực tế. Nó không chỉ cân bằng lưu lượng; nó còn cung cấp cho tôi một lá chắn có thể lập trình được cho toàn bộ hệ thống DNS.
Hãy coi dnsdist như một proxy nhận diện giao thức. Không giống như bộ cân bằng tải Lớp 4 (Layer 4 load balancer) thông thường chỉ nhìn thấy IP và cổng, dnsdist kiểm tra chính tiêu đề (header) của DNS. Nó hiểu các loại truy vấn, tên miền và các cờ (flags). Điều này cho phép bạn định tuyến lưu lượng dựa trên nội dung thực tế của yêu cầu, một khả năng đã cứu hạ tầng của tôi trong một đợt tấn công 50.000 QPS (Truy vấn mỗi giây) – mức lưu lượng có thể đè bẹp một thiết lập BIND tiêu chuẩn.
Bắt đầu nhanh: Cài đặt và chạy trong 5 phút
Nếu bạn có các trình phân giải backend như Bind, PowerDNS hoặc Unbound, bạn có thể đặt dnsdist phía trước chúng để đóng vai trò điều phối lưu lượng. Dưới đây là cách chạy một phiên bản cơ bản trên Ubuntu 22.04 hoặc 24.04.
1. Cài đặt
Mặc dù các kho lưu trữ mặc định thường có sẵn dnsdist, tôi khuyên bạn nên sử dụng kho lưu trữ chính thức của PowerDNS để có các bản vá bảo mật mới nhất (như phiên bản 1.9.x). Để thử nghiệm nhanh trong lab, kho lưu trữ tiêu chuẩn là đủ:
sudo apt update
sudo apt install dnsdist -y
2. Cấu hình cơ bản
Cấu hình của bạn nằm ở /etc/dnsdist/dnsdist.conf. Chúng ta sẽ thiết lập một bộ cân bằng đơn giản lắng nghe trên cổng 53 và phân phối các truy vấn đến hai trình phân giải upstream bằng cú pháp dựa trên Lua.
-- Lắng nghe trên tất cả các giao diện
setLocal('0.0.0.0:53')
-- Định nghĩa các máy chủ backend với kiểm tra sức khỏe (health checks)
newServer({address="8.8.8.8", name="google-primary", checkName="google.com."})
newServer({address="1.1.1.1", name="cloudflare-secondary", checkName="google.com."})
-- Kích hoạt giao diện web để giám sát thời gian thực
setWebserverConfig("0.0.0.0:8083", "mat_khau_bao_mat_cua_ban")
3. Khởi chạy
Áp dụng các thay đổi bằng cách khởi động lại dịch vụ:
sudo systemctl restart dnsdist
sudo systemctl enable dnsdist
Kiểm tra thiết lập bằng lệnh dig @127.0.0.1 google.com. dnsdist giờ đây sẽ chuyển tiếp các truy vấn của bạn giữa hai upstream một cách liền mạch.
Phép màu thực sự: Xử lý lưu lượng thông minh
Sức mạnh thực sự của dnsdist đến từ việc kiểm tra gói tin sâu (deep packet inspection). Trong môi trường thực tế, tôi thường chia lưu lượng thành các “pool”. Bạn có thể định tuyến các tên miền nội bộ quan trọng đến một nhóm máy chủ ưu tiên cao, trong khi gửi các truy vấn internet thông thường đến một trình phân giải công cộng.
Các chính sách cân bằng tải thông minh
Chính sách mặc định leastOutstanding là một bước ngoặt. Thay vì luân phiên các máy chủ một cách mù quáng, dnsdist theo dõi số lượng truy vấn hiện đang được xử lý cho mỗi backend. Nếu một máy chủ chậm lại—có lẽ do một truy vấn đệ quy nặng—dnsdist sẽ phát hiện độ trễ và chuyển các truy vấn mới sang các nút nhanh hơn. Các tùy chọn khác bao gồm:
- firstAvailable: Tuyệt vời cho các kịch bản máy chủ chính/dự phòng khi quá tải.
- wrandom: Phân phối ngẫu nhiên có trọng số cho các máy chủ có cấu hình phần cứng khác nhau.
- roundrobin: Cách tiếp cận tuần tự cổ điển.
Console trực tiếp
Console tương tác là công cụ khắc phục sự cố yêu thích của tôi. Chạy dnsdist -c để vào môi trường Lua trực tiếp. Bạn có thể xem các tên miền được truy vấn nhiều nhất hoặc chặn một IP lạm dụng trong thời gian thực mà không cần chạm vào tệp cấu hình. Đó là sự khác biệt giữa việc vận hành mù quáng và việc có một radar hành trình đầy đủ cho lưu lượng DNS của bạn.
Xây dựng tường lửa DNS
Vì dnsdist nằm ở biên (edge), đây là nơi hoàn hảo để loại bỏ lưu lượng độc hại. Việc lọc ở đây tiết kiệm chu kỳ CPU hơn đáng kể so với việc để những truy vấn đó tác động đến các công cụ phân giải đệ quy nặng nề của bạn.
1. Giới hạn tốc độ theo từng IP
Để ngăn chặn một máy khách duy nhất độc chiếm tài nguyên, bạn có thể điều tiết chúng. Quy tắc này giới hạn mỗi IP duy nhất chỉ được thực hiện 10 truy vấn mỗi giây. Bất cứ điều gì vượt quá mức đó sẽ bị loại bỏ ngay lập tức.
-- Ngắt lưu lượng từ các IP vượt quá 10 QPS
addAction(MaxQPSIPRule(10), DropAction())
2. Loại bỏ các truy vấn ‘ANY’
Kẻ tấn công thường sử dụng các truy vấn ANY để khuếch đại các cuộc tấn công DDoS. Vì rất ít ứng dụng hợp lệ thực sự cần phản hồi ANY, bạn có thể chặn chúng chỉ bằng một dòng lệnh:
-- Chặn tất cả các truy vấn loại ANY để ngăn chặn tấn công khuếch đại
addAction(QTypeRule(DNSQType.ANY), DropAction())
3. Chặn tên miền độc hại tức thì
Nếu bạn xác định được một tên miền lừa đảo (phishing) hoặc C2 của botnet, bạn có thể chặn nó ngay tại cửa ngõ. Tôi đã sử dụng cách này để bảo vệ hơn 500 người dùng bằng cách chặn các tên miền độc hại đã biết trước khi chúng kịp phân giải.
-- Ngắt các yêu cầu đối với một tên miền độc hại cụ thể
addAction("malware-callback.com", DropAction())
Mẹo ổn định khi triển khai thực tế
Chạy dnsdist ở quy mô lớn đòi hỏi một vài bước bổ sung để đảm bảo độ tin cậy. Đây là những gì tôi đã học được từ việc quản lý các cụm máy chủ lưu lượng cao.
Kiểm tra sức khỏe mạnh mẽ
Đừng chỉ kiểm tra xem máy chủ có “đang chạy” hay không. Hãy sử dụng checkName để đảm bảo máy chủ thực sự trả về các bản ghi DNS hợp lệ. Nếu một backend bắt đầu trả về lỗi SERVFAIL, dnsdist sẽ tự động loại nó khỏi danh sách luân chuyển trong vòng vài giây.
Kích hoạt Packet Cache
Packet cache cực kỳ hiệu quả. Bằng cách phục vụ các truy vấn lặp lại từ bộ nhớ, bạn có thể giảm tải cho backend từ 40% trở lên. Trong các thử nghiệm của tôi, các phản hồi được lưu trong cache trả về trong vòng chưa đầy 1ms, so với 20-50ms cho một truy vấn đệ quy.
-- Lưu trữ cache cho 10.000 phản hồi duy nhất
pc = newPacketCache(10000)
getPool(""):setCache(pc)
Bảng điều khiển (Dashboard)
Bảng điều khiển web tích hợp cung cấp cái nhìn trực quan về tỷ lệ khớp cache (cache hit rates) và phân bổ độ trễ. Nó rất quan trọng để phát hiện các bất thường. Chỉ cần đảm bảo bạn giới hạn quyền truy cập vào IP VPN quản trị của mình để ngăn chặn truy cập trái phép.
Triển khai dnsdist biến dịch vụ DNS của bạn từ một dịch vụ tĩnh thành một cửa ngõ có khả năng phục hồi và lập trình được. Nó nhẹ, xử lý hàng triệu truy vấn trên phần cứng khiêm tốn và cung cấp khả năng kiểm soát chi tiết cần thiết để tồn tại trước sự khó lường của web hiện đại.

