利用 ipset 封禁大量 IP
環境:CentOS7.4 自帶6.29 版本(目前全球服務器廠商普遍使用的CentOS 最高版本爲 7.4)
用途:當機器受到網絡***時,使用 iptables 封 IP,有時候可能會封禁成千上萬個 IP,如果添加成千上萬條規則,在一臺注重性能的服務器或者本身性能就很差的設備上就不在適用了。ipset 就是爲了避免這個問題而生的。
基本流程:
ipset create test hash:ip
iptables -I INPUT -m set --match-set test src -j DROP
ipset add test 192.168.80.100
ipset add test 192.168.80.101
ipset add test ...
ipset list test # 查看 test 集合的內容
第一步:新建ipset 集合
第二歩:添加iptables 規則
第三步:向ipset中添加ip
創建集合
ipset n,create [ SETNAME ] [ TYPENAME ] [ CREATE-OPTIONS ]
SETNAME:即所創建集合的名字
TYPENAME:即類型名字,用類型來儲存ip
CREATE-OPTIONS:即創建選項,TYPENAME類型所對應的值
注意:
TYPENAME相關類型有:bitmap link hash
其中bitmap link 的儲存方式的集合大小是固定,hash類型的儲存大小是可變的(後面會解釋的)
CREATE-OPTIONS相關類型有:ip, net, mac, port, iface
即除了ip外,還可以是網絡段,端口號(支持指定 TCP/UDP 協議),mac 地址,網絡接口名稱,或者多種。
添加iptables 規則
在iptables中可以使用 -m set啓用ipset模塊
iptables -I INPUT -m set --match-set test src -j DROP
iptables -I INPUT -m set ! --match-set file src -j DROP
如果源地址(src)屬於 test 這個集合,就進行 DROP 操作。這條命令中,test 是作爲黑名單的,如果要把某個集合作爲白名單,添加一個 ‘!’ 符號就可以。
向集合中添加記錄
inset add [ SETNAME ] [ ADD-ENTRY ] [ ADD-OPTIONS ]
SETNAME:即所要添加ip的集合名字
ADD-ENTRY:所要添加的ip或含端口號等其他類型
ADD-OPTIONS:添加ip時的其他條件(後面會解釋的)
ipset add test 4.5.6.7
注意:可以同過以下方法找到需要封禁的ip
netstat -ntu | tail -n +3 | awk '{print $5}' | sort | uniq -c | sort -nr
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
注意:如果創建集合是指定的存儲內容包含 ip, 例如 hash:ip 或 hash:ip,port ,在添加記錄時,可以填 IP 段,但是仍然是以單獨一個個 IP 的方式來存儲的
刪除
刪除集合內的ip
inset del SETNAME DEL-ENTRY
參考添加的解釋
ipset del test 192.168.80.100 # 從 test 集合中刪除內容
刪除集合
ipset destroy test # 刪除 test 集合
ipset destroy # 刪除所有集合
注意:在刪除集合時,如果該集合被iptables規則已經引用,則需先刪除集合所在的規則,在刪除集合,如果集中存在ip並不會影響刪除集合
存儲類型
hash:net
hash:net 指定了可以往file 這個集合裏添加 IP 段或 IP 地址。
ipset create file hash:net
ipset add file 192.168.80.0/24
ipset add file 192.168.80.0/30 nomatch
ipset add file 192.168.80.9
ipset test file 192.168.80.2
第一條命令:創建hash:net集合
第二條命令:添加192.168.80.0/24該ip段的範圍
第三條命令:添加192.168.80.0/30該ip段的範圍,nomatch 是之前提到的[ ADD-OPTIONS ],就是添加某ip的附加條件
作用:是把 192.168.80.0/30 從 192.168.80.0/24 這一範圍相對更大的IP段裏“剝離”出來
也就是說執行完 ipset add file 192.168.80.0/24 之後,192.168.80.0/24 這一段 IP 是屬於file 集合的,接着又執行了 ipset add file 192.168.80.0/30 nomatch 之後,192.168.80.0/24 裏包含着的 192.168.80.0/30 這部分,就不屬於file 集合了。執行 ipset test file 192.168.80.2 就會得到結果 192.168.80.2 is NOT in set file,即表示該ip不屬於file集合了
注意:如下圖所示,即使結果出現了192.168.80.2 is NOT in set file,但還是可以添加到file集合中的,所以在添加IP段的時候,要清楚IP段所表示的範圍
hash:ip,port
ipset create pro hash:ip,port
ipset add pro 192.168.80.106,80
ipset add pro 192.168.80.108,udp:53
ipset add pro 192.168.80.104,80-86
第一條:創建 hash:ip,port 集合
第二條:添加 IP 地址爲192.168.80.106端口號爲80的記錄,沒有註明協議,默爲TCP協議
第三條:註明協議爲UDP協議
第四條:註明了IP地址和一個端口號範圍,這也是合法的命令
需要注意的是,前面有說過的:如果創建集合是指定的存儲內容包含 ip, 例如 hash:ip 或 hash:ip,port ,在添加記錄時,可以填 IP 段,但是仍然是以單獨一個個 IP 的方式來存儲的
解封
創建
如果一個集合是作爲黑名單使用,可以通過timeout參數,實現到期自動從黑名單裏刪除記錄
ipset create time hash:ip timeout 300
ipset add time 192.168.80.103
ipset add time 192.168.80.105 timeout 60
第一條:創建一個含有timeout參數的time集合,默認值爲1000s
第二條:在添加IP時不加timeout參數時,默認timeout 時間就時1000s
第三條:向集合添加IP 時指定了不同於默認值的 timeout 數值 100,那麼這一條記錄就會在100s後自動刪除
當我們再次查看time集合時,可以看到時間在倒計時,標誌着它們在多少秒之後會被刪除
修改
如果要重新爲某條記錄指定 timeout 參數,可以使用 -exit 參數
ipset -exist add time 192.168.80.103 timeout 500
這樣192.168.80.103 這一條數據的timeout 值就變成了500
注意:
1. 如果在創建集合時沒有指定timeout,那麼之後添加記錄時不支持timeout 參數,但如果在集合沒有指定timeout時,在添加記錄時使用了timeout參數,會報出錯誤想
2. 如果需要默認記錄不會過期(自動刪除),又需要添加某條記錄時加timeout參數,可以在創建集合時指定timeout的值爲0
如下圖所示:
ipset create err hash:ip
ipset add err 192.168.80.107 timeout 100
# 報錯信息爲:ipset v6.29: Kernel error received: Unknown error -1
hash的自增
前面說過:bitmap link 的儲存方式的集合大小是固定,hash類型的儲存大小是可變的
下面介紹下hash的兩個參數
hashsize:指定了創建集合時初始大小
maxelem:指定了集合最大存儲記錄的數量
如下圖所示:
ipset create initia hash:ip,port hashsize 4096 maxelem 1000000
ipset add initia 192.168.80.109
這樣就創建了一個 initia 集合,初始 hash 大小是 2048,如果滿了 hash 會自動擴容爲之前的兩倍,最大能存儲的數量是 100000 個
注意:如果沒有指定,則hashsize的默認初始值爲1024,maxelem的默認最大值爲65536
其他常用命令(包括前面提到的刪除)
ipset del test x.x.x.x # 從 test 集合中刪除內容
ipset list test # 查看 test 集合內容
ipset list # 查看所有集合的內容
ipset flush test # 清空 test 集合
ipset flush # 清空所有集合
ipset destroy test # 銷燬 test 集合
ipset destroy # 銷燬所有集合
ipset save test # 輸出 test 集合內容到標準輸出
ipset save # 輸出所有集合內容到標準輸出
ipset restore # 根據輸入內容恢復集合內容