Postfix 中的自動黑名單

Postfix 中的自動黑名單

我有許多 Postfix 指令,它們成功地限制了濫用。然而:實施限制後,濫用者只需重新連結並經歷重新失敗相同測試的完整過程。對於連接客戶端之前強制執行的限制,不存在持久性記憶體。

在執行一次資源昂貴的指令後,是否有任何解決方案可以短路此循環並直接進入區塊?理想情況下,我希望支援將 IPv4 / IPv6 位址列入黑名單 -

答案1

更新:

我對該解決方案進行了重大更新,並添加了 IPv6 支援和內務管理,以實現「滾動」阻止列表,以便在犯罪者停止訪問您的伺服器後修剪 IP。

介紹:

儘管有許多 Postfix 指令可以阻止濫用者,但這些指令的問題是沒有持久儲存此類先前決定的記憶。因此,濫用者可以無休止地重新連接,並且他們的流量必須通過相同的測試重新失敗。因此,最終目標是打破這種無休止的濫用循環,並在第一次資源密集型測試失敗後禁止違規 IP。

我有開源了一個解決方案我在自己的(有點)繁忙的郵件伺服器上運行,該伺服器託管許多網域的許多帳戶。簡而言之,它創建了一個 SystemD 服務和計時器,它觸發一個腳本,該腳本使用 RegEx 來抓取/var/log/maillogIPv4 和 IPv6 位址的濫用模式。迄今為止,測試已成功地大大減少了濫用行為。

樣本輸出來自/etc/postfix/access.不包含單一 IPv6 位址:

213.230.115.33 REJECT
213.230.75.114 REJECT
185.66.252.78 REJECT
162.243.133.39 REJECT
104.168.159.38 REJECT
78.128.113.109 REJECT
77.40.3.227 REJECT
77.40.3.101 REJECT
61.163.192.88 REJECT
37.0.20.10 REJECT
26.189.237.221 REJECT
[2001:da8:5066:66:eda:41ff:fe1d:b27] REJECT

順便說一句,讓 IPv6 來處理這個問題有點麻煩,但我最終做到了;-)

黑名單策略:

在 2.5 個月內,我將大約 1200 多個 IP 列入黑名單使用我的儲存庫的上一個版本,該版本持續記錄了犯罪者 IP。如果沒有定期修剪此清單的機制,就會出現可擴展性問題。我的新方法是建立一個滾動封鎖清單:不斷抓取郵件日誌以尋找新的濫用者 IP,並刪除那些不再出現在郵件日誌中的 IP。我能想到的任何其他方法都是基於任意時間來清除 IP。

因此,在日誌輪替之後,如果濫用者沒有出現在新郵件日誌中,則只有當他們進行後續濫用嘗試時,他們才不會被包含在黑名單中。只有在輪調之前的郵件日誌生命週期內,IP 才會被列入黑名單。

程式碼

我可以說,根據我的測試,該存儲庫按照其說明進行操作。然而,我毫不懷疑某些部分可以更優雅。以下是執行業務並提供同儕審查的主要腳本。

如果您有任何想法/建議,請讓我們聽聽,或最好還是向我發送拉取請求(請僅在您測試了增強功能之後)。該腳本很容易測試 -它為你做了一切,並且所有程式碼都有很好的註釋- 且同樣容易放鬆。

請注意:此腳本僅在您具有讀取 中的「存取」對應的指令時才有效main.cf另請注意,Postfix 的限制性指令是從左到右強制執行的,因此任何讀取“訪問”映射的指令都應該位於運行更昂貴的測試的指令的左側。

如果您只想進行一些測試,該儲存庫包含一個用於卸載所有內容的腳本。

cat <<'EOF'> /etc/postfix/access-autoBlacklisting.sh
#!/bin/bash
#
# Author/Developer: Terrence Houlahan Linux Engineer F1Linux.com
# Linkedin: https://www.linkedin.com/in/terrencehoulahan
# License: GPL 3.0
# Source:  https://github.com/f1linux/postfix-autoBlacklisting.git
# Version: 03.20.00

# OPERATION:
# ----------
# This script PREPENDS offending IP addresses from "/var/log/maillog" to "/etc/postfix/access"
# This ensures restrictive access rules applied before permissive grants.
# Consult README.md file for more granular detail about this script and its operation.

# Stop timer from executing Blacklisting script: Existing blacklist in /etc/postfix/access is enforce enforced while the new blacklist rebuilds
systemctl stop Postfix-AutoBlacklisting.timer

# Purge blacklist: Blacklist recreated each script execution capturing both previous offending IPs as well as newest ones present in logs
sed -i '/REJECT$/d' /etc/postfix/access

# Purge the scratch file:
> /etc/postfix/access-blacklist

### Scrape log for different forms of abuse using different tests to identify abuse IPs and squirt each to same central file:
# Enable/Disable any of below tests according to your requirements. Adding your own is easy if you use my tests which isolate offending IPs as templates.

# TEST 1: Blacklist Zombie hosts from endlessly squirting spam: These are identified by no PTR record being set for them.
# This test will catch both new zombies as well as those already RBLed which should serve to stop them constantly being endlessly checked against the RBL
# IPv4 Test:
# Below commented test was found to not be 100 perecent as accurate as the one using the awk form. Have not investigated why however.
#grep "does not resolve to address" /var/log/maillog | grep -Eo "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | sort -u >> /etc/postfix/access-blacklist
grep "does not resolve to address" /var/log/maillog | awk 'match($0, /([0-9]{1,3}[\.]){3}[0-9]{1,3}/) {print substr($0, RSTART, RLENGTH)}' | sort -u >> /etc/postfix/access-blacklist
# IPv6 Test:
grep "does not resolve to address" /var/log/maillog | grep -Eo "2[0-9a-fA-F]{3}:(([0-9a-fA-F]{1,4}[:]{1,2}){1,6}[0-9a-fA-F]{1,4})" | sort -u | awk '{print "["$1"]"}' >> /etc/postfix/access-blacklist


# TEST 2: Block spammers guessing account names where they know our domain:
# WARNING: this could potentially cause a block where an unintentional misspelling of an mail account name occured.
# Uncomment only if you are OK with accepting such a risk:
# IPv4 Test:
#grep "Recipient address rejected: User unknown in virtual mailbox table" /var/log/maillog | sed -rn 's/.*\[(([0-9]{,3}.){4})\].*/\1/gp' >> /etc/postfix/access-blacklist
# IPv6 Test:
#grep "Recipient address rejected: User unknown in virtual mailbox table" /var/log/maillog | grep -Eo "2[0-9a-fA-F]{3}:(([0-9a-fA-F]{1,4}[:]{1,2}){1,6}[0-9a-fA-F]{1,4})" | sort -u | awk '{print "["$1"]"}' >> /etc/postfix/access-blacklist


# Populate an array with sorted and depuplicated list of offending IPs scraped from maillog using foregoing tests:
readarray arrayIPblacklist < <( cat /etc/postfix/access-blacklist | sort -u -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | sed '/^$/d' )

# If "access" is a new empty file then the subsequent "sed" will fail. Any new file will have a zero size so the '-s' test will not equal 'true'.
# So we use negation to test "true" and echo a blank space to file. The subsequent "sed" will now execute.
# If "access" file already has whitelist entry then the 'if' statement does nothing and "sed" which follows executes as expected for a non-empty file:
if [ ! -s /etc/postfix/access ]; then echo "" > /etc/postfix/access; fi

for i in "${arrayIPblacklist[@]}"; do
        # Write list of IPS from array to TOP of "access" file to enforce restrictions BEFORE processing whitelisted "OK" addresses:
        sed -i "1i $i" /etc/postfix/access
        # Append " REJECT" (with a space prepended in front of it) after each of the IPs added to to the "access" file:
        sed -i '1s/$/ REJECT/' /etc/postfix/access
done


# Rebuild the /etc/postfix/access Berkeley DB:
postmap /etc/postfix/access

systemctl reload postfix.service

# After cycle completes and IPs written to /etc/postfix/acces we wipe array which repopulates anew upon next script execution:
unset arrayIPblacklist

systemctl start Postfix-AutoBlacklisting.timer

EOF

結論:

我相信我已經作為某個系統來維護先前被阻止的 IP 的持久性內存,以阻止無休止地重複昂貴的測試。完美嗎?可能還需要一些改進,但從我迄今為止的測試來看,結果似乎很有希望。

如果您厭倦了您的郵件伺服器被垃圾郵件發送者無休止地濫用,這是一個快速且簡單的解決方案,可以儘早將其關閉:

https://github.com/f1linux/postfix-autoBlacklisting

相關內容