Hướng dẫn chi tiết về iptables recent module và các kịch bản cấu hình bảo mật

Tổng quan về module recent

Module recent của iptables cho phép hệ thống tạo và quản lý các danh sách địa chỉ IP động dựa trên các hoạt động mạng. Đây là công cụ hữu hiệu để kiểm soát tần suất kết nối, ngăn chặn các cuộc tấn công quét cổng (port scanning) hoặc từ chối dịch vụ (DoS). Module này hoạt động bằng cách ghi lại các địa chỉ IP thỏa mãn certain criteria và áp dụng các hành động giới hạn thời gian hoặc số lượng lần truy cập đối với chúng.

Các tham số cấu hình cơ bản

  • --name [tên_list]: Định danh cho danh sách theo dõi. Mặc định là "DEFAULT". Thông tin sẽ được lưu tại /proc/net/xt_recent/.
  • --rsource: Theo dõi địa chỉ IP nguồn (mặc định).
  • --rdest: Theo dõi địa chỉ IP đích.
  • --set: Thêm địa chỉ IP vào danh sách (hoặc cập nhật timestamp nếu đã tồn tại).
  • --rcheck: Kiểm tra xem địa chỉ IP có nằm trong danh sách hay không. Không làm mới thời gian.
  • --update: Tương tự --rcheck nhưng sẽ cập nhật thời gian truy cập cuối cùng (last seen) nếu IP tồn tại trong danh sách.
  • --seconds [thời_gian]: Chỉ định khoảng thời gian (giây) để so sánh. Phải dùng kèm với --rcheck hoặc --update.
  • --hitcount [số_lượng]: Quy định số lần truy cập tối đa cho phép. Phải dùng kèm với --rcheck hoặc --update.
  • --remove: Xóa địa chỉ IP ra khỏi danh sách theo dõi.

Một số lưu ý quan trọng

Các danh sách theo dõi của module recent được lưu trữ trong hệ thống file tại /proc/net/xt_recent/. Mỗi danh sách tương ứng với một file. Theo mặc định, module chỉ lưu trữ tối đa 100 entry cho mỗi danh sách (con số này có thể thay đổi khi tải module). Khi danh sách đầy, các entry cũ nhất sẽ bị loại bỏ để nhường chỗ cho entry mới.

Sự khác biệt chính giữa --rcheck--update nằm ở cách tính thời gian:

  • --rcheck: Tính thời gian từ gói tin đầu tiên được ghi nhận. Ví dụ, nếu quy tắc là 60 giây, đếm ngược bắt đầu khi gói tin đầu tiên xuất hiện.
  • --update: Tính thời gian từ gói tin gần nhất. Mỗi khi có gói tin khớp quy tắc, bộ đếm thời gian sẽ được reset về 0. Điều này có nghĩa là nếu kẻ tấn công liên tục gửi gói tin với tốc độ chậm hơn giới hạn, họ sẽ không bao giờ bị chặn.

Kịch bản 1: Ngăn chặn tấn công Brute Force vào SSH

Để bảo vệ dịch vụ SSH, chúng ta có thể giới hạn số lần kết nối mới từ một địa chỉ IP trong một khoảng thời gian nhất định.

# Giới hạn số lượng kết nối đồng thời từ 1 IP
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP

# Ghi log các IP cố gắng kết nối quá nhanh
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH_AUTH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH_AUTH -j LOG --log-prefix "SSH_BRUTE_FORCE: "

# Chặn các IP cố gắng kết nối quá 4 lần trong 60 giây
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH_AUTH -j DROP

Trong ví dụ trên, các quy tắc sẽ ghi nhận địa chỉ IP khi có yêu cầu kết nối mới. Nếu IP đó gửi quá 4 yêu cầu trong vòng 60 giây, nó sẽ bị chặn.

Kịch bản 2: Port Knocking qua ICMP (Ping)

Kỹ thuật "Port Knocking" cho phép ẩn cổng SSH và chỉ mở khi người dùng gửi một tín hiệu xác định trước. Ở đây, chúng ta sử dụng gói ICMP (ping) với kích thước cụ thể làm "chìa khóa".

# 1. Cho phép các kết nối đã được thiết lập
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# 2. Quy tắc mở cổng: Nếu nhận được gói ping có kích thước 100 byte (payload), thêm IP vào danh sách KNOCK_LIST
iptables -A INPUT -p icmp --icmp-type echo-request -m length --length 100 -m recent --set --name KNOCK_LIST --rsource -j ACCEPT

# 3. Cho phép SSH chỉ nếu IP nằm trong KNOCK_LIST và chưa quá 15 giây kể từ khi "gõ cửa"
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 15 --name KNOCK_LIST --rsource -j ACCEPT

# 4. Mặc định chặn các kết nối khác (tùy chọn, tùy vào chính sách mặc định của bạn)
iptables -P INPUT DROP

Để kết nối SSH từ máy khách, trước tiên bạn cần thực hiện lệnh ping với kích thước gói tin cụ thể:

# Trên Linux: ping -s 92 [IP_Server] (92 byte payload + 8 byte ICMP header = 100 byte)
ping -s 92 192.168.1.100

Sau khi ping, bạn có 15 giây để thiết lập kết nối SSH.

Kịch bản 3: Bảo vệ Web Server khỏi HTTP Flood

Để ngăn chặn tấn công CC hoặc SYN Flood nhằm vào cổng 80, chúng ta giới hạn số kết nối HTTP mới mỗi phút.

# Ghi log và chặn nếu một IP mở quá 20 kết nối trong 60 giây
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name HTTP_ACCESS --rcheck --seconds 60 --hitcount 20 -j LOG --log-prefix "HTTP_FLOOD: " --log-ip-options
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name HTTP_ACCESS --rcheck --seconds 60 --hitcount 20 -j DROP

# Cho phép các kết nối bình thường và ghi nhận vào danh sách
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name HTTP_ACCESS --set -j ACCEPT

Kịch bản 4: Phân tích quy tắc thứ tự xử lý (Set vs Check)

Vị trí của quy tắc --set--update/--rcheck là rất quan trọng. Xét ví dụ sau giới hạn 5 kết nối SSH mỗi giờ (3600 giây).

Cách đặt quy tắc an toàn (Để Policy mặc định là DROP):

# Quy tắc 1: Kiểm tra xem IP có vi phạm không, nếu có thì DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSH_LIMIT --rcheck --seconds 3600 --hitcount 5 -j DROP

# Quy tắc 2: Nếu không vi phạm, ghi nhận IP này và cho phép (ACCEPT)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSH_LIMIT --set -j ACCEPT

Luồng xử lý:

  1. Gói tin đầu tiên đến: Quy tắc 1 kiểm tra (chưa có dữ liệu, bỏ qua) -> Quy tắc 2 ghi nhận IP (count=1) và ACCEPT.
  2. Gói tin thứ 2..5 đến: Quy tắc 1 kiểm tra (count < 5, bỏ qua) -> Quy tắc 2 cập nhật IP và ACCEPT.
  3. Gói tin thứ 6 đến: Quy tắc 1 kiểm tra (count = 5, khớp điều kiện hitcount) -> Thực hiện DROP. Gói tin không đi tiếp đến quy tắc 2.

Kịch bản 5: Mở cổng SSH bằng "Knocking" qua TCP

Ngoài ICMP, bạn có thể dùng một cổng TCP ngẫu nhiên làm chìa khóa.

# 1. Ghi log khi có ai đó "gõ" vào cổng 8888
iptables -A INPUT -p tcp --dport 8888 --syn -j LOG --log-prefix "KNOCK_TRY: "

# 2. Nếu có kết nối đến cổng 8888, thêm IP vào danh sách SECRET_KNOCK và từ chối kết nối này
iptables -A INPUT -p tcp --dport 8888 --syn -m recent --set --name SECRET_KNOCK --rsource -j REJECT --reject-with tcp-reset

# 3. Cho phép SSH nếu IP có trong danh sách SECRET_KNOCK và thời gian "gõ" chưa quá 30 giây
iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 30 --name SECRET_KNOCK --rsource -j ACCEPT

Để mở cổng SSH, bạn có thể dùng netcat hoặc telnet để kết nối一次 đến cổng 8888:

nc -v -z server_ip 8888

Kiểm tra trạng thái danh sách

Bạn có thể xem các địa chỉ IP đang được theo dõi bởi module recent thông qua các file trong thư mục /proc/net/xt_recent/. Ví dụ, nếu tên list là SSH_LIMIT:

cat /proc/net/xt_recent/SSH_LIMIT

Kết quả sẽ hiển thị địa chỉ IP, thời gian sống (TTL) và dấu thời gian truy cập gần nhất (last_seen).

Thẻ: iptables linux firewall network-security sysadmin

Đăng vào ngày 14 tháng 7 lúc 18:44