Módulo mail#

Implementa um proxy de email: o Angie trata as conexões de clientes IMAP, POP3 e SMTP e, depois que um servidor de autenticação externo aceita um cliente e escolhe o backend do cliente, retransmite a sessão a esse backend. Os demais módulos desta seção acrescentam o suporte aos protocolos, a troca de dados com o servidor de autenticação, o SSL/TLS e as configurações de proxy.

Ao compilar a partir do código-fonte, o módulo não é compilado por padrão; ele deve ser habilitado com a opção de compilação --with-mail.

Em pacotes e imagens de nossos repositórios, o módulo está incluído na compilação.

Como funciona#

O Angie fica entre os clientes de email e os backends e trata cada sessão em quatro etapas:

  1. O cliente se conecta ao Angie, não ao backend. O próprio Angie envia a saudação, responde às consultas de capacidades, executa o STARTTLS e recebe as credenciais do cliente por um dos métodos definidos com imap_auth, pop3_auth ou smtp_auth.

  2. O Angie passa as credenciais ao servidor de autenticação definido por auth_http, nos cabeçalhos de uma requisição HTTP. Um cliente SMTP que envia email sem autenticação aciona essa requisição depois de enviar o comando RCPT TO.

  3. O servidor de autenticação aceita ou rejeita o cliente. Para aceitá-lo, o servidor de autenticação devolve o endereço IP e a porta do backend nos cabeçalhos de resposta Auth-Server e Auth-Port, e também pode devolver o nome de usuário e a senha para fazer login no backend.

  4. O Angie abre uma conexão TCP com o backend, sem TLS, e faz login em nome do cliente com o comando IMAP LOGIN ou com os comandos POP3 USER e PASS. Para um backend SMTP, o Angie passa os dados do cliente com o comando XCLIENT, se a diretiva xclient estiver habilitada, como está por padrão, e autentica com AUTH PLAIN, se a diretiva proxy_smtp_auth estiver habilitada. A partir daí, o Angie retransmite os dados entre o cliente e o backend.

O bloco mail não tem proxy_pass nem grupos de upstream: a resposta do servidor de autenticação é a única forma de o Angie saber para onde fazer proxy de uma sessão. Por isso todo server do bloco mail precisa de auth_http, até mesmo um que aceita email SMTP sem autenticação. Os cabeçalhos de requisição e resposta são descritos no módulo Auth HTTP.

Exemplo de configuração#

Uma configuração mínima faz proxy de sessões IMAP e POP3 para um único backend em 192.0.2.10. O servidor de autenticação é um location no próprio Angie: ele aceita todos os clientes e deixa a verificação da senha para o backend, o que combina com os métodos de login em texto simples habilitados por padrão. Coloque o bloco mail no nível superior de angie.conf e os blocos map e server dentro do bloco 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 o backend verifica a senha, a diretiva proxy_pass_error_message está habilitada: um cliente com a senha errada recebe a resposta de erro do backend em vez de um erro interno, e o Angie então fecha a conexão. O servidor de autenticação recebe as senhas dos clientes sem criptografia, por isso ele deve escutar em um endereço local ou em outro endereço confiável.

Uma configuração mais completa também faz proxy de SMTP e habilita mais métodos de autenticação. O servidor de autenticação dessa configuração, aqui um script CGI, precisa verificar por conta própria os digests de APOP e CRAM-MD5 e devolver a senha do usuário em Auth-Pass, conforme descrito no 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;
    }
}

Diretivas#

error_log_user_tag#

Adicionado na versão 1.12.0.

Sintaxe

error_log_user_tag value;

Padrão

—

Contexto

mail, server

Anexa uma tag aos registros de error_log de cada sessão tratada pelo servidor. Ao contrário de suas contrapartes http e stream, o valor (value) é uma string estática e não pode conter variáveis. A diretiva pode ser especificada várias vezes para adicionar várias tags. Essas diretivas são herdadas do nível de configuração anterior se, e somente se, não houver diretivas error_log_user_tag definidas no nível atual.

Tags aparecem, como a lista tags, apenas nos destinos de error_log que usam format=json; filter=tag: as corresponde em qualquer formato.

listen#

Sintaxe

listen address[:port] [ssl] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [bind] [ipv6only=on | off] [multipath] [so_keepalive=on | off | [keepidle]:[keepintvl]:[keepcnt]];

Padrão

—

Contexto

server

Define o address e port para o socket no qual o servidor aceitará conexões. É possível especificar apenas a port, para que o Angie escute em todas as interfaces IPv4 (e IPv6, se habilitado) disponíveis. O endereço também pode ser um nome de host, por exemplo:

listen 127.0.0.1:110;
listen *:110;
listen 110;     # mesmo que *:110
listen localhost:110;

Endereços IPv6 são especificados entre colchetes:

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

Sockets de domínio UNIX são especificados com o prefixo unix::

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

Nota

Servidores diferentes devem escutar em pares address:port diferentes.

ssl

especifica que todas as conexões aceitas nesta porta devem funcionar em modo SSL.

proxy_protocol

especifica que todas as conexões aceitas nesta porta devem usar o protocolo PROXY. As informações obtidas são passadas para o servidor de autenticação e podem ser usadas para alterar o endereço do cliente.

A diretiva listen pode ter vários parâmetros adicionais específicos para chamadas de sistema relacionadas a sockets.

backlog=number

define o parâmetro backlog na chamada listen() que limita o comprimento máximo da fila de conexões pendentes. Por padrão, backlog é definido como -1 no FreeBSD, DragonFly BSD e macOS, e como 511 em outras plataformas.

rcvbuf=size

define o tamanho do buffer de recepção (a opção SO_RCVBUF) para o socket de escuta.

sndbuf=size

define o tamanho do buffer de envio (a opção SO_SNDBUF) para o socket de escuta.

bind

faz uma chamada bind() separada para o par endereço:porta indicado. Sem esse parâmetro, se várias diretivas listen compartilham uma porta com endereços diferentes e uma delas escuta em todos os endereços dessa porta, o Angie chama bind() apenas para o socket curinga e determina o endereço que aceitou a conexão com getsockname(). Os parâmetros backlog, rcvbuf, sndbuf, ipv6only, multipath e so_keepalive sempre implicam uma chamada bind() separada.

ipv6only=on | off

determina (via a opção de socket IPV6_V6ONLY) se um socket IPv6 escutando em um endereço curinga [::] aceitará apenas conexões IPv6 ou tanto conexões IPv6 quanto IPv4. Este parâmetro está ativado por padrão. Só pode ser definido uma vez na inicialização.

multipath

habilita aceitar conexões via Multipath TCP (MPTCP), suportado no kernel Linux versão 5.6 e posterior.

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

Configura o comportamento "TCP keepalive" para o socket de escuta.

''

se este parâmetro for omitido, as configurações do sistema operacional estarão em vigor para o socket

on

a opção SO_KEEPALIVE é ativada para o socket

off

a opção SO_KEEPALIVE é desativada para o socket

Alguns sistemas operacionais suportam a configuração de parâmetros TCP keepalive por socket usando as opções de socket TCP_KEEPIDLE, TCP_KEEPINTVL e TCP_KEEPCNT. Em tais sistemas (atualmente, Linux, NetBSD, DragonFly, FreeBSD e macOS), eles podem ser configurados usando os parâmetros keepidle, keepintvl e keepcnt. Um ou dois parâmetros podem ser omitidos, neste caso a configuração padrão do sistema para a opção de socket correspondente estará em vigor. No macOS, o parâmetro keepidle define a opção de socket TCP_KEEPALIVE em vez de TCP_KEEPIDLE.

Por exemplo,

so_keepalive=30m::10

definirá o timeout de inatividade (TCP_KEEPIDLE) para 30 minutos, deixará o intervalo de sonda (TCP_KEEPINTVL) em seu padrão do sistema, e definirá a contagem de sondas (TCP_KEEPCNT) para 10 sondas.

mail#

Sintaxe

mail { ... }

Padrão

—

Contexto

main

Fornece o contexto do arquivo de configuração no qual as diretivas do proxy de email são especificadas.

max_commands#

Sintaxe

max_commands number;

Padrão

max_commands 1000;

Contexto

mail, server

Define o número máximo de comandos emitidos durante a autenticação para melhorar a proteção contra ataques DoS.

max_errors#

Sintaxe

max_errors number;

Padrão

max_errors 5;

Contexto

mail, server

Define o número de erros de protocolo após os quais a conexão é fechada.

protocol#

Sintaxe

protocol imap | pop3 | smtp;

Padrão

—

Contexto

server

Define o protocolo para um servidor proxy. Os protocolos suportados são IMAP, POP3 e SMTP.

Se a diretiva não for definida, o protocolo pode ser detectado automaticamente com base na porta conhecida especificada na diretiva listen:

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

Ao compilar a partir do código-fonte, protocolos desnecessários podem ser desabilitados usando as --without-mail_imap_module, --without-mail_pop3_module e --without-mail_smtp_module opções de compilação.

resolver#

Sintaxe

resolver [address ...] [conf [=file]] [valid=time] [ipv4=on | off] [ipv6=on | off] [status_zone=zone] | off;

Padrão

resolver off;

Contexto

mail, server

Configura os servidores de nomes usados para encontrar o nome do host de um cliente SMTP, que o Angie passa ao servidor de autenticação no cabeçalho de requisição Client-Host e ao backend SMTP no comando XCLIENT. Por exemplo:

resolver 127.0.0.53 [::1]:5353;

O endereço pode ser especificado como um nome de domínio ou endereço IP, com uma porta opcional. Se a porta não for especificada, a porta 53 é usada. Os servidores de nomes são consultados em round-robin.

Deve ser especificado pelo menos um endereço de servidor DNS ou o parâmetro conf, exceto na forma resolver off;.

Além de endereços de servidor explícitos, a diretiva reconhece:

off

desabilita a resolução do nome do host do cliente e cancela o valor herdado da diretiva

conf [=file]

lê endereços de servidor DNS do arquivo especificado, ou de /etc/resolv.conf se nenhum arquivo for especificado

O arquivo pode conter linhas nameserver no mesmo formato usado pelo resolver do sistema:

nameserver 127.0.1.4
nameserver 127.0.1.5

Os endereços lidos do arquivo são adicionados a quaisquer endereços especificados explicitamente na diretiva, e todos eles são então consultados juntos em modo round-robin. Se o arquivo estiver ausente, não puder ser lido ou não listar nenhum endereço, e nenhum estiver configurado explicitamente, o Angie recorre ao servidor padrão 127.0.0.1:53.

Em tempo de execução, o Angie relê o arquivo quando ele muda, atualizando o conjunto de servidores DNS.

Nota

Recomenda-se usar um resolver local confiável, como 127.0.0.53 (systemd-resolved), em vez de um público (p.ex., 8.8.8.8). Resolvers públicos expõem consultas DNS a terceiros e aumentam o risco de ataques de envenenamento de cache.

Nota

O valor da diretiva é herdado por blocos aninhados e pode ser sobrescrito neles se necessário. Dentro de um único bloco, a diretiva só pode ser especificada uma vez; repeti-la é um erro de configuração.

Ao buscar o nome do host do cliente, o Angie faz cache de cada resposta DNS durante o período de validade do seu TTL. O parâmetro opcional valid permite sobrescrever esse período:

valid

parâmetro opcional permite sobrescrever a validade da entrada em cache

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

Por padrão, o Angie procurará endereços IPv4 e IPv6 durante a resolução.

ipv4=off

desabilita a busca de endereços IPv4

ipv6=off

desabilita a busca de endereços IPv6

status_zone

parâmetro opcional, habilita a coleta de informações sobre requisições e respostas do servidor DNS na zona especificada

Dica

Para prevenir spoofing de DNS, é recomendado configurar servidores DNS em uma rede local confiável adequadamente protegida.

Dica

Ao executar no Docker, use seu endereço de servidor DNS interno como 127.0.0.11.

resolver_timeout#

Sintaxe

resolver_timeout tempo;

Padrão

resolver_timeout 30s;

Contexto

mail, server

Define um timeout para resolução de nomes, por exemplo:

resolver_timeout 5s;

server#

Sintaxe

server { ... }

Padrão

—

Contexto

mail

Define a configuração para um servidor.

server_name#

Sintaxe

server_name nome;

Padrão

server_name hostname;

Contexto

mail, server

Define o nome do servidor que é usado:

  • na saudação inicial do servidor POP3/SMTP;

  • no salt durante a autenticação SASL CRAM-MD5;

  • no comando EHLO ao conectar ao backend SMTP, se a passagem do comando XCLIENT estiver habilitada.

Se a diretiva não for especificada, o hostname da máquina é usado.

timeout#

Sintaxe

timeout tempo;

Padrão

timeout 60s;

Contexto

mail, server

Define o timeout que é usado antes que o proxy para o backend seja iniciado.