31 de Mayo, 2008

Fenómenos extraños con stunnel y POP3s (¿y ONO?)

First bug ever

En este servidor tengo un servicio de POP3s (ese que me obliga a actualizar el certificado cada año :D), que no es más que el protocolo POP3 transportado en una capa SSL (Secure Socket Layer), que cifra todo el tráfico entre cliente y servidor de forma que la comunicación es bastante segura.

Mi elección de sistema operativo libre para este servidor es OpenBSD, que viene con un servidor POP3 bastante sencillo e integrado en el sistema: popa3d.

La única pega es que solo soporta la autenticación con LOGIN, que básicamente pide usuario y contraseña en texto plano, lo cual no es demasiado adecuado para recoger el correo por Internet. No implementan otros mecanismos, como APOP o CRAM-MD5, argumentando que la transferencia de los correos seguiría haciéndose de forma insegura (sin cifrar).

Tampoco es un problema insalvable, porque podemos utilizar stunnel para añadir esa capa SSL y obtener con el conjunto un servidor seguro bastante resultón :).

stunnel tiene dos ramas diferenciadas: la 3 (bien documentada, incluso tengo publicada una receta sobre POP3s y OpenBSD), y la 4 (completamente nueva, y sin mucha documentación).

Llevo mucho tiempo con problemas, pero lo achacaba al cambio a la rama 4, hasta que el fin de semana pasado empeoró todo y tuve que arreglarlo, aprendiendo mucho por el camino :). ¿Es posible que el responsable fuera mi ISP?

Probé lo más evidente (revisar el cortafuegos, incluso apagarlo), y recogí toda la información que pude y me apunté a la lista de usuarios de stunnel para buscar ayuda o pistas que me permitieran resolver el problema.

Mi configuración era bastante estándar, y nada más arrancar la máquina todo funcionaba perfectamente, pero pasadas unas horas nos encontrábamos con que, cuando se establecía la comunicación, en un punto temprano de la negociación inicial de SSL el proceso se detenía durante unos 3 minutos, para luego continuar normalmente :o.

Corriendo stunnel en modo debug me encontraba con que el parón de los 3 minutos sucedía en:

2008.05.23 10:47:29 LOG7[16334:0]: SSL state (accept): before/accept initialization

No había ningún log en el sistema que indicara ningún problema de ningún tipo, ni relacionado ni todo lo contrario.

Entonces compilé stunnel en modo debug, y haciendo un gdb attach pid pude observar, con el comando bt, la linea donde se quedaba esperando stunnel:

#0  0x0193571d in poll () from /usr/lib/libc.so.38.2
#1  0x1c00ac84 in s_poll_wait (fds=0x8964b310, sec=300, msec=0) at
stunnel-4.24/src/network.c:271
#2  0x1c00453c in init_ssl (c=0x89643000) at
stunnel-4.24/src/client.c:349
#3  0x1c00410d in do_client (c=0x89643000) at
stunnel-4.24/src/client.c:202
...

En una llamada a poll(2), que mira si en un fichero hay datos para leer o escribir.

Verifiqué en gdb que se llamaba a la función con los parámetros correctos, revisé el código de stunnel, probé a compilar stunnel para que usara el viejo select(2) en lugar de poll: nada. poll se bloqueaba esperando leer datos, porque no habían datos para leer (y el tiempo máximo de espera eran 300 segundos, un valor normal en estos casos).

En este punto decicí obtener más información desde la parte del cliente. Había probado desde dos conexiones distintas, con proveedores diferentes, pero siempre con Evolution como cliente y sin muchos detalles (otros usuarios de blackshell usan otros clientes, y tenían el mismo problema).

En OpenSSL hay un comando que no conocía y que es muy útil para estos casos: s_client.

Básicamente se utiliza como cliente para depurar fallos en los servidores que utilizan SSL, así que era la herramienta que necesitaba. Ejecuté:

$ openssl s_client -connect blackshell.usebox.net:995 -msg -state

Pudiendo comprobar que había una comunicación inicial (siempre 178 bytes), pero se quedaba el cliente escribiendo lo que esperaba leer el servidor... durante esos 3 minutos :o.

En este punto todo tenía pinta de ser un problema de red, y mirando netstat(8) pude comprobar que el servidor no tenía bytes esperando en la cola de recepción, por lo que ¡poll estaba esperando correctamente!

Entonces es cuando empiezo a pensar que la conexión del servidor es una linea residencial de ONO, que tienen fama (no sé si merecida) de quitar prioridad al P2P, que mucha gente usa P2P con cifrado y en puertos estándar para engañar a ONO...

Cambié el puerto de POP3s a un puerto no estándar, y todo funcionó como la seda. Subjetivamente creo que la negociación ahora se realiza incluso más rápido que cuando todo va bien en el puerto estándar :o.

Así que no sé qué ha pasado, pero llevo ya una semana felizmente usando otro puerto, y ¡sin ningún problema!

Lo que tampoco sé es si echarle la culpa a ONO, con lo que si alguien tiene otra explicación razonable con los datos que he propocionado, le agradecería un comentario en esta anotación :D.

Anotación por Juan J. Martínez, clasificada en: security, unix, internet, networking.

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: