Módulo de correo#

Implementa un proxy de correo: Angie gestiona las conexiones de los clientes IMAP, POP3 y SMTP y, una vez que un servidor de autenticación externo acepta a un cliente y elige el backend que le corresponde, retransmite la sesión del cliente a ese backend. Los demás módulos de esta sección añaden soporte de protocolos, el intercambio con el servidor de autenticación, SSL/TLS y los ajustes del proxy.

Cuando se compila desde el código fuente, este módulo no se compila por defecto; debe habilitarse con la opción de compilación --with-mail.

En paquetes e imágenes de nuestros repositorios, el módulo está incluido en la compilación.

Cómo funciona#

Angie se sitúa entre los clientes de correo y los backends y gestiona cada sesión en cuatro pasos:

  1. El cliente se conecta a Angie, no al backend. Es Angie quien envía el saludo, responde a las consultas de capacidades, ejecuta STARTTLS y recibe las credenciales del cliente por uno de los métodos establecidos con imap_auth, pop3_auth o smtp_auth.

  2. Angie pasa las credenciales al servidor de autenticación establecido con auth_http, en las cabeceras de una solicitud HTTP. Un cliente SMTP que envía correo sin autenticarse desencadena esta solicitud tras su comando RCPT TO.

  3. El servidor de autenticación acepta o rechaza al cliente. Para aceptarlo, devuelve la dirección IP y el puerto del backend en las cabeceras de respuesta Auth-Server y Auth-Port, y además puede devolver el nombre de usuario y la contraseña para iniciar sesión en el backend.

  4. Angie abre una conexión TCP con el backend, sin TLS, e inicia sesión en nombre del cliente con el comando IMAP LOGIN o con los comandos POP3 USER y PASS. A un backend SMTP, Angie le pasa los datos del cliente con el comando XCLIENT si xclient está habilitado, como ocurre por defecto, y se autentica con AUTH PLAIN si proxy_smtp_auth está habilitado. A partir de ese momento, Angie retransmite los datos entre el cliente y el backend.

El bloque mail no tiene proxy_pass ni grupos upstream: la respuesta del servidor de autenticación es la única forma que tiene Angie de saber adónde enviar una sesión por proxy. Por eso cada server del bloque mail necesita auth_http, incluso el que acepta correo SMTP sin autenticación. Las cabeceras de solicitud y de respuesta se describen en el módulo Auth HTTP.

Ejemplo de configuración#

Una configuración mínima envía por proxy las sesiones IMAP y POP3 a un único backend en 192.0.2.10. El servidor de autenticación es un bloque location del propio Angie: acepta a todos los clientes y deja la comprobación de la contraseña al backend, lo que encaja con los métodos de autenticación de texto plano habilitados por defecto. El bloque mail va en el nivel superior de angie.conf, y los bloques map y server, dentro del bloque http existente:

mail {
    auth_http                127.0.0.1:9000/mail-auth;
    proxy_pass_error_message on;

    server {
        listen   143;
        protocol imap;
    }

    server {
        listen   110;
        protocol pop3;
    }
}

http {
    map $http_auth_protocol $mail_backend_port {
        imap 143;
        pop3 110;
    }

    server {
        listen 127.0.0.1:9000;

        location = /mail-auth {
            add_header Auth-Status OK;
            add_header Auth-Server 192.0.2.10;
            add_header Auth-Port   $mail_backend_port;

            return 204;
        }
    }
}

Como el backend comprueba la contraseña, proxy_pass_error_message está habilitado: un cliente con una contraseña incorrecta recibe la respuesta de error del backend en lugar de un error interno, y Angie cierra después la conexión. El servidor de autenticación recibe las contraseñas de los clientes sin cifrar, por lo que conviene que escuche en una dirección local o en cualquier otra de confianza.

Una configuración más completa también envía por proxy las sesiones SMTP y habilita más métodos de autenticación. Su servidor de autenticación, aquí un script CGI, tiene que comprobar por sí mismo el digest de APOP y CRAM-MD5 y devolver la contraseña del usuario en Auth-Pass, como se describe en el módulo Auth HTTP:

worker_processes auto;

error_log /var/log/angie/error.log info;

events {
    worker_connections  1024;
}

mail {
    server_name       mail.example.com;
    auth_http         localhost:9000/cgi-bin/auth.cgi;

    imap_capabilities IMAP4rev1 UIDPLUS IDLE LITERAL+ QUOTA;

    pop3_auth         plain apop cram-md5;
    pop3_capabilities LAST TOP USER PIPELINING UIDL;

    smtp_auth         login plain cram-md5;
    smtp_capabilities "SIZE 10485760" ENHANCEDSTATUSCODES 8BITMIME DSN;
    xclient           off;

    server {
        listen   25;
        protocol smtp;
    }
    server {
        listen   110;
        protocol pop3;
        proxy_pass_error_message on;
    }
    server {
        listen   143;
        protocol imap;
    }
    server {
        listen   587;
        protocol smtp;
    }
}

Directivas#

error_log_user_tag#

Added in version 1.12.0.

Sintaxis

error_log_user_tag value;

Predeterminado

—

Contexto

mail, server

Añade una etiqueta a los registros de error_log de cada sesión que atiende el servidor. A diferencia de sus equivalentes de http y stream, el value es una cadena estática y no puede contener variables. La directiva puede especificarse varias veces para añadir varias etiquetas. Estas directivas se heredan del nivel de configuración anterior si y solo si en el nivel actual no hay directivas error_log_user_tag.

Las etiquetas aparecen, como la lista tags, solo en los destinos de error_log que usan format=json; filter=tag: las reconoce en cualquier formato.

listen#

Sintaxis

listen dirección[:puerto] [ssl] [proxy_protocol] [backlog=número] [rcvbuf=tamaño] [sndbuf=tamaño] [bind] [ipv6only=on | off] [multipath] [so_keepalive=on | off | [keepidle]:[keepintvl]:[keepcnt]];

Predeterminado

—

Contexto

server

Establece la dirección y el puerto para el socket en el que el servidor aceptará conexiones. Es posible especificar solo el puerto, de modo que Angie escuche en todas las interfaces IPv4 disponibles (y IPv6, si está habilitado). La dirección también puede ser un nombre de host, por ejemplo:

listen 127.0.0.1:110;
listen *:110;
listen 110;     # equivalente a *:110
listen localhost:110;

Las direcciones IPv6 se especifican entre corchetes:

listen [::1]:110;
listen [::]:110;

Los sockets de dominio UNIX se especifican con el prefijo unix::

listen unix:/var/run/angie.sock;

Nota

Cada servidor debe escuchar en un par dirección:puerto distinto.

ssl

especifica que todas las conexiones aceptadas en este puerto funcionen en modo SSL.

proxy_protocol

especifica que todas las conexiones aceptadas en este puerto usen el protocolo PROXY. La información obtenida se pasa al servidor de autenticación y puede usarse para cambiar la dirección del cliente.

La directiva listen puede tener varios parámetros adicionales específicos para llamadas al sistema relacionadas con sockets.

backlog=número

establece el parámetro backlog en la llamada listen() que limita la longitud máxima de la cola de conexiones pendientes. Por defecto, backlog se establece en -1 en FreeBSD, DragonFly BSD y macOS, y en 511 en otras plataformas.

rcvbuf=tamaño

establece el tamaño del buffer de recepción (la opción SO_RCVBUF) para el socket de escucha.

sndbuf=tamaño

establece el tamaño del buffer de envío (la opción SO_SNDBUF) para el socket de escucha.

bind

hace una llamada bind() independiente para el par dirección:puerto indicado. Sin este parámetro, si varias directivas listen comparten puerto con direcciones distintas y una de ellas escucha en todas las direcciones de ese puerto, Angie llama a bind() solo para el socket comodín y determina la dirección que aceptó la conexión con getsockname(). Los parámetros backlog, rcvbuf, sndbuf, ipv6only, multipath y so_keepalive implican siempre una llamada bind() independiente.

ipv6only=on | off

determina (mediante la opción de socket IPV6_V6ONLY) si un socket IPv6 que escucha en una dirección comodín [::] aceptará solo conexiones IPv6 o tanto IPv6 como IPv4. Este parámetro está activado por defecto. Solo puede configurarse una vez al inicio.

multipath

habilita la aceptación de conexiones a través de Multipath TCP (MPTCP), compatible desde la versión 5.6 del kernel de Linux.

so_keepalive=on | off | [keepidle]:[keepintvl]:[keepcnt]

Configura el comportamiento "TCP keepalive" para el socket de escucha.

''

si se omite este parámetro, se aplicarán los valores predeterminados del sistema operativo para el socket

on

la opción SO_KEEPALIVE se activa para el socket

off

la opción SO_KEEPALIVE se desactiva para el socket

Algunos sistemas operativos permiten configurar parámetros de TCP keepalive por socket mediante las opciones de socket TCP_KEEPIDLE, TCP_KEEPINTVL y TCP_KEEPCNT. En dichos sistemas (actualmente, Linux, NetBSD, DragonFly, FreeBSD y macOS), pueden configurarse mediante los parámetros keepidle, keepintvl y keepcnt. Se pueden omitir uno o dos parámetros, en cuyo caso se aplicarán los valores predeterminados del sistema para la opción de socket correspondiente. En macOS, el parámetro keepidle establece la opción de socket TCP_KEEPALIVE en lugar de TCP_KEEPIDLE.

Por ejemplo:

so_keepalive=30m::10

establecerá el tiempo de inactividad (TCP_KEEPIDLE) en 30 minutos, dejará el intervalo de sondeo (TCP_KEEPINTVL) en su valor predeterminado del sistema y establecerá el número de sondeos (TCP_KEEPCNT) en 10 sondeos.

mail#

Sintaxis

mail { ... }

Predeterminado

—

Contexto

main

Proporciona el contexto de archivo de configuración en el que se especifican las directivas del proxy de correo.

max_commands#

Sintaxis

max_commands número;

Predeterminado

max_commands 1000;

Contexto

mail, server

Establece el número máximo de comandos emitidos durante la autenticación para mejorar la protección contra ataques DoS.

max_errors#

Sintaxis

max_errors número;

Predeterminado

max_errors 5;

Contexto

mail, server

Establece el número de errores de protocolo tras los cuales se cierra la conexión.

protocol#

Sintaxis

protocol imap | pop3 | smtp;

Predeterminado

—

Contexto

server

Establece el protocolo para un servidor proxy. Los protocolos admitidos son IMAP, POP3 y SMTP.

Si la directiva no se especifica, el protocolo puede detectarse automáticamente en función del puerto bien conocido indicado en la directiva listen:

imap: 143, 993
pop3: 110, 995
smtp: 25, 587, 465

Cuando se compila desde el código fuente, pueden deshabilitarse los protocolos innecesarios usando las opciones de compilación --without-mail_imap_module, --without-mail_pop3_module y --without-mail_smtp_module.

resolver#

Sintaxis

resolver [dirección ...] [conf [=file]] [valid=tiempo] [ipv4=on | off] [ipv6=on | off] [status_zone=zona] | off;

Predeterminado

resolver off;

Contexto

mail, server

Configura los servidores de nombres que se usan para buscar el nombre de host de un cliente SMTP, que Angie pasa al servidor de autenticación en la cabecera de solicitud Client-Host y al backend SMTP en el comando XCLIENT. Por ejemplo:

resolver 127.0.0.53 [::1]:5353;

La dirección puede especificarse como un nombre de dominio o una dirección IP, con un puerto opcional. Si no se especifica el puerto, se usa el puerto 53. Los servidores de nombres se consultan de forma round-robin.

Debe especificarse al menos una dirección de servidor DNS o el parámetro conf, excepto en la forma resolver off;.

Además de direcciones de servidor explícitas, la directiva reconoce:

off

deshabilita la resolución del nombre de host del cliente y cancela el valor heredado de la directiva

conf [=file]

lee direcciones de servidor DNS desde el archivo especificado, o desde /etc/resolv.conf si no se especifica ningún archivo

El archivo puede contener líneas nameserver con el mismo formato usado por el resolver del sistema:

nameserver 127.0.1.4
nameserver 127.0.1.5

Las direcciones leídas del archivo se añaden a cualquier dirección especificada explícitamente en la directiva, y todas ellas se consultan después conjuntamente en modo round-robin. Si el archivo no existe, no puede leerse o no enumera ninguna dirección, y no hay ninguna configurada explícitamente, Angie recurre al servidor predeterminado 127.0.0.1:53.

En tiempo de ejecución, Angie vuelve a leer el archivo cuando cambia, actualizando el conjunto de servidores DNS.

Nota

Se recomienda usar un resolver local de confianza, como 127.0.0.53 (systemd-resolved), en lugar de uno público (p.ej., 8.8.8.8). Los resolvers públicos exponen las consultas DNS a terceros y aumentan el riesgo de ataques de envenenamiento de caché.

Nota

El valor de la directiva es heredado por los bloques anidados y puede ser sobrescrito en ellos si es necesario. Dentro de un único bloque, la directiva solo puede especificarse una vez; repetirla constituye un error de configuración.

Al buscar el nombre de host del cliente, Angie almacena en caché cada respuesta DNS durante el período de vigencia de su TTL. El parámetro opcional valid permite sobrescribir ese período:

valid

parámetro opcional que permite sobrescribir la validez de las entradas en caché

resolver 127.0.0.53 [::1]:5353 valid=30s;

De forma predeterminada, Angie buscará tanto direcciones IPv4 como IPv6 al resolver.

ipv4=off

deshabilita la búsqueda de direcciones IPv4

ipv6=off

deshabilita la búsqueda de direcciones IPv6

status_zone

parámetro opcional que habilita la recopilación de información sobre las solicitudes y respuestas del servidor DNS en la zona especificada

Truco

Para prevenir ataques de spoofing DNS, se recomienda configurar servidores DNS en una red local de confianza debidamente asegurada.

Truco

Al ejecutar en Docker, usa la dirección interna de su servidor DNS, como 127.0.0.11.

resolver_timeout#

Sintaxis

resolver_timeout tiempo;

Predeterminado

resolver_timeout 30s;

Contexto

mail, server

Establece un tiempo de espera para la resolución de nombres, por ejemplo:

resolver_timeout 5s;

server#

Sintaxis

server { ... }

Predeterminado

—

Contexto

mail

Establece la configuración de un servidor.

server_name#

Sintaxis

server_name nombre;

Predeterminado

server_name hostname;

Contexto

mail, server

Establece el nombre del servidor que se usa:

  • en el saludo inicial del servidor POP3/SMTP;

  • en la sal durante la autenticación SASL CRAM-MD5;

  • en el comando EHLO al conectarse al backend SMTP, si el envío del comando XCLIENT está habilitado.

Si la directiva no se especifica, se usará el nombre de host de la máquina.

timeout#

Sintaxis

timeout tiempo;

Predeterminado

timeout 60s;

Contexto

mail, server

Establece el tiempo de espera que se utiliza antes de iniciar el proxy hacia el backend.