У меня есть множество директив Postfix, которые успешно ограничивают злоупотребления.ОДНАКО: После того, как ограничение введено, нарушитель просто подключается заново и проходит через полный процесс повторного провала тех же тестов. Нет никакого сохранения памяти относительно предыдущих ограничений, которые подключающийся клиент имел введенными.
Есть ли решение, чтобы сократить этот цикл и перейти сразу к блоку после того, как ресурсоемкая директива была применена всего один раз? В идеале я хотел бы иметь поддержку для внесения в черный список адресов IPv4 / IPv6-
решение1
ОБНОВЛЯТЬ:
Я внес существенные изменения в решение и добавил поддержку IPv6, а также средства для реализации «скользящего» списка блокировки с целью удаления IP-адресов после того, как злоумышленники перестанут атаковать ваш сервер.
Вступление:
Хотя существует множество директив Postfix, которые могут блокировать злоумышленников, проблема в том, что они не сохраняют память о таких предыдущих решениях.Таким образом, злоумышленник может бесконечно переподключаться, и его трафик должен снова проваливаться теми же тестами. Конечная цель, таким образом, состоит в том, чтобы разорвать этот бесконечный цикл злоупотреблений и просто забанить нарушающий IP после того, как первый ресурсоемкий тест провалится.
Я имеюрешение с открытым исходным кодомЯ работаю на своем собственном (довольно) загруженном почтовом сервере, на котором размещено много учетных записей для многих доменов. В двух словах, он создает SystemD Service & Timer, который запускает скрипт, использующий RegExs для сбора /var/log/maillog
шаблонов злоупотреблений — как для адресов IPv4, так и для 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-адреса заносятся в черный список только на время существования почтового журнала до ротации.
Код
Могу сказать, что репозиторий делает то, что заявлено на упаковке, по результатам моего тестирования. Однако я не сомневаюсь, что некоторые части могли бы быть более элегантными. Ниже представлен основной скрипт, который делает свое дело и предлагается для рецензирования.
Если у вас есть какие-либо мысли/предложения, давайте выслушаем их или, что еще лучше, отправьте мне запрос на включение (пожалуйста, только после того, как вы протестируете свои улучшения). Скрипт легко тестировать-он делает все за вас, и весь код хорошо прокомментирован- и так же легко расслабиться.
ПОЖАЛУЙСТА, ОБРАТИ ВНИМАНИЕ: Этот скрипт имеет эффект только в том случае, если у вас есть директивы, которые считывают карту «доступа» в 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-адресах, чтобы остановить бесконечное повторение дорогостоящих тестов. Идеально ли это? Возможно, не помешала бы некоторая полировка, но результаты моих тестов пока кажутся многообещающими.
Если вам надоело, что ваш почтовый сервер(ы) постоянно подвергается атакам со стороны спамеров, вот быстрое и простое решение, которое позволит отключить их при первой же возможности: