Medidas extremas para asegurar el servidor de correo

Nota: Este post pertenece a una saga de configuración de correo, para entenderlo debes ir primero a la página de índice en saga de servidores de correo.

Entrando en modo paranoia, además de la configuración del ratelimit suelo añadir algunas medidas de seguridad extra en los servidores de correo. Principalmente los realizo para evitar volver a caer en los listados RBL, prefiero bloquear el correo y mirar que ocurre cuando se superen ciertos límites.

Firewall

Esta es sencilla, solo el usuario Debia-exim puede enviar paquetes por el puerto 25. Evito que otros procesos locales se conecten a puertos 25 de máquinas externas, principalmente los PHP hackeados.

iptables -A OUTPUT -p tcp --dport 25 -m owner --uid-owner Debian-exim -j ACCEPT
iptables -A OUTPUT -p tcp --dport 25 -j DROP

Bloqueador en python del puerto 25

Tengo un script en el cron que analiza las estadísticas de exim y cuando se superan N correos envíados por smtp diarios bloque el puerto 25. El script muestra en la salida un aviso si hace el bloqueo y al ejecutarse desde el cron la salida se envía por correo a root.

¡Cuidado si tienes un .forward en root, la cuenta destino debe estar en la propia máquina ya que se ha bloqueado el puerto 25!

En /etc/cron.d/ creo un archivo nuevo con mi entrada de cron, por ejemplo /etc/cron.d/antispam

# Comprobar correos enviados para cerrar el puerto 25
# Cada 15 minutos comprobar el numero de correos enviados
5,20,35,50 * * * * root /root/bin/correo-check-exim.py

El script «/root/bin/correo-check-exim.py» es un poco salvaje ya que llama a exim-stats y busca la línea donde se cuentan los correos enviados, lo pego ya que no es muy grande

#!/usr/bin/python
# -*- coding: utf-8 -*-
# V6: Cambio en iptables
import os
import sys
import subprocess
import time
import re

VERSION=6

LIMIT=250  # Limite maximo diario de corres enviados 200 recomendado
EXIM_LOG="/var/log/exim4/mainlog"
CMD="/usr/sbin/eximstats"
RUN="/sbin/iptables -I OUTPUT 1 -p tcp --dport 25 -j DROP" # Se añade en primera posicion

comando=CMD + " " + EXIM_LOG

def cierraPuerto():
  line=os.popen('/sbin/iptables -L OUTPUT | egrep "DROP.*tcp.*dpt:smtp" | wc -l ').read()
  res=int(line)
  if res >= 2 :
    print "Puerto ya bloqueado"
  else:
    print "Bloqueado correo saliente !!"
    os.system(RUN)
 


sb=None
try:
 sb = subprocess.Popen(comando,
   stdin = subprocess.PIPE,
   stdout = subprocess.PIPE,
   stderr =  subprocess.PIPE,
   shell=True)
except:
 pass

if sb==None:
 print "** Error: no se ha podido ejecutar el comando '%s'" % comando
 exit(255);

while sb:
 res=sb.poll()
 if res==None:
   #print "Todavia corriendo"
   time.sleep(1)
 else:
   break

 std,err = sb.communicate()
 lines=std.split("\n")
 line=""
 #print "Lineas %s" % len(lines)
 for l in lines:
   if l.find(" remote_smtp ") > 0:
     line=l;
     break

if len(lines)<2 or lines[1][0:15]!="Exim statistics":
  # Comando error no se han enviado correos todavia
  print "** Error fallo el comando "
  print "** Salida del comando:\n",lines
  exit(255)

if line!="":
  #print line
  match_o = re.search( r'([0-9]+$)', line)
  if not match_o:
    print "** Error, no se encuentra el numero de correos enviados en la linea'%s'" % line
  else:
    send=int(match_o.group(0))
    if send > LIMIT:
      cierraPuerto()

paulino

paulino escribió 18 entradas

Navegación de la entrada


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puede usar las siguientes etiquetas y atributos HTML:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>