Tenho inúmeras diretivas Postfix que limitam o abuso com sucesso.NO ENTANTO: após a aplicação de uma restrição, o agressor simplesmente se reconecta e passa pelo processo completo de reprovação nos mesmos testes. Não há persistência de memória em relação às restrições anteriores que um cliente de conexão impôs.
Existe alguma solução para causar um curto-circuito neste loop e ir direto para um bloco depois que uma diretiva que consome muitos recursos foi aplicada apenas uma vez? Idealmente, eu gostaria de suporte para colocar na lista negra ambos os endereços IPv4/IPv6-
Responder1
ATUALIZAR:
Fiz uma atualização material na solução e adicionei suporte e manutenção IPv6 para implementar uma lista de bloqueios "contínuos" para remover IPs depois que os infratores pararem de acessar seu servidor.
Introdução:
Embora existam muitas diretivas Postfix que podem bloquear os abusadores, o problema com elas é que não há persistência de memória de tais decisões anteriores.Assim, um agressor pode se reconectar indefinidamente e seu tráfego deverá falhar novamente nos mesmos testes. O objetivo final, portanto, é quebrar esse ciclo interminável de abuso e simplesmente banir um IP ofensivo depois que o primeiro teste com uso intensivo de recursos falhar.
Eu tenhoopensource uma soluçãoEu executo meu próprio servidor de e-mail (um tanto) ocupado, que hospeda muitas contas para muitos domínios. Resumindo, ele cria um serviço e temporizador SystemD que dispara um script que usa RegExs para procurar /var/log/maillog
padrões de abuso - para endereços IPv4 e IPv6. Até agora, os testes foram bem-sucedidos, reduzindo substancialmente o abuso.
Saída de amostra do /etc/postfix/access
. Não a inclusão de um único endereço 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
Aliás, fazer com que o IPv6 funcionasse com isso foi um pouco complicado, mas no final consegui ;-)
Estratégia de lista negra:
Em 2,5 meses, tive mais de 1.200 IPs na lista negrausando a iteração anterior do meu repositório que gravou persistentemente os IPs do infrator. Sem um mecanismo para limpar periodicamente esta lista, haveria problemas de escalabilidade. Minha nova abordagem é criar uma lista contínua de bloqueios: vasculhar continuamente o maillog em busca de novos IPs de agressores e descartar aqueles que não aparecem mais no maillog.Qualquer outra abordagem que eu pudesse imaginar baseava-se em um período de tempo arbitrário para limpar IPs.
Portanto, após uma rotação de log, se um agressor não aparecer no novo maillog, ele NÃO será incluído na lista negra - somente se fizer uma tentativa de abuso subsequente. Os IPs estão na lista negra apenas durante a vida do maillog antes de uma rotação.
Código
Posso dizer que o repo faz o que diz nos meus testes. Porém, não duvido que algumas partes poderiam ser mais elegantes. Abaixo está o roteiro principal que faz o negócio e é oferecido para revisão por pares.
Se você tiver alguma opinião/sugestão, vamos ouvi-la ou, melhor ainda, envie-me uma solicitação de pull (somente depois de testar suas melhorias). O script é fácil de testar-faz tudo por você e todo o código é bem comentado- e igualmente fácil de relaxar.
OBSERVE: Este script só tem efeito se você tiver diretivas que leiam o mapa de "acesso" no main.cf
.Observe também que as diretivas restritivas do Postfix são aplicadas da esquerda para a direita, portanto, qualquer diretiva que leia o mapa de "acesso" deve ser deixada de lado nas diretivas que executam testes mais caros.
O repositório inclui um script para desinstalar tudo se você quiser apenas fazer alguns testes.
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
Conclusão:
Acredito que cheguei como um sistema para manter a persistência da memória sobre IPs bloqueados anteriormente para impedir que testes caros sejam repetidos indefinidamente. É perfeito? Provavelmente seria necessário algum polimento, mas os resultados parecem promissores em meus testes até agora.
Se você está farto do(s) seu(s) servidor(es) de e-mail serem incessantemente abusados pelos spammers, esta é uma solução rápida e fácil de implementar para desligá-los na primeira oportunidade: