SMTP y TLS: cifrado y autenticación del servidor y del cliente

Introducción

Este artículo describe como usar SMTP y TLS para cifrar la comunicación entre el cliente y el servidor, incluyendo la autenticación de ambas partes. La ides es que el servidor nos autentique como usuarios validos usando certificados x509.

Configuración en el servidor (Postfix)

smtpd_tls_cert_file=/etc/postfix/tls-cert.pem
smtpd_tls_key_file=/etc/postfix/tls-key.pem
smtpd_tls_CAfile = /etc/postfix/cacert.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scache
smtpd_tls_ask_ccert = yes
smtpd_tls_loglevel = 1

smtpd_recipient_restrictions =
        permit_mynetworks
        permit_tls_clientcerts
        reject_unauth_destination

relay_clientcerts = hash:/etc/postfix/relay_clientcerts

Este es un fragmento con los parámetros de configuración que se agregaron al main.cf de Postfix. A continuación la explicacion:

  • tls-cert.pem y tls-key.pem son las claves publica y privada del SMTP servidor.
  • cacert.pem es la clave publica de la CA.
  • El certificado, la clave privada y el certificado de la CA se crearon con el script CA.sh que viene con openssl:
    1. Agregue -extensions v3_ca a la linea
      $CA -out ${CATOP}/$CACERT $CADAYS -extensions v3_ca -batch
    2. ./CA.sh -newca

      pide la passphrase y otros parámetros necesarios para el certificado.

    3. Edite el CA.sh y le agregue -nodes a la línea:
      $REQ -new -keyout newkey.pem -out newreq.pem $DAYS
    4. ./CA.sh -newreq

      para crear el request del certificado para el postfix.

    5. ./CA.sh -sign

      para firmar el request.

    6. cp newcert.pem /etc/postfix/tls-cert.pem
      cp newreq.pem /etc/postfix/tls-key.pem
    7. Pongan los permisos de tls-key.pem a 600 por seguridad.

Y listo!

Configuración de un cliente (msmtp)

Como uso Mutt+msmtp para enviar correo configure el segundo para que se valide con Postfix usando los certificados x509.

  1. Cree el certificado del lado cliente de la misma forma que lo hice del lado servidor (ver sección anterior, ./CA.sh -newreq y ./CA.sh -sign).
  2. Copie elnewcert.pem y newkey.pem como postfix-cert.pem y postfix-key.pem respectivamente al ~/.ssl/ de mi desktop.
  3. Luego configure el ~/.msmtprc con los siguientes datos:
    account example
    host mail.example.com.ar
    from diego@example.com.ar
    tls on
    tls_starttls on
    tls_certcheck off
    tls_key_file ~/.ssl/postfix-key.pem
    tls_cert_file ~/.ssl/postfix-cert.pem
    tls_trust_file ~/.ssl/cacert.pem
    
    account default: example
    

Y eso seria todo…

Post to Twitter

Compartiendo una conexión SSH

Algo útil de ssh, se puede compartir la conexión. Dicho de otra forma, nos conectamos una vez sola a un servidor y luego abrimos otras sesiones ssh usando la misma conexión.

Un ejemplo lo explica mejor:

#ssh -M -S /tmp/servidorX usuario@servidorX
... no logueamos como siempre y luego...
#ssh -S /tmp/servidorX usuario@servidorX
#ssh -S /tmp/servidorX usuario@servidorX
#ssh -S /tmp/servidorX usuario@servidorX
.
.
.

Solo para personas impacientes =)

Post to Twitter

Qué es SASL?

SASL como todo concepto abstracto no es simple de explicar. En principio es un mecanismo a través del cual los protocolos orientados a conexiones (LDAP, SMTP, IMAP) se desligan del manejo de la autenticación, la cual pasa a ser una serie de bits cuyo contenido no tiene importancia para el protocolo. El objetivo es mantener todos los mecanismos de autenticación en un lugar común a todos los protocolos, con la ventaja de eliminar redundancia de código y con la posibilidad de que se soporten nuevos mecanismos de autenticación sin tocar una linea de codigo en las implementaciones de los servicios.

Expliquemos mejor como funciona con un ejemplo concreto. Supongamos que tenemos un SMTP (Postfix) que soporta SASL a través de la librería Cyrus-SASL. A su vez esta libreria tiene los plugins para soportar los mecanismos de autenticación PLAIN y DIGEST-MD5. Veamos el comienzo de la comunicación SMTP:

S: 220 mail.ejemplo.com.ar ESMTP Postfix
C: ehlo woitasen.com.ar
S: 250-mail.ejemplo.com.ar
S: 250-PIPELINING
S: 250-SIZE 10240000
S: 250-VRFY
S: 250-ETRN
S: 250-STARTTLS
S: 250-AUTH PLAIN DIGEST-MD5
S: 250-ENHANCEDSTATUSCODES
S: 250-8BITMIME
S: 250 DSN

La C indica los mensajes enviados por el cliente y la S los enviados por el servidor.

Este es el clásico comando HELO del protocolo SMTP. Se usa para que el cliente se anuncie al servidor, el cual contesta con una serie de parámetros informativos. El mas importante ahora es el “250-AUTH”, el cual indica que el servidor soporta autenticación a través de los mecanismos PLAIN y DIGEST-MD5. En realidad, el servidor soporta SASL y es esta quien soporta esos mecanismos de autenticación.

Ahora bien, para que todo funcione el cliente tambien debe soportar SASL. Supongamos que el cliente usa Cyrus-SASL. Si la libreria tiene solo el plugin para autenticar con DIGEST-MD5, entonces se produce la siguiente secuencia de mensajes:

C: AUTH DIGEST-MD5
S: 334
   PENCeUxFREJoU0NnbmhNWitOMjNGNndAZWx3b29kLmlubm9zb2Z0LmNvbT4=
C: ZnJlZCA5ZTk1YWVlMDljNDBhZjJiODRhMGMyYjNiYmFlNzg2ZQ==
S: 235 Authentication successful.

El cliente le esta indicando al servidor que quiere autenticar con DIGEST-MD5, el servidor le contesta 334 enviando un “challenge” al cual el cliente responde. El intercambio finaliza con la confirmación de que la autenticación finalizo correctamente.

Ahora veamos como encaja SASL. EL challenge, es esa secuencia de caracteres enviados por el servidor luego del 334. Esta secuencia es generada por la librería SASL. Al servidor SMTP no le importa el contenido de este mensaje. El cliente recibe el challenge y lo procesa con su librería SASL, la cual devuelve otra secuencia de caracteres que el cliente envía al servidor. La función de SASL es generar estos mensajes y de avisarle al servidor si la autenticación finalizo correctamente o no.

Entonces, para ir cerrando, SASL se encarga del manejo de los mensajes de autenticación, siendo algo abstracto para los protocolos orientados a servicios. Si aparece un nuevo mecanismo de autenticación y la librería de SASL lo soporta, automaticamente el servicio también tendrá soporte sin tocar una linea código.

Post to Twitter

Tail calls, GCC y Linux.

Estaba mirando un post en Lwn.net que hablaba de Tail Calls y un problema con Linux, así que me puse a investigar el tema. Ésto requiere un poco de conocimiento de la ABI de Unix, que en todo caso lo resumiré en otro post, si es posible.

Tail call es una llamada a una función, que se realiza al final de la función invocante, la cual suele ser optimizada en tiempo y espacio usando el stack frame de esta. Algo asi como:

int calc(int a){
   .
   .
   .

return func(a);

}

Reservar el stack frame para func() desperdicia tiempo y espacio. Aprovechando que el de calc() ya no va a ser utilizado. GCC lo deja a disposición de func().

Esta optimización es problemática en Linux, principalmente en system calls, por lo que es evitada con un hack que básicamente mete código nulo entre el fin de la función y el tail call:

asmlinkage long sys_open(const char __user *filename, int flags, int mode)
{
        long ret;

        if (force_o_largefile())
                flags |= O_LARGEFILE;

        ret = do_sys_open(AT_FDCWD, filename, flags, mode);
        /* avoid REGPARM breakage on x86: */
        prevent_tail_call(ret);
        return ret;
}

Los system calls tienen la etiqueta asmlinkage que indica que al GCC que esa función tiene todos sus argumentos en el stack.

Post to Twitter