Tengo numerosas directivas Postfix que limitan con éxito el abuso.SIN EMBARGO: Después de que se aplica una restricción, el abusador simplemente se vuelve a conectar y pasa por el proceso completo de volver a fallar las mismas pruebas. No hay persistencia de la memoria con respecto a las restricciones anteriores que haya aplicado un cliente que se conecta.
¿Existe alguna solución para cortocircuitar este bucle e ir directamente a un bloque después de que se haya aplicado una directiva costosa en recursos solo una vez? Idealmente, me gustaría recibir soporte para incluir en la lista negra direcciones IPv4/IPv6.
Respuesta1
ACTUALIZAR:
Realicé una actualización material de la solución y agregué soporte y mantenimiento de IPv6 para implementar una lista de bloqueo "continua" para eliminar las IP después de que los infractores dejen de acceder a su servidor.
Introducción:
Aunque hay muchas directivas Postfix que pueden bloquear a los abusadores, el problema con ellas es que no hay persistencia en la memoria de dichas decisiones anteriores.Por lo tanto, un abusador puede volver a conectarse sin cesar y su tráfico tiene que volver a fallar en las mismas pruebas. Por lo tanto, el objetivo final es romper este ciclo interminable de abuso y simplemente prohibir una IP infractora después de que la primera prueba que requiere muchos recursos haya fallado.
Heuna solución de código abiertoEjecuto mi propio servidor de correo (algo) ocupado que aloja muchas cuentas para muchos dominios. En pocas palabras, crea un temporizador y servicio SystemD que activa un script que utiliza expresiones regulares para detectar /var/log/maillog
patrones de abuso, tanto para direcciones IPv4 como IPv6. Hasta ahora, las pruebas han tenido éxito y han reducido sustancialmente el abuso.
Salida de muestra de /etc/postfix/access
. No la inclusión de una única dirección 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
Por cierto, lograr que IPv6 funcionara con esto fue un poco complicado, pero al final lo logré ;-)
Estrategia de lista negra:
En 2,5 meses tenía más de 1200 IP en la lista negrausando la iteración anterior de mi repositorio que registraba persistentemente las IP de los infractores. Sin un mecanismo para podar periódicamente esta lista, habría problemas de escalabilidad. Mi nuevo enfoque es crear una lista de bloqueo continua: buscar continuamente en el registro de correo nuevas IP de abusadores y eliminar aquellas que ya no aparecen en el registro de correo.Cualquier otro enfoque que se me ocurrió se basó en una cantidad de tiempo arbitraria para purgar las IP.
Entonces, después de una rotación de registro, si un abusador no aparece en el nuevo registro de correo, NO será incluido en la lista negra, solo si realiza un intento de abuso posterior. Las IP están en la lista negra solo durante la vida del registro de correo antes de una rotación.
Código
Puedo decir que el repositorio hace lo que dice en la lata de mis pruebas. Sin embargo, no dudo que algunas partes podrían ser más elegantes. A continuación se muestra el guión principal que hace el negocio y se ofrece para revisión por pares.
Si tiene alguna idea o sugerencia, escuchémosla o, mejor aún, envíeme una solicitud de extracción (solo después de haber probado sus mejoras). El guión es fácil de probar.hace todo por ti y todo el código está bien comentado- e igualmente fácil de relajarse.
TENGA EN CUENTA: Este script sólo tiene efecto si tiene directivas que leen el mapa de "acceso" en main.cf
.También tenga en cuenta que las directivas restrictivas de Postfix se aplican de izquierda a derecha., por lo que cualquier directiva que lea el mapa de "acceso" debe dejarse de directivas que ejecutan pruebas más costosas.
El repositorio incluye un script para desinstalar todo si solo deseas realizar algunas pruebas.
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
Conclusión:
Creo que he llegado como un sistema para mantener la persistencia de la memoria sobre IP previamente bloqueadas para evitar que se repitan pruebas costosas sin cesar. ¿Es perfecto? Probablemente le vendría bien un poco de pulido, pero los resultados parecen prometedores según mis pruebas hasta ahora.
Si está harto de que los spammers abusen interminablemente de su(s) servidor(es) de correo, esta es una solución rápida y fácil de implementar para cerrarlos lo antes posible: