Open Relay Tester
Después de una semanita de vacaciones vuelvo al trabajo y a los posts.

En esta entrega les traigo una herramienta de desarrollé hace un par de meses para testear servidores SMTP y verificar si son Open Relay. Un servidor de mails es Open Relay si permite a cualquier usuario enviar e-mails sin previa autenticación, esto es, no hace falta ninguna credencial para poder enviar e-mails. Pueden encontrar un ejemplo sobre el uso (o abuso) de un servidor open relay en el post Dando pelea al SPAM: Sender Policy Framework (SPF), donde explico como es posible conectarnos a un servidor SMTP utilizando telnet y enviar e-mails.

La cuestión es que tener servidores Open Relay es feo feo, porque cualquier persona/programa los puede utilizar para enviar e-mails a nombre nuestro. Osea, alguien se podría conectar al servidor de empresa.com y enviar e-mails @empresa.com. El uso común de los Open Relay es enviar SPAM. El spammer se conecta a nuestro servidor y envia e-mails de forma masiva a cualquier parte, y todo a nombre de nuestro dominio emrpesa.com.
Algunas de las consecuencias de este problema es que usan nuestro ancho de banda, llenan nuestros logs, usan nuestro procesador, y lo peor de todo, es que ensucian nuestro nombre. Si nuestro dominio es conocido como spammer, distintos servicios nos listarán en sus listas negras, rebotando nuestros e-mails por ser considerados SPAM (aún en los casos que no es spam).
Obviamente todo esto es malo, y necesitamos hacer algo al respecto. Un punto de partida es revisar si nuestros servidores son Open Relay y configurarlos para que dejen de serlo. Es por eso que escribí este programa, para identificar aquellos servidores con este problema.

El programa está escrito en python y es muy simple. Uno puede indicarle la dirección del servidor a testear, o bien un archivo con una lista de servidores. Además debemos indicar qué dirección de e-mail utilizar para realizar las pruebas. El programa testea el/los servidores con algunas combinaciones de la dirección de e-mail entregada y devuelve 2 archivos: error.log donde se listan los errores encontrados y openrelay.log donde se listan los servidores que son Open Relay.

#!/usr/bin/python
# -*- coding: utf-8 -*-

######################################################
# Created by: d3m4s1@d0v1v0
# Date: 2009-11-27
# Modified: 2009-11-30
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License v2 as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
######################################################

import os
import sys
import smtplib
from optparse import OptionParser
from time import strftime, gmtime
import socket

class smtptester:
def __init__(self):
#self.fromaddr = fromaddr
self.logfile = open("error.log", "w")
self.openrelay = open("openrelay.log", "w")
self.openrelay.write("The following configurations permits to send e-mails:\n")

def __del__(self):
self.logfile.close()
self.openrelay.close()

def set_logfile(self, logfile):
if (os.path.exists(logfile)):
self.logfile = open(logfile, "w")

def test_servers(self, filename, fromaddr, toaddr):
if(not os.path.exists(filename)):
print "file "+f+" doesn't exist!"
exit(-1)
f = open(filename)

for addr in f:
splitedaddr = addr.split(":")
if(len(splitedaddr) > 1):
port = splitedaddr[1]
else:
port = "25"
self.test_server(addr, fromaddr, toaddr, port)

def test_server(self, addr, fromaddr, toaddr, port="25"):
print "--------------------------------"
print "testing server "+addr
server_ip = socket.gethostbyname(addr)
(fromuser, fromdomain) = fromaddr.split("@")
(touser, todomain) = toaddr.split("@")

# the from addresses to test
fromlist = (fromaddr, fromuser+"@"+server_ip, "demasiadovivo@anything.com")
rcptlist = (toaddr, touser+"@"+server_ip, '"'+toaddr+'"'+"@"+server_ip, "@"+server_ip+":"+toaddr)

try:
smtp = smtplib.SMTP(addr, port)
except:
print "can't connect to server: "+str(sys.exc_info()[1])+"\n"
self.logfile.write("can't connect to server: "+str(sys.exc_info()[1])+"\n")
return

msg = ("From: d3m4s1/-\d0v1v0 <%s>\r\nTo: %s \r\nSubject: d3m4s1@d0v1v0 smtp relay test!\r\n\r\nthis is an open relay test\r\n\r\n" %(fromaddr, toaddr))

for rcpttest in rcptlist:
for fromtest in fromlist:
try:
print "testing from: "+fromtest+" to: "+rcpttest+"... ",
smtp.sendmail(fromtest, rcpttest, msg)
smtp.docmd("RSET")

self.openrelay.write("-server address="+addr+", FROM: "+fromtest+", TO: "+rcpttest+"\n")
print "[OK]"

except:
self.logfile.write("["+str(strftime("%Y-%m-%d %H:%M:%S", gmtime()))+"] the mail couldn't be send from: "+fromtest+" to: "+rcpttest+" | error: "+str(sys.exc_info()[1])+"\n")
print "[FAIL]"
smtp.quit()
print ""

# set command line options
parser = OptionParser(usage="usage: %prog <-a|-f> <address|filename> -s <sender> -r <receiver> [options]", version="%prog 0.2")
parser.add_option("-a", "--address",
metavar="SERVER", dest="server", help="server address (test a single server)")
parser.add_option("-p", "--port",
metavar="PORT", dest="port", help="server port (default 25)")
parser.add_option("-f", "--file",
metavar="FILE", dest="filename", help="file containing the address of the servers to test")
parser.add_option("-s", "--sender",
metavar="FROM", dest="sender", help="sender address (e.g. demasiadovivo@example.com)")
parser.add_option("-r", "--receiver",
metavar="RCPT", dest="receiver", help="receiver address (e.g. other@example.com)")


(options, args) = parser.parse_args()

if((not options.server) and (not options.filename)):
parser.print_help()
exit(-1)

tester = smtptester()
if(options.sender and options.receiver):
if(options.server):
tester.test_server(options.server, options.sender, options.receiver, options.port)
elif(options.filename):
tester.test_servers(options.filename, options.sender, options.receiver)
else:
parser.print_help()
else:
parser.print_help()


Un ejemplo del uso del programa es:
# ./smtp-tester.py -a 192.168.1.25 -s test@test.com -r open@empresa.com
--------------------------------
testing server 192.168.1.25
testing from: test@test.com to: open@empresa.com... [OK]
testing from: test@192.168.1.25 to: open@empresa.com... [OK]
testing from: demasiadovivo@anything.com to: open@empresa.com... [OK]
testing from: test@test.com to: test@192.168.1.25... [FAIL]
testing from: test@192.168.1.25 to: test@192.168.1.25... [FAIL]
testing from: demasiadovivo@anything.com to: test@192.168.1.25... [FAIL]
testing from: test@test.com to: "open@empresa.com"@192.168.1.25... [FAIL]
testing from: test@192.168.1.25 to: "open@empresa.com"@192.168.1.25... [FAIL]
testing from: demasiadovivo@anything.com to: "open@empresa.com"@192.168.1.25... [FAIL]
testing from: test@test.com to: @192.168.1.25:open@empresa.com... [FAIL]
testing from: test@192.168.1.25 to: @192.168.1.25:open@empresa.com... [FAIL]
testing from: demasiadovivo@anything.com to: @192.168.1.25:open@empresa.com... [FAIL]

donde se testea la posibilidad de enviar e-mails a open@empresa.com desde la cuenta test@test.com. Vale aclarar que los e-mails son realmente enviados en la prueba, osea, traten de poner como destinatario una cuenta que ustedes posean.

El programa dista de ser optimo, dado que algunas combinaciones de e-mails no son necesarias una vez que una de las pruebas anteriores falló... es algo a corregir en alguna próxima versión.
Espero que les sea de utilidad.

3 comentarios:

Zerial dijo...

Bueno, tambien agregar que los Open Relayt se caracterizan por permitir enviar correos a direcciones externas, no solo sin autentificacion.

Si te conectas a un smtp de una empresa, probalemente podras enviar mails a todos los @empresa.com pero no a @otrodmominio.com. Los open relay permiten enviar mails a cualquier destinatario.

d3m4s1@d0v1v0 dijo...

Si, obvié esa parte de la explicación. Al primero suelo llamarlo Open Relay interno, porque permite mandar mails solo a destinatarios dentro del mismo dominio.
Claro está que el segundo es mucho más problemático y preocupante.

Anónimo dijo...

El smtp de P! es Open Relay no? =X

Publicar un comentario