Bài viết hướng dẫn sử dụng iptables trên server cài HĐH nhân Linux phần nào ứng phó trước các cuộc tấn công DDoS.
Mục lục
DDoS là gì?
DoS (Denial of Service) là cuộc tấn công mang tính chất phá hoại bằng cách làm ngập lụt (flood) đến mức quá tải hạ tầng mạng của Server đích bằng dòng dữ liệu khổng lồ, khiến cho các máy client bình thường khác không thể kết nối với server.
DDoS (Distributed Denial of Service) là cuộc tấn công DoS có quy mô lớn với traffic phá hoại đến từ nhiều nguồn, có thể là từ hệ thống rất nhiều máy client bị điều khiển (botnet).
Ta thường gặp nhất là DDoS tấn công từ Layer 3, nhằm vào hạ tầng các Website với mục đích “hạ gục” nguồn thông tin và công cụ kinh doanh của đối phương.
Khi đối diện với cuộc tấn công DDoS quy mô lớn thì rất khó để phân biệt đâu là request tấn công và đâu là request từ người dùng thật. Việc phân loại này nếu automate thì cũng cực kỳ tốn kém tài nguyên.
Vì thế nếu ta cung cấp các dịch vụ công cộng thì DDoS hầu như không thể ngăn chặn hoàn toàn mà chỉ có thể tìm cách “chống chọi” mà thôi.
Để chống chọi với DDoS cần có một hạ tầng cực kỳ mạnh mẽ và đồng bộ từ Layer 1 đến Layer 7 trong mô hình OSI – vô cùng tốn kém.
Vì vậy DDoS thực sự là một loại hình tội phạm phá hoại tài sản, và Anti-DDoS là “key” cạnh tranh hàng đầu giữa các dịch vụ Hosting.
Có khá nhiều phương pháp DDoS, và dưới đây là hướng dẫn sử dụng iptables
để ứng phó với một số loại hình tấn công, phần nào làm giảm mức độ ảnh hưởng ngay tại server Linux.
Cấu hình giảm hậu quả DDoS ở mức kernel
Thêm đoạn cấu hình sau vào cuối file /etc/sysctl.conf
để tối ưu hiệu năng của kernel trước các cuộc tấn công DDoS và hỗ trợ cho các cấu hình ngừa DDoS bằng iptables phía sau.
kernel.printk = 4 4 1 7 kernel.panic = 10 kernel.sysrq = 0 kernel.shmmax = 4294967296 kernel.shmall = 4194304 kernel.core_uses_pid = 1 kernel.msgmnb = 65536 kernel.msgmax = 65536 vm.swappiness = 20 vm.dirty_ratio = 80 vm.dirty_background_ratio = 5 fs.file-max = 2097152 net.core.netdev_max_backlog = 262144 net.core.rmem_default = 31457280 net.core.rmem_max = 67108864 net.core.wmem_default = 31457280 net.core.wmem_max = 67108864 net.core.somaxconn = 65535 net.core.optmem_max = 25165824 net.ipv4.neigh.default.gc_thresh1 = 4096 net.ipv4.neigh.default.gc_thresh2 = 8192 net.ipv4.neigh.default.gc_thresh3 = 16384 net.ipv4.neigh.default.gc_interval = 5 net.ipv4.neigh.default.gc_stale_time = 120 net.netfilter.nf_conntrack_max = 10000000 net.netfilter.nf_conntrack_tcp_loose = 0 net.netfilter.nf_conntrack_tcp_timeout_established = 1800 net.netfilter.nf_conntrack_tcp_timeout_close = 10 net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10 net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 20 net.netfilter.nf_conntrack_tcp_timeout_last_ack = 20 net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20 net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 20 net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10 net.ipv4.tcp_slow_start_after_idle = 0 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.ip_no_pmtu_disc = 1 net.ipv4.route.flush = 1 net.ipv4.route.max_size = 8048576 net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 net.ipv4.tcp_congestion_control = htcp net.ipv4.tcp_mem = 65536 131072 262144 net.ipv4.udp_mem = 65536 131072 262144 net.ipv4.tcp_rmem = 4096 87380 33554432 net.ipv4.udp_rmem_min = 16384 net.ipv4.tcp_wmem = 4096 87380 33554432 net.ipv4.udp_wmem_min = 16384 net.ipv4.tcp_max_tw_buckets = 1440000 net.ipv4.tcp_tw_recycle = 0 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_max_orphans = 400000 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_rfc1337 = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 2 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_sack = 1 net.ipv4.tcp_fack = 1 net.ipv4.tcp_ecn = 2 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 60 net.ipv4.tcp_keepalive_probes = 10 net.ipv4.tcp_no_metrics_save = 1 net.ipv4.ip_forward = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.all.rp_filter = 1
Áp dụng ngay cấu hình trên bằng lệnh sysctl như sau.
sudo sysctl -p
Ngăn ngừa DDoS bằng iptables
Do các cuộc tấn công DDoS có cường độ rất cao, ta không nên sử dụng INPUT
chain để ngăn chặn các gói tin này vì sẽ ảnh hưởng đến giảm hiệu năng của hệ thống, do gói tin trước khi đến INPUT
chain phải đi qua PREROUTING
và FORWARD
chain.
Vì thế ta hãy dùng mangle
table để xử lý gói tin tại PREROUTING
chain.
Chặn các gói tin không hợp lệ
Chặn các gói tin không phải là SYN và không thuộc các gói TCP đã bắt tay (ESTABLISHED) thành công.
iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
Chặn các gói tin mới nhưng không phải là SYN
Chặn các gói tin mới (kết nối chưa ở trạng thái ESTABLISHED) nhưng không có cờ SYN. Cái này tương tự cái trên nhưng vì lý do nào đó rule phía trên để lọt vài gói kiểu như thế này.
iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
Chặn các gói SYN có kích thước bất thường
Ngăn ngừa SYN flood bằng cách chặn các gói SYN có giá trị TCP MSS (Maximum segment size) lớn bất thường ví dụ từ 536 – 65535.
iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
Chặn các gói tin có trạng thái không hợp lý
Ngăn chặn các gói tin chứa một số cờ mà các gói tin hợp lệ không bao giờ được set.
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
Ngăn các gói tin giả mạo (spoofing) là từ mạng riêng
Nếu máy chủ không có liên hệ gì với mạng nội bộ thì ta nên có thiết lập này để loại bỏ các gói tin ‘giả vờ’ như đến từ các máy trong cùng mạng LAN.
iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
Chặn các gói tin ICMP
ICMP thường dùng để ping và vì thế dễ bị lợi dụng để thực hiện đòn Ping of Death (ping flood), ICMP flood hoặc ICMP fragmentation flood. Nếu cảm thấy việc sử dụng ping là không cần thiết thì nên bật thiết lập này.
iptables -t mangle -A PREROUTING -p icmp -j DROP
Không cho client tạo quá nhiều kết nối
Rule dưới đây ngăn không cho client tạo quá 80 kết nối (connection) đến server. Điều này giúp ngăn chặn tấn công kiểu tạo kết nối (connection attack).
Con số 80 chỉ là ví dụ, ta cần điều chỉnh tùy theo hoạt động của ứng dụng trên server.
iptables -A INPUT -p tcp -m connlimit --connlimit-above 80 -j REJECT --reject-with tcp-reset
Giới hạn số kết nối TCP mới từ một client trong khoảng thời gian ngắn
Giới hạn không cho nhiều hơn 60 kết nối TCP mới từ một client trong mỗi giây. Con số 60 cũng chỉ là ví dụ trong tham số –limit.
Cách này nói chung cũng không hiệu quả lắm trong việc ngăn DDoS vì kẻ gian thường tấn công bằng số lượng lớn client hoặc giả mạo vô hạn IP nguồn.
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
Ngăn các gói fragment
Ngăn chặn các gói fragment với mục đích ngăn ngừa UDP fragmentation flood.
Tuy nhiên trước một cuộc tấn công UDP fragment flood vũ bão thì phía network card là physical layer cũng sẽ bị quá tải và nhiều khả năng gói tin không có cơ hội gặp rule này. Vì thế nó cũng không cần thiết lắm.
iptables -t mangle -A PREROUTING -f -j DROP
Giảm thiểu số lượng TCP RST trong khoảng thời gian ngắn
Mục đích của việc giảm thiểu này (ví dụ dưới đây là chỉ cho 2 gói RST trong 1 giây) là để ngăn chặn kiểu tấn công TCP RST floods. Tuy nhiên hiệu quả của phương pháp này vẫn còn là dấu hỏi.
iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
Ngăn ngừa port scanning
Port scanning không hẳn là một hành vi DDoS nhưng nó là một trong những sự chuẩn bị của ‘tội ác’ này bằng việc phát hiện những cổng TCP nào đang mở trên server.
Rule dưới đây nhận biết dấu hiệu của port scanning dựa trên các cờ và tần suất của gói TCP đến và chặn hành vi này.
/sbin/iptables -N port-scanning /sbin/iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN /sbin/iptables -A port-scanning -j DROP
Ngăn tấn công brute-force
Rule dưới đây giảm thiểu tấn công brute-force để dò mật khẩu truy cập, bằng cách hạn chế số lượng những kết nối mới tạo trong khoảng thời gian ngắn tại một cổng dịch vụ nào đó.
Ví dụ sau là dành cho SSH – một trong những service phổ biến và can thiệp sâu trên server (SHH port= 22). Ta có thể thay bằng cổng dịch vụ khác.
/sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set /sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP