Iptables 之recent模塊小結


 

Iptables的recent模塊用於限制一段時間內的連接數, 是謹防大量請求攻擊的必殺絕技! 善加利用該模塊可充分保證服務器安全。

recent常用參數
--name      設定列表名稱,即設置跟蹤數據庫的文件名. 默認DEFAULT;
--rsource   源地址,此為默認。 只進行數據庫中信息的匹配,並不會對已存在的數據做任何變更操作;
--rdest       目的地址;
--seconds  指定時間內. 當事件發生時,只會匹配數據庫中前"幾秒"內的記錄,--seconds必須與--rcheck或--update參數共用;
--hitcount   命中次數. hits匹配重復發生次數,必須與--rcheck或--update參數共用;
--set           將地址添加進列表,並更新信息,包含地址加入的時間戳。 即將符合條件的來源數據添加到數據庫中,但如果來源端數據已經存在,則更新數據庫中的記錄信息;
--rcheck     檢查地址是否在列表,以第一個匹配開始計算時間;
--update    和rcheck類似,以最后一個匹配計算時間。 如果來源端的數據已存在,則將其更新;若不存在,則不做任何處理;
--remove   在列表里刪除相應地址,后跟列表名稱及地址。如果來源端數據已存在,則將其刪除,若不存在,則不做任何處理;

recent模塊需要注意的地方
a)  目錄/proc/net/下的xt_recent目錄是在啟用recent模塊之后才有的,如果沒有在iptables中使用recent模塊,/proc/net/目錄中是沒有xt_recent目錄的;
b)  因recent模塊最多只能記錄20條記錄,所以當源發送的數據包超過20后,recent模塊的計數器會立刻減掉20,這也就是為什么old_packets的值就總是處於1-20之間;
c)  如果配合seconds參數使用的是--rcheck參數而不是--update,則recent模塊會從收到第一個數據包開始計算阻斷時間,而--update是從收到的最后一個數據包開始計算阻斷時間,即如果服務器在8點收到了源發出第一個icmp數據包,在8點15分收到源發出的第20個數據包,如果使用的是--rcheck參數,那么8點半的時候,用戶就又可以發送icmp數據包了,如果使用是--update參數,則用戶必須等到8點40才能發送icmp數據包;
d)  當源發送數據包的個數大於或等於recent模塊的hitcount參數所指定的值時,相應的iptables規則才會被激活;

recent命令大體有如下三個排列組合
--set句在前,--update(或--rcheck)句在后;
--update(或--rcheck)句在前,--set句在后;
--set句帶或不帶-j ACCEPT。基本是上面這三項的排列組合;

下面通過幾個案例進行說明
1)  利用iptables的recent模塊來抵御簡單的DOS攻擊, 下面以限制ssh遠程連接為例

iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds  300 --hitcount 3 --name SSH -j DROP

以上三條規則的解釋如下:
a) 利用connlimit模塊將單IP的並發設置為3;會誤殺使用NAT上網的用戶,可以根據實際情況增大該值;
b) 利用recent和state模塊限制單IP在300s內只能與本機建立3個新連接。被限制一分鍾后即可恢復訪問。
c) 第一句是記錄訪問tcp 22端口的新連接,記錄名稱為SSH, --set 記錄數據包的來源IP,如果IP已經存在將更新已經存在的條目
d) 第三句是指SSH記錄中的IP,300s內發起超過3次連接則拒絕此IP的連接。
     --update 是指每次建立連接都更新列表;
     --seconds必須與--update同時使用
     --hitcount必須與--update同時使用
e) 可以使用下面的這句記錄日志:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSH Attack"

recent模塊可以看作iptables里面維護了一個地址列表,這個地址列表可以通過"--set"、"--update"、"--rcheck"、"--remove"四種方法來修改列表,每次使用時只能選用一種
還可附帶"--name"參數來指 定列表的名字(默認為DEFAULT),"--rsource"、"--rdest"指示當前方法應用到數據包的源地址還是目的地址(默認是前者)。recent語句都帶有布爾型返回值,每次執行若結果為真,則會執行后續的語句,比如"-j ACCEPT"之類的。"--seconds"參數表示限制包地址被記錄進列表的時間要小於等於后面的時間。

基於上面的說明,現在來看四個基本方法的作用:
--set       將地址添加進列表,並更新信息,包含地址加入的時間戳。
--rcheck  檢查地址是否在列表。
--update  跟rcheck一樣,但會刷新時間戳。
--remove 就是在列表里刪除地址,如果要刪除的地址不存在就會返回假。

例1:限制無法ssh直接連接服務器,需先用較大包ping一下,此時在15秒內才可以連接上

iptables -P INPUT DROP
iptables -A INPUT -s 127.0.0.1/32 -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 128 -m recent --set --name SSHOPEN --rsource -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 15 --name SSHOPEN --rsource -j ACCEPT

以上命令解說
a) 將INPUT鏈默認策略置為DROP,當包走完INPUT鏈而沒被拿走時就會丟棄掉;
b) 本地localhost的包全部接受;
c)  對於已建立連接或是與已連接相關的包都接受,服務器對外連接回來的包一般都走這條;基本環境已經配好了,現在開始要為連接到服務器的ssh打開通路。
d)  icmp類型8是ping包;指定包大小為128字節;recent用的列表名稱為SSHOPEN,列表記錄源地址。符合上述條件的數據包都接收。如果ping包內容為100字節,則加上IP      頭, ICMP頭的28字節,總共128字節。
e) 接受一般的ping包;
f)  對連接ssh 22端口的連接進行處理,來源於SSHOPEN源地址列表並且在列表時間小於等於15秒的才放行。

例2:  限制每ip在一分鍾內最多對服務器只能有8個http連接

iptables -I INPUT -p tcp --dport 80 -d 192.168.10.10 -m state --state NEW -m recent --name httpuser --set
iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j LOG --log-prefix 'HTTP attack: '
iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j DROP

以上命令解說
a) 192.168.10.10是服務器ip
b) 參數-I,將本規則插入到 INPUT 鏈里頭的最上頭。只要是 TCP連接,目標端口是80,目標 IP是我們服務器的IP,剛剛新被建立起來時,我們就將這個聯機列入 httpuser 這分  清單中;
c) 參數-A,將本規則附在 INPUT 鏈的最尾端。只要是60秒內,同一個來源連續產生多個聯機,到達第9個聯機時,我們對此聯機留下Log記錄。記錄行會以 HTTP attack 開頭。  每一次的本規則比對, –update 均會更新httpuser清單中的列表;
d)  參數-A,將本規則附在 INPUT 鏈的最尾端。同樣的比對條件,但是本次的動作則是將此連接丟掉;
e) 所以,這三行規則表示,我們允許一個客戶端,每一分鍾內可以接上服務器8個。具體數值可以看運維者決定。這些規則另外也可以用在其它對外開放的網絡服務上,例如port  22 (SSH), port 25 (smtp email)。

2) 對連接到服務器B的SSH連接進行限制,每個IP每小時只限連接5次

-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set -j ACCEPT

服務器A連接服務器B的SSH服務的數據包流程,假設以下數據包是在一小時(3600秒)內到達服務器B(iptables配置如上)的:
a) 當這個服務器A的第1個SSH包到達服務器B,規則1檢查SSHPOOL列表中這個源IP是否有hitcount,因為是第一個包,顯而易見,列表是0,規則1判定這個數據包不必執行      DROP,並且也不處理這個數據包,將數據包轉給下條規則。
b) 規則2將這個數據包計入SSHPOOL列表,就是做+1,因為規則中有-j ACCEPT,規則2放行這個包。
c) 第1個數據包進入服務器B,不用再在iptables里轉了。
d) 當第2個SSH包到達服務器B,規則1檢查SSHPOOL列表的hitcount,發現是1沒有超過5,於是判定不執行DROP並轉給下條規則處理。
e) 規則2在SSHPOOL中+1,並放行,第2個數據包進入服務器B。
f) 第3、4、5個包同上。
g) 第6個包到達服務器B,規則1檢查SSHPOOL列表中的hitcount,發現是5了已經連接5次了,於是規則2執行DROP,不必再轉給下條規則了丟棄該包。
h) 第7、8…個包同上。

實際上recent的處理更為復雜, 從上面的流程可以看出,--set的功能在於計錄數據包,將源IP加入列表。--rcheck(update)的功能在於判定數據包在seconds和hitcount條件下是否要DROP。

如果采用下面的配置, 則必須在INPUT鏈的默認策略為ACCEPT的情況下才能生效並使用, 否則(即INPUT鏈的默認策略為DROP)所有的SSH包都被丟棄了!!!!

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT                            //必須添加這個前提條件才能生效!
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP

這個命令與上面命令的區別在於:set句在前,且set句不帶-j ACCEPT。這導致數據包的流程也不同。
a) 第1個數據包到達規則1后馬上計入SSHPOOL列表,並且規則1因為沒有-j ACCEPT,直接將數據包轉給下條規則。規則2拿到這個數據包后檢查SSHPOOL列表,發現是1,也  不處理這個包,轉給下條規則。如果后續的規則都沒有再處理這個數據包,則最后由INPUT鏈的默認策略ACCEPT處理。由於上面的策略是DROP,所以丟棄該包,於是這兩行命令在我的服務器上不能用。
b) 這里有個問題,由於set句在前,數據包進入是先計入列表,再判定是否合法。這導致第5個包到達后,先在列表中+1,結果是5,再由規則2判定,發現是5,結果丟棄該包,    最后真正ACCEPT的只有4個包。其實個人認為這樣寫的代碼不符合正常的思維邏輯, 而且這樣寫只能正常工作於默認策略是ACCEPT的情況,所以不建議用這個版本的命令,我的版本ACCEPT、DROP策略都能用。

從上面可以看出,在使用recent模塊的命令的時候,一定要先確認iptables的INPUT鏈的默認策略是什么。

接着說下--rcheck 和 --update的區別
--rcheck從第1個包開始計算時間,--update是在rcheck的基礎上增加了從最近的DROP包開始計算阻斷時間,具有准許時間和阻斷時間,update會更新last-seen時間戳。

就拿上面那個配置案例來說, rcheck是接收到第1個數據包時開始計時,一個小時內僅限5次連接,后續的包丟棄,直到一小時過后又可以繼續連接。update則是接收到第1個數據包時計算准許時間,在一個小時的准許時間內僅限5次連接,當有包被丟棄時,從最近的丟棄包開始計算阻斷時間,在一個小時的阻斷時間內沒有接收到包,才可以繼續連接。所以rcheck類似令牌桶,一小時給你5次,用完了抱歉等下個小時吧。update類似網銀,連續輸錯5次密碼,停止一小時,只不過update更嚴格,阻斷時間是從最近的一次輸錯時間開始算,比如輸錯了5次,過了半個小時又輸錯一次,這時阻斷時間不是剩半小時,而是從第6次重新計算,剩一小時. 

可以拿下面這個命令進行測試, 自行替換rcheck、update,然后ping一下就明白了:

-A INPUT -p icmp -m recent --name PINGPOOL --rcheck --seconds 30 --hitcount 5 -j DROP
-A INPUT -p icmp -m recent --name PINGPOOL --set -j ACCEPT
 
-A INPUT -p icmp -m recent --name PINGPOOL --update --seconds 30 --hitcount 5 -j DROP
-A INPUT -p icmp -m recent --name PINGPOOL --set -j ACCEPT

溫馨提示:
ICMP包和UDP包在iptables中的state情況是一樣的,因為是無狀態的,不同於TCP,iptables可以靠SYN等flags確定state,而iptables是基於ICMP包/UDP包到達服務器的間隔時間來確定state的。比如在做上面測試的時候,使用ping 192.168.10.10 -t時,除了第一個ICMP包state是NEW,后續的包state都是ESTABLISHED,結果因為前面有一句:

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

結果測試ping一直是通的,這個一定要弄明白!

3) 限制80端口60秒內每個IP只能發起10個新連接,超過記錄日記及丟失數據包,可防CC及非偽造IP的syn flood

iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --rcheck --seconds 60 --hitcount 10 -j LOG --log-prefix 'DDOS:' --log-ip-options
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --rcheck --seconds 60 --hitcount 10 -j DROP
iptables -A INPUT -p tcp --dport 80 --syn -m recent --name webpool --set -j ACCEPT

以上命令解說
第1行規則表示: 60秒10個新連接,超過記錄日志。
第2行規則表示: 60秒10個新連接,超過記錄日志。
第3行規則表示: 范圍內允許通過。
即每個IP目標端口為80的新連接會記錄在案,可在/proc/net/xt_recent/目錄內查看,rcheck檢查此IP是否在案及請求次數,如果超過規則就丟棄數據包,否則進入下條規則並更新列表信息。

發送特定指定執行相應操作,按上面設置, 如果自己IP被阻止了,可設置解鎖。

iptables -A INPUT -p tcp --dport 5000 --syn -j LOG --log-prefix "WEBOPEN: "
#記錄日志,前綴WEBOPEN:
iptables -A INPUT -p tcp --dport 5000 --syn -m recent --remove --name webpool --rsource -j REJECT --reject-with tcp-reset
#符合規則即刪除webpool列表內的本IP記錄

4)  默認封閉SSH端口,為您的SSH服務器設置開門暗語

iptables -A INPUT -p tcp --dport 50001 --syn -j LOG --log-prefix "SSHOPEN: "
#記錄日志,前綴SSHOPEN:
iptables -A INPUT -p tcp --dport 50001 --syn -m recent --set --name sshopen --rsource -j REJECT --reject-with tcp-reset
#目標端口tcp 50001的新數據設定列表為sshopen返回TCP重置,並記錄源地址。
iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT
#開啟SSH端口,15秒內允許記錄的源地址登錄SSH。
 
#開門鑰匙
nc host 50001 
telnet host 50001
nmap -sS host 50001

5) 指定端口容易被破解密鑰,可以使用ping指定數據包大小為開門鑰匙

iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -j LOG --log-prefix "SSHOPEN: "
#記錄日志,前綴SSHOPEN:
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -m recent --set --name sshopen --rsource -j ACCEPT
#指定數據包78字節,包含IP頭部20字節,ICMP頭部8字節。
iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT

安裝上面配置后, 依然無法ssh登錄到指定主機, 因為沒有添加"INPUT鏈的默認策略為ACCEPT"的前提, 即需要下面這個前提條件!

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

整理后的配置規則

iptables -F
iptables -X
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -j LOG --log-prefix 'SSH_OPEN_KEY'
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -m recent --name openssh --set --rsource -j ACCEPT
iptables -A INPUT -p tcp --dport 22 --syn -m state --name openssh --rcheck --seconds 60 --rsource -j ACCEPT
iptables -P INPUT DROP
針對上面整理后的配置規則說明
第1,2行規則表示: 清空原有的iptables規則
第3行規則表示: 已經建立成功的連接和與主機發送出去的包相關的數據包都接受,如果沒有這一步,后面的tcp連接無法建立起來
第4行規則表示: 出現長度為78字節icmp回響包在 /var/log/syslog 生成log,log以SSH_OPEN_KEY開頭
第5行規則表示: 出現長度為78字節icmp回響包,將源地址信息記錄在openssh文件中,並接受
第6行規則表示: 對於openssh文件中的源地址60s以內發送的 ssh 連接SYN請求予以接受
第7行規則表示: 將INPUT鏈的默認策略設置為drop

調試過程:
a) 如果沒有設置第3行規則,則無法建立ssh連接
b) 在沒有第3行規則的情況下,設置第6行如果不加--syn,則可以ssh連接一會兒,過一會兒又自動斷線,除非ping一下目的地址.
原理是:ping目的地址,則會更新openssh的時間,這樣ssh連接還在60s之內,所以可以通信,過一會兒,60s超時,則就會斷開ssh連接。如果加了--syn,只能進行開始的syn,無法正常連接

在客戶機上,如果需要ssh到主機,需要先ping主機進行解鎖

ping -s 50 ip    #linux主機的ip
ping -l 50 ip     #windows主機的ip

並在一分鍾之內ssh到主機,這樣在/proc/net/xt_recent/目錄下生成openssh文件, 內容如下:

src=192.168.10.10
ttl: 53
last_seen: 42963x6778
oldest_pkt: 1 4296376778, 4295806644, 4295806895, 4295807146, 4295826619, 4295826870, 4295827122, 4295827372, 4295833120, 4295833369, 4295834525, 4295834777, 4295872016, 4295872267, 4295872519, 4295872769, 4295889154, 4295889406, 4295889658, 4295889910


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM