iptables - Rate limiting

最後更新: 2019-09-18

目錄

 


Rate limiting (recent module)

 

Load Module

modprobe ipt_recent

Rule 的建立次序

<1> 建立新的 Chain, 用來存放 port 22 的設定

iptables -N SSH

<2> 到 port 22 的 package 會去到新建立的 Chain (SSH)

# The -m state and --state NEW options restrict the operation of these rules to new connections only.

# Without this every packet would count towards the rate limit

iptables -I INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -j SSHSCAN

<3> 更新 Source IP 的連接次數

# --set option causes the recent module add the source address of the packet to the list.(oldest_pkt)

# If the source address is already in the list, this will update the existing entry.(last_seen)

# This will always return success. 可以接上 "-j ACCEPT/DROP" 使用

# --name NAME. Specify the list to use for the commands. no name => "DEFAULT"

iptables -A SSH -m recent --name SSHSCAN --set

/proc/net/xt_recent/NAME 的內容"

src=192.168.123.10 ttl: 64 last_seen: 5199646892 oldest_pkt: 3 5199609471, 5199627202, 5199646892

說明

last_seen 那 pkg 排第 oldest_pkt

"--set -j ACCEPT" 用於 default DROP

i.e.

...
-A Port53 -m recent --name Port53 --rcheck --seconds 1 --hitcount 10 -j LOG --log-prefix "Port53: "
-A Port53 -m recent --name Port53 --update --seconds 1 --hitcount 10 -j DROP
-A Port53 -m recent --name Port53 --set -j ACCEPT
-A Port53 -j DROP

<4> hit 中條件才 Drop

# --rcheck, Check if the source address of the packet is currently in the list.

# --update, Like --rcheck, except it will update the "last seen" timestamp if it matches.

=> update 比 rcheck 嚴格, Source 必須 "Quiet" seconds 時間才解封

iptables -A SSH -m recent --name SSHSCAN --rcheck --seconds 60 --hitcount 4 -j LOG \
         --log-prefix "Anti SSH-Bruteforce: "
iptables -A SSH -m recent --name SSHSCAN --update --seconds 60 --hitcount 4 -j DROP

--seconds

conjunction with one of --rcheck or --update

When used, this will narrow the match to only happen
(when the address is in the list and was seen within the last given number of seconds)

--hitcount hits

conjunction with one of --rcheck or --update

The maximum value for the hitcount parameter is given by the "ip_pkt_list_tot"

Other setting

--rsource (This is the default)

Match/save the source address of each packet in the recent list table.

--rdest

Match/save the destination address of each packet in the recent list table.

<5> Policy

如果 Default Policy 係 DROP 的話, 在這裡要 ACCEPT 它

iptables -A SSHSCAN -j ACCEPT

查看什麼人被 Catch 了

/proc/net/xt_recent/<name>

src=192.168.123.10 ttl: 64 last_seen: 5199646892 oldest_pkt: 3 5199609471, 5199627202, 5199646892       
# 它們不是順序的, "round robin replacement" 來

Usage:

#  to add addr to the DEFAULT list

echo +addr >/proc/net/xt_recent/DEFAULT

# to remove addr from the DEFAULT list

echo -addr >/proc/net/xt_recent/DEFAULT

# to flush the DEFAULT list (remove all entries).

echo / >/proc/net/xt_recent/DEFAULT

Module parameters

modinfo xt_recent

ip_list_tot:       number of IPs to remember per list (uint)
ip_pkt_list_tot:   number of packets per IP to remember (max. 255) (--hitcount)
ip_list_hash_size: size of hash table used to look up IPs (default: 32768)
                   0 means to calculate it based on ip_list_tot

# checking setting

cat /sys/module/xt_recent/parameters/ip_list_tot               # Default: 100

cat /sys/module/xt_recent/parameters/ip_pkt_list_tot        # Default: 20

# 永久 setting

/etc/modprobe.d/xt_recent.conf

options xt_recent ip_list_tot=20480 ip_pkt_list_tot=10

P.S.

# 查看是否支援此功能

modprobe -l | grep recent

kernel/net/netfilter/xt_recent.ko

# load modue

modprobe xt_recent

# reload module with new settings

在 /etc/sysconfig/iptables "#" 了  "recent" 有關的 rule

service iptables restart

modprobe -r xt_recent

應用1: Quiet Time

由 (--rcheck)

iptables -A FORWARD -i eth0 -m recent --rcheck --seconds 60 -j DROP
iptables -A FORWARD -i eth0 -m recent --set -j ACCEPT

改成(--update)

iptables -A FORWARD -i eth0 -m recent --update --seconds 60 -j DROP
iptables -A FORWARD -i eth0 -m recent --set -j ACCEPT

應用2: sync attack

# These rules limit the rate of SYN requests from one IP to 20 per minute. Do not use it on regular basis!

iptables -A INPUT -p tcp -m state --state NEW -m recent \
         --update --seconds 60 --hitcount 20 -j DROP
iptables -A INPUT -p tcp -m state --state NEW -m recent \
         --set -j ACCEPT

應用3: 防 DOS

# load module

# create setting

echo 'options xt_recent ip_list_tot=20480 ip_pkt_list_tot=15' > /etc/modprobe.d/xt_recent.conf

# load module

modprobe xt_recent

# checking load module

lsmod | grep xt_recent

# setup rule

/etc/sysconfig/iptables

# Rule
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -j HTTPDOS
.........

:HTTPDOSWL - [0:0]
-A HTTPDOSWL -s 192.168.88.177 -j ACCEPT

:HTTPDOS - [0:0]
-A HTTPDOS -j HTTPDOSWL
-A HTTPDOS -m recent --set --name HTTPDOS
-A HTTPDOS -m recent --rcheck --seconds 1 --hitcount 15 --name HTTPDOS --rsource -j DROP
-A HTTPDOS -j ACCEPT

# checking

# check xt_recent working

# server side

less /proc/net/xt_recent/HTTPDOS

# client side

openload server_ip/index.php 100

# whitelist

# add ip to whitelist

iptables -I HTTPDOSWL -s 192.168.88.183 -j ACCEPT

# cleanup

iptables -F HTTPDOSWL

 


連線數量限制

 

iplimit

-m iplimit --iplimit-above <num>

Example:

iptables -A INPUT -p tcp --syn --dport 80 -m iplimit --iplimit-above 10 --iplimit-mak 24 -j REJECT

在同一 C 級網絡內, 同時只可有 10 個不同 IP address 連到本機的 80 Port.

connlimit

modprobe xt_connlimit

lsmod | grep xt_connlimit

# This will reject connections above 15 from one source IP

iptables -A INPUT -p tcp --dport 80 \
         -m connlimit --connlimit-above 15 \
         -j REJECT --reject-with tcp-reset

Other opts

--connlimit-mask 32              # Default: 32

[!] --mark value[/mask]

Usage:

*filter

......................

:HTTPDOSWL - [0:0]
-A HTTPDOSWL -s 192.168.88.177 -j ACCEPT
-A HTTPDOSWL -j RETURN

:HTTPDOS - [0:0]
-A HTTPDOS -j HTTPDOSWL
-A HTTPDOS -j LOG --log-level 4 --log-prefix 'DDOS'
-A HTTPDOS -j DROP

-A INPUT -i eth0 -p tcp --dport 80 -m connlimit --connlimit-above 10 -j HTTPDOS
-A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT

.......................


-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

 


速度限制 - limit

 

Module

modprobe xt_limit

用法:

-m limit

‐‐limit N[/unit]                         單位時間內發多少個通行證

                                              By default 3 matches per hour

                                              Default unit 是 , 可用的單位: /second, /minute, /hour, /day

‐‐limit‐burst N                         一開始有多少個通行證可用, Default 5. 用光了後, 新的 package 就不能通過 !

P.S.

# 相當於 3 matches per hour , with a burst of 5 (沒有填 --limit 及 --limit-burst 時)

iptables -A INPUT -p icmp --icmp-type ping -m limit-j ACCEPT
iptables -A INPUT -p icmp --icmp-type ping -j DROP

Example1: limit ping

iptables -A INPUT -p icmp --icmp-type ping -m limit --limit 6/m -j ACCEPT
iptables -A INPUT -p icmp --icmp-type ping -j DROP

output:

PING 192.168.123.13 (192.168.123.13) 56(84) bytes of data.
64 bytes from 192.168.123.13: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from 192.168.123.13: icmp_seq=2 ttl=64 time=0.044 ms
64 bytes from 192.168.123.13: icmp_seq=3 ttl=64 time=0.070 ms
64 bytes from 192.168.123.13: icmp_seq=4 ttl=64 time=0.051 ms
64 bytes from 192.168.123.13: icmp_seq=5 ttl=64 time=0.051 ms
64 bytes from 192.168.123.13: icmp_seq=11 ttl=64 time=0.055 ms
64 bytes from 192.168.123.13: icmp_seq=21 ttl=64 time=0.051 ms

# 一開始連續 5 個 package 通過, 之後每 10s 一個 package 通過 (60s/6p=10)

Remark:

‐‐limit‐burst 的 N 不能太大, 否則 limit 有排都不生效

Example2: Limit tcp syn

iptables -A INPUT -p tcp -m state --state NEW -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -A INPUT –p tcp –m state --state NEW –j DROP

OR

iptables -N syn_flood
iptables -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j syn_flood
iptables -A syn_flood -m limit --limit 25/s --limit-burst 50 -j RETURN
iptables -A syn_flood -j DROP

Example3: http DOS

:HTTPDOSWL - [0:0]
-A HTTPDOSWL -s 192.168.88.177 -j ACCEPT
-A HTTPDOSWL -j RETURN

:HTTPDOS - [0:0]
-A HTTPDOS -j HTTPDOSWL
-A HTTPDOS -j LOG --log-level 4 --log-prefix 'HTTPDOS'
-A HTTPDOS -j DROP

# Keep state.
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

-A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW -m limit --limit 5 --limit-burst 15 -j ACCEPT
-A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW -j HTTPDOS

More More

以下 limit rule 係無效的. ("Keep state" 在 "Limit response ping" 前)

# Keep state
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Limit response ping
-A INPUT -p icmp --icmp-type 8 -m limit --limit 2/s --limit-burst 2 -j ACCEPT
-A INPUT -p icmp -j DROP

 


DoS Protection(SYN,RST)

 

iptables -v -nL

Chain DOS_PROTECT (1 references)
 pkts bytes target  prot opt in   out source     destination
    0     0 RETURN  icmp --  eth0 *   0.0.0.0/0  0.0.0.0/0     icmptype 8 limit: avg 1/sec burst 5
    0     0 DROP    icmp --  eth0 *   0.0.0.0/0  0.0.0.0/0     icmptype 8
    0     0 RETURN  tcp  --  eth0 *   0.0.0.0/0  0.0.0.0/0     tcp flags:0x17/0x04 limit: avg 1/sec burst 5
    0     0 DROP    tcp  --  eth0 *   0.0.0.0/0  0.0.0.0/0     tcp flags:0x17/0x04
    1    52 RETURN  tcp  --  eth0 *   0.0.0.0/0  0.0.0.0/0     tcp flags:0x17/0x02 limit: avg 10000/sec burst 100
    0     0 DROP    tcp  --  eth0 *   0.0.0.0/0  0.0.0.0/0     tcp flags:0x17/0x02

Remark

  • SYN=0x02
  • RST=0x04