
使用 Linux Debian Bookworm。
問題
我想阻止來自特定國家/地區的所有傳入連接到我的伺服器。
編輯
正如有人在評論中指出的那樣,我真的不應該使用iptables 這樣做,因為一旦它阻止的IP 位址清單增長到無法管理的大小(例如數千個IP 位址),這將使我的伺服器停止運行。相反,我應該使用ipset
(阻止整個範圍)。問題在於它取決於我需要定期下載的清單。我想要我設置過一次的東西(最好)。
那麼如何阻止來自特定國家的連線呢?來自中國和俄羅斯的流量(有時是暴力攻擊)正在失控。他們經常讓我的伺服器癱瘓。他們不遵守 robots.txt 文件,並且非常積極地抓取網站(同時有數百個、有時數千個連接)。我真的需要阻止這種情況。我的猜測是,我的伺服器處理的所有流量中 90% 以上都是惡意/格式錯誤的。
編輯2
我找到了一些在線教程(像這個)如何做到這一點,但這些教程似乎很老了。此外,它還需要下載和編譯/安裝一些模組。我擔心這可能會在未來中斷(當更新/升級其他軟體包甚至發行版時)或可能成為未來的安全風險。我使我的伺服器保持最新狀態(透過定期運行 apt-get update / apt-get Upgrade / apt-get dist-upgrade )。
原始訊息
我在網路上找到了一個腳本(簡而言之)每秒獲取已建立連接的 IP 位址列表,然後使用 geoiplookup 來獲取 IP 位址的國家。如果國家/地區位於您想要封鎖的國家/地區清單中,它會使用 iptables 將 IP 位址新增至您的防火牆過濾器。我對腳本做了一些細微的更改(使其更具可讀性,因為我對這個腳本每次封鎖 IP 位址時都會向我發送電子郵件不感興趣)。然後該腳本透過 crontab 每分鐘運行一次:
#!/bin/bash
# Script found on lautenbacher.io"
end=$((SECONDS+55))
while [ $SECONDS -lt $end ]; do
echo $SECONDS
netstat -ant | egrep ':.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > testcc.txt
sed 's/^[ t]*//' -i testcc.txt
sed '/^$/d' -i testcc.txt
while read c d; do
if [[ $c > "0" ]]; then
bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "BLR,") {print 1}}')
if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
echo "running geolookup"
echo checking ip $d
geoiplookup $d
isCloudflare=0
# The original script made an exception for CLOUDFLARE. I don't want that exception
# bGF1dGVuYmFjaGVyLmlX=$(whois $d)
# if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE "* ]]; then
# isCloudflare=1
# echo Cloudflare detected
# fi
if [[ "$isCloudflare" != 1 ]]; then
echo try to add ip $d to blocklist
sudo iptables -I INPUT -s $d -j DROP
### I would like to sever the connection here ###
fi
fi
fi
done < testcc.txt
sleep 1
:
done
順便說一句,我不知道為什麼腳本的作者使用如此奇怪的變數名稱(“bGF1dGVuYmFjaGVyLmlv”)。
無論如何,問題是每當它發現與來自被禁止國家/地區的 IP 位址的連接時,它就會運行
sudo iptables -I INPUT -s $d -j DROP
在IP位址上。這一切都很好,但大多數連接都有些持久,這意味著一秒鐘後會找到相同的 IP 位址,並再次使用 iptables 新增。我不確定會發生什麼(它會創建重複的規則嗎?),但我想在使用 iptables 添加 ipaddress 後立即刪除連接。
簡而言之:如何終止具有 IP 位址的連線?
答案1
幾年來,Linux 核心一直有一個 API 可以強制終止現有的 IP 套接字,無論其狀態為何。可以用以下方法完成ss
命令及其過濾器語法:
-K
,--kill
嘗試強行關閉套接字。此選項顯示已成功關閉的套接字,並靜默跳過核心不支援關閉的套接字。它僅支援 IPv4 和 IPv6 套接字。
您可以替換:
### I would like to sever the connection here ###
和:
ss --kill -n dst = "$d"
這篩選( dst = ...
) 是必需的,因為該指令將終止顯示的任何套接字。如果沒有過濾器,那就超出了要求。本機進程可能會在其套接字上遇到罕見的錯誤,例如ECONNABORTED
。遠端節點可能會收到 TCP RST 通知,除非也(暫時)新增了 OUTPUT 規則來阻止它。
另請參閱此問答(我在其中做出了回答):在 Ubuntu 中刪除所有 TCP 連線(已建立、相關),其中 OP 嘗試使用以下方法來防止攻擊IP集(並且還存在陳舊連線和狀態防火牆的問題)。