最近遇到一個問題:服務器被全球的IP頻繁試圖通過ssh登錄。
於是想到通過iptables防火牆限制訪問,達到:僅允許指定ip段訪問ssh服務(22端口)。
關於iptables添加規則的文章有很多,而鮮有介紹規則之間的順序。因此希望通過這篇文章介紹iptables多條規則之間是如何協同工作的。
注:作者並沒有在此投入很多時間調研,因而以下僅僅是個人理解,有錯誤之處希望不吝指出。
假設希望僅僅允許 111.111.0.0/16 IP段ssh登錄,而禁止其他所有ip登錄。
最簡單的命令是:
iptables -I INPUT -p tcp --dport 22 -j DROP
iptables -I INPUT -s 111.111.0.0/16 -p tcp --dport 22 -j ACCEPT
第一句 禁止了所有對22端口的入訪問,第二句允許111.111.0.0/16的訪問。
這兩句命令的關鍵在於 “-I” 選項,這個選項表示將當前規則插入到第一條,因此上面兩條執行完之后,新增的兩條規則是(用iptables -L 列出所有規則):
ACCEPT tcp -- 111.111.0.0/16 anywhere tcp dpt:ssh
DROP tcp -- anywhere anywhere tcp dpt:ssh
當有新鏈接請求時,iptables就使用這些規則:
首先查看第一條:ACCEPT tcp -- 111.111.0.0/16 anywhere tcp dpt:ssh
如果這個ip在地址段里,那么允許。如果不在,才查看下一條規則:
DROP tcp -- anywhere anywhere tcp dpt:ssh
也就是禁止訪問。
這樣就實現了最初設定的目標。
這兩條命令存在一個問題,當用戶以 ssh登錄身份執行時,執行了第一條:iptables -I INPUT -p tcp --dport 22 -j DROP
后,這條命令被置頂了,從而此時等價實現了“禁止一切ssh”,然后用戶就被斷開連接了。。。。悲劇
所以更安全的命令應該如下:
iptables -I INPUT -s 111.111.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I INPUT 2 -p tcp --dport 22 -j DROP
即先執行允許訪問,再顯式的將禁止訪問放在第二條。
通過以上簡單分析可以得出:
iptables對新鏈接一條一條的查看,直到得出允許/禁止結論,如果在前一條就得出了結論,那么后面的規則都不會起作用。