Vấn đề của việc chặn IP thủ công và sức mạnh của IP Sets
Lúc mới quản trị hệ thống Web lớn, mình từng rơi vào cảnh server bị tấn công brute-force từ hàng nghìn IP. Hồi đó, mình cứ cắm cúi gõ firewall-cmd --add-rich-rule để chặn từng địa chỉ một. Kết quả là bảng rule dài dằng dặc. Mỗi lần reload firewall, CPU server vọt lên 100%, khiến request của người dùng thật bị nghẽn nghiêm trọng.
Sau sự cố đó, mình rút ra kinh nghiệm: Đừng bao giờ quản lý hàng trăm IP bằng các rule đơn lẻ. Đó là lúc IP Sets trở thành giải pháp tối ưu. Công cụ này cho phép bạn gom hàng nghìn IP hoặc dải mạng (subnet) vào một danh sách duy nhất. Thay vì duyệt qua 1.000 rule để kiểm tra một gói tin, firewall chỉ cần kiểm tra một lần nhờ cấu trúc Hash Table. Tốc độ xử lý lúc này là O(1), gần như tức thì.
Dù CentOS Stream 9 đã chuyển sang dùng nftables làm backend, Firewalld IP Sets vẫn cực kỳ mạnh mẽ. Nếu bạn muốn chặn triệt để traffic từ các quốc gia thường xuyên tấn công, đây là kỹ thuật bạn không thể bỏ qua.
Cài đặt và chuẩn bị môi trường
CentOS Stream 9 thường cài sẵn Firewalld, nhưng chúng ta cần đảm bảo dịch vụ đang chạy ổn định. Hãy cài thêm package ipset để hỗ trợ các thao tác kiểm tra nhanh.
# Cập nhật hệ thống nhanh
sudo dnf update -y
# Cài đặt công cụ cần thiết
sudo dnf install firewalld ipset -y
# Kích hoạt firewalld
sudo systemctl enable --now firewalld
# Kiểm tra trạng thái hoạt động
sudo firewall-cmd --state
Khi migrate hệ thống từ CentOS 7 sang bản 9, mình nhận thấy cấu trúc lệnh không đổi nhiều. Tuy nhiên, hiệu suất xử lý IP Sets trên bản 9 mượt hơn hẳn nhờ sự tối ưu của nftables bên dưới.
Cấu hình chi tiết IP Sets trên Firewalld
Bước 1: Tạo một IP Set mới
Trước tiên, hãy tạo một cái “giỏ” để chứa danh sách đen. Mình đặt tên là blacklist_ips. Loại IP Set phổ biến nhất là hash:net, hỗ trợ cả IP đơn lẻ lẫn dải mạng CIDR.
sudo firewall-cmd --permanent --new-ipset=blacklist_ips --type=hash:net
Thông tin các tham số:
--permanent: Lưu cấu hình vĩnh viễn qua các lần reboot.--new-ipset: Đặt tên cho danh sách.--type=hash:net: Kiểu dữ liệu để lưu các dải mạng (ví dụ: 192.168.1.0/24).
Bước 2: Nạp IP vào danh sách
Bạn có thể thêm thủ công các IP nghi vấn hoặc dải mạng thường xuyên spam vào set vừa tạo.
# Chặn một IP cụ thể
sudo firewall-cmd --permanent --ipset=blacklist_ips --add-entry=1.2.3.4
# Chặn nguyên một dải mạng
sudo firewall-cmd --permanent --ipset=blacklist_ips --add-entry=192.168.100.0/24
Nếu danh sách lên tới hàng trăm IP, đừng gõ tay. Hãy lưu chúng vào file list.txt (mỗi dòng một IP) và dùng vòng lặp bash để import:
for ip in $(cat list.txt); do
sudo firewall-cmd --permanent --ipset=blacklist_ips --add-entry=$ip
done
Bước 3: Kích hoạt luật chặn
Tạo danh sách xong, firewall vẫn chưa làm gì cả. Bạn cần thêm một “rich rule” để ra lệnh cho Firewalld: “Hễ thấy IP nào trong blacklist_ips thì DROP ngay lập tức”.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source ipset="blacklist_ips" drop'
Cuối cùng, reload lại để mọi thay đổi có hiệu lực:
sudo firewall-cmd --reload
Cách Blacklist toàn bộ IP của một quốc gia
Đây là chiêu thức cực kỳ hiệu quả. Giả sử server của bạn chỉ phục vụ người dùng Việt Nam. Việc chặn traffic từ các quốc gia không liên quan sẽ giảm tới 80-90% nguy cơ bị scan lỗi tự động.
Sử dụng dữ liệu từ IPDeny, bạn có thể tự động hóa việc này bằng script:
# Tạo IP Set cho quốc gia cụ thể (ví dụ: Trung Quốc - mã 'cn')
sudo firewall-cmd --permanent --new-ipset=country_block --type=hash:net
# Tải danh sách dải IP mới nhất
curl -O http://www.ipdeny.com/ipblocks/data/countries/cn.zone
# Import hàng nghìn dải mạng vào Set
for range in $(cat cn.zone); do
sudo firewall-cmd --permanent --ipset=country_block --add-entry=$range
done
# Áp dụng luật DROP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source ipset="country_block" drop'
sudo firewall-cmd --reload
Lưu ý: Quá trình import 5.000 – 8.000 dải mạng có thể mất 1-2 phút. Tuy nhiên, khi đã nạp xong, việc lọc gói tin sẽ không hề gây lag cho server.
Kiểm tra và Giám sát
Để chắc chắn hệ thống đang chạy đúng, bạn hãy sử dụng các lệnh kiểm tra sau:
1. Liệt kê các IP Set hiện có:
sudo firewall-cmd --get-ipsets
2. Xem danh sách IP bên trong một Set:
sudo firewall-cmd --ipset=blacklist_ips --get-entries
3. Kiểm tra nhanh một IP có bị chặn hay không:
ipset test blacklist_ips 1.2.3.4
Mẹo quản lý chuyên nghiệp
- Dùng Drop thay vì Reject: Khi chặn diện rộng, hãy dùng
dropđể im lặng ngắt kết nối.rejectsẽ gửi phản hồi về cho attacker, gây tốn băng thông vô ích. - Sao lưu cấu hình: Toàn bộ IP Set được lưu dưới dạng file XML tại
/etc/firewalld/ipsets/. Bạn chỉ cần copy file này sang server mới là xong. - Tự động cập nhật: Dải IP quốc gia luôn thay đổi. Bạn nên thiết lập Cronjob hàng tuần để tải lại file zone và cập nhật danh sách tự động.
Làm chủ IP Sets giúp mình tự tin hơn hẳn khi đối mặt với các đợt tấn công từ internet. Chỉ với vài dòng lệnh, bạn đã thiết lập được một “tấm khiên” vững chắc cho server CentOS Stream 9 của mình mà không lo hy sinh hiệu suất.

