server 受 ssh暴力登入攻擊的分析與防禦(3)--iptables + ipset 進階用法

參考 https://serverfault.com/a/537382/451844  的做法,再加上ipset [2]修改成進階的防攻擊規則。這個進階規則假設暴力攻擊會在解除封鎖的五分鐘內再度攻擊,且攻擊頻率固定。如超過一定數量,就再度封鎖並加倍封鎖時間。

iptables-ipset-limiter.sh
GitHub Gist: instantly share code, notes, and snippets.
#!/bin/bash
# Assumming brute force attack has constant hit rate, says X hit per Y seconds, across enough long time range, says T seconds. 
# Every time we block a suspisuous ip for a period of time and unblock it, 
# we should wait T seconds to see if there were further attack with rate X/Y hit/seconds.
# If this ip still has attack action during T seconds with hit rate X/Y, send it to block list which has doubled block time.
# 

L1_period=300
L2_period=3600
L1_hit_upper=12
L1_hit_lower=1
L2_hit=7

during_period=3600
during_hit=5

# create ipsets to store different block time range buckets
ipset create timer0L1 hash:ip counters timeout $L1_period
ipset create timer0L2 hash:ip counters timeout $L2_period
ipset create blockset hash:ip timeout $during_period
ipset create allowset hash:ip


# block 10 min 
hit_period=600
wait_time=$(($hit_period+$during_period))
ipset create timer1 hash:ip counters timeout $wait_time

iptables -X black1
iptables -N black1
iptables -A black1 -j SET --add-set blockset src --timeout $hit_period
iptables -A black1 -j SET --add-set timer1 src
iptables -A black1 -j LOG --log-prefix 'black1-DROP: '
iptables -A black1 -j DROP


# block 20 min
hit_period=$(($hit_period*2))
during_period=$(($during_period*2))
wait_time=$(($hit_period+$during_period))
ipset create timer2 hash:ip counters timeout $wait_time

iptables -X black2
iptables -N black2
iptables -A black2 -j SET --add-set blockset src --timeout $hit_period
iptables -A black2 -j SET --add-set timer2 src
iptables -A black2 -j LOG --log-prefix 'black2-DROP: '
iptables -A black2 -j DROP


# block 40 min
hit_period=$(($hit_period*2))
during_period=$(($during_period*2))
wait_time=$(($hit_period+$during_period))
ipset create timer3 hash:ip counters timeout $wait_time

iptables -X black3
iptables -N black3
iptables -A black3 -j SET --add-set blockset src --timeout $hit_period
iptables -A black3 -j SET --add-set timer3 src
iptables -A black3 -j LOG --log-prefix 'black3-DROP: '
iptables -A black3 -j DROP


# block 1 day
hit_period=86400
during_period=28800
wait_time=$(($hit_period+$during_period))
ipset create timer4 hash:ip counters timeout $wait_time

iptables -X black4
iptables -N black4
iptables -A black4 -j SET --add-set blockset src --timeout $hit_period
iptables -A black4 -j SET --add-set timer4 src
iptables -A black4 -j LOG --log-prefix 'black4-DROP: '
iptables -A black4 -j DROP


# block 24 days
hit_period=2073600
during_period=57600
wait_time=$(($hit_period+$during_period))

iptables -X black0
iptables -N black0
iptables -A black0 -j SET --add-set blockset src --timeout $hit_period
iptables -A black0 -j SET --del-set timer4 src
iptables -A black0 -j SET --add-set timer4 src --timeout $wait_time
iptables -A black0 -j LOG --log-prefix 'black0-DROP: '
iptables -A black0 -j DROP


# just for log when drop from blockset
iptables -X blackb
iptables -N blackb
iptables -A blackb -j LOG --log-prefix 'blackb-DROP: '
iptables -A blackb -j DROP


# timer L2 (long term cumulative rules)
iptables -X blackL2
iptables -N blackL2
iptables -A blackL2   -m set --match-set timer0L2 src --packets-gt $L2_hit -j black1
iptables -A blackL2   -j SET --add-set timer0L2 src
iptables -A blackL2   -j SET --add-set timer0L1 src
iptables -A blackL2   -j ACCEPT


# create limiter chain
iptables -X limiter
iptables -N limiter
iptables -A limiter   -m set --match-set allowset src -j ACCEPT
iptables -A limiter   -m set --match-set blockset src -j blackb
iptables -A limiter   -m set --match-set timer4 src --packets-gt $during_hit -j black0
iptables -A limiter   -m set --match-set timer3 src --packets-gt $during_hit -j black4
iptables -A limiter   -m set --match-set timer2 src --packets-gt $during_hit -j black3
iptables -A limiter   -m set --match-set timer1 src --packets-gt $during_hit -j black2
iptables -A limiter   -m set --match-set timer0L1 src --packets-gt $L1_hit_upper -j black1
iptables -A limiter   -m set --match-set timer0L1 src --packets-gt $L1_hit_lower -j ACCEPT
iptables -A limiter   -m set --match-set timer0L2 src -j blackL2
iptables -A limiter   -j SET --add-set timer0L2 src
iptables -A limiter   -j SET --add-set timer0L1 src
iptables -A limiter   -j ACCEPT


# create rules to limiter chain
iptables -A INPUT   -p TCP --dport ssh   -m state --state NEW -j limiter

set allowed ip

sudo ipset add allowset 192.168.2.100

參考 Man page of IPTABLES  :

for iptables options

-A, --append chain rule-specification
    Append one or more rules to the end of the selected chain. When the source and/or destination names resolve to more than one address, a rule will be added for each possible address combination. 

-I, --insert chain [rulenum] rule-specification
    Insert one or more rules in the selected chain as the given rule number. So, if the rule number is 1, the rule or rules are inserted at the head of the chain. This is also the default if no rule number is specified. 

-N, --new-chain chain
    Create a new user-defined chain by the given name. There must be no target of that name already. 
-X, --delete-chain [chain]
    Delete the optional user-defined chain specified. There must be no references to the chain. If there are, you must delete or replace the referring rules before the chain can be deleted. The chain must be empty, i.e. not contain any rules. If no argument is given, it will attempt to delete every non-builtin chain in the table. 

Man page of iptables-extensions

for iptables -j SET

SET
This module adds and/or deletes entries from IP sets which can be defined by ipset(8).

--add-set setname flag[,flag...]
    add the address(es)/port(s) of the packet to the set 
--del-set setname flag[,flag...]
    delete the address(es)/port(s) of the packet from the set 
    
--timeout value
    when adding an entry, the timeout value to use instead of the default one from the set definition 
--exist
    when adding an entry if it already exists, reset the timeout value to the specified one or to the default from the set definition 

for iptables -m set

set
This module matches IP sets which can be defined by ipset(8).

[!] --match-set setname flag[,flag]...
    where flags are the comma separated list of src and/or dst specifications and there can be no more than six of them. Hence the command 

     iptables -A FORWARD -m set --match-set test src,dst 
    will match packets, for which (if the set type is ipportmap) the source address and destination port pair can be found in the specified set. If the set type of the specified set is single dimension (for example ipmap), then the command will match packets for which the source address can be found in the specified set. 
    
! --update-counters
    If the --update-counters flag is negated, then the packet and byte counters of the matching element in the set won't be updated. Default the packet and byte counters are updated. 
    
--packets-lt value
    If the packet is matched an element in the set, match only if the packet counter of the element is less than the given value as well. 
--packets-gt value
    If the packet is matched an element in the set, match only if the packet counter of the element is greater than the given value as well. 

Man page of IPSET

you need to add timeout option when create ipset to support timeout function:


GENERIC CREATE AND ADD OPTIONS
timeout
All set types supports the optional timeout parameter when creating a set and adding entries. The value of the timeout parameter for the create command means the default timeout value (in seconds) for new entries. If a set is created with timeout support, then the same timeout option can be used to specify non-default timeout values when adding entries. Zero timeout value means the entry is added permanent to the set. The timeout value of already added elements can be changed by re-adding the element using the -exist option. The largest possible timeout value is 2147483 (in seconds). Example:

    ipset create test hash:ip timeout 300 
    ipset add test 192.168.0.1 timeout 60 
    ipset -exist add test 192.168.0.1 timeout 600 

When listing the set, the number of entries printed in the header might be larger than the listed number of entries for sets with the timeout extensions: the number of entries in the set is updated when elements added/deleted to the set and periodically when the garbage collector evicts the timed out entries. 


counters, packets, bytes
All set types support the optional counters option when creating a set. If the option is specified then the set is created with packet and byte counters per element support. The packet and byte counters are initialized to zero when the elements are (re-)added to the set, unless the packet and byte counter values are explicitly specified by the packets and bytes options. An example when an element is added to a set with non-zero counter values:

    ipset create foo hash:ip counters 
    ipset add foo 192.168.1.1 packets 42 bytes 1024 
    
    
SET TYPES
hash:ip
The hash:ip set type uses a hash to store IP host addresses (default) or network addresses. Zero valued IP address cannot be stored in a hash:ip type of set. 


hash:ip,port
The hash:ip,port set type uses a hash to store IP address and port number pairs. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. 

 Examples:

    ipset create foo hash:ip,port 
    ipset add foo 192.168.1.0/24,80-82 
    ipset add foo 192.168.1.1,udp:53 
    ipset add foo 192.168.1.1,vrrp:0 
    ipset test foo 192.168.1.1,80 

清除所有set中的ip紀錄

ipset flush

清除所有 sets

ipset destroy

What is the difference between iptables -X and iptables -F? - Server Fault

清除所有chain 中的 rule

iptables -F

當 chain 為empty時,刪除所有 user defined chain (Built-in chain 無法刪除)

iptables -X

[1] IP sets 包含ipset, iptables, iptables-extention 的說明

[2] Advanced Firewall Configurations with ipset | Linux Journal

系列文章

server 受 ssh暴力登入攻擊的分析與防禦(1)--iptables 的使用

server 受 ssh暴力登入攻擊的分析與防禦(2)--fail2ban 的使用

server 受 ssh暴力登入攻擊的分析與防禦(3)--iptables + ipset 進階用法

server 受 ssh暴力登入攻擊的分析與防禦(4)--使用 captcha 及 2FA