Auth HTTP#

Autentica clientes de email por meio de um servidor HTTP externo, o servidor de autenticação, que também escolhe o backend de cada sessão. O Angie não tem outra fonte de endereços de backend para email, portanto todo server do bloco mail precisa da diretiva auth_http (veja Como funciona).

Exemplo de configuração#

O Angie faz proxy de sessões IMAP para um de dois backends, escolhido pelo domínio no nome de usuário, e atua como seu próprio servidor de autenticação, por meio de um location no bloco http. 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;
    }
}

http {
    map $http_auth_user $mail_backend {
        ~@example\.com$ 192.0.2.10;
        ~@example\.org$ 192.0.2.20;
    }

    map $mail_backend $mail_auth_status {
        ""      "Invalid login or password";
        default OK;
    }

    map $http_auth_login_attempt $mail_auth_wait {
        ~^[1-9]$ 3;
        default  "";
    }

    server {
        listen 127.0.0.1:9000;

        location = /mail-auth {
            add_header Auth-Status $mail_auth_status;
            add_header Auth-Server $mail_backend;
            add_header Auth-Port   143;
            add_header Auth-Wait   $mail_auth_wait;

            return 204;
        }
    }
}

Esse servidor de autenticação encaminha os clientes, mas não verifica as senhas dos clientes: o Angie faz login no backend com a senha enviada pelo cliente, e o backend a aceita ou a rejeita. Se o backend a rejeitar, a diretiva proxy_pass_error_message repassa a resposta do backend ao cliente, e o Angie fecha a conexão. Um usuário de qualquer outro domínio recebe o erro Invalid login or password. Nas nove primeiras tentativas de uma sessão, o Angie atrasa esse erro em três segundos e deixa o cliente tentar de novo; a partir da décima tentativa, ele envia o erro imediatamente e fecha a conexão.

Diretivas#

auth_http#

Sintaxe

auth_http uri;

Padrão

—

Contexto

mail, server

Define o URL do servidor de autenticação: um endereço IP ou um nome de domínio com porta opcional (80 por padrão) e URI, ou o caminho de um socket de domínio UNIX após o prefixo unix:, como em unix:/run/mail-auth.sock:/mail-auth. O prefixo de esquema http:// é opcional. HTTPS não é suportado: um URL com https:// falha no teste de configuração com a mensagem invalid port in auth_http. O Angie resolve o nome de domínio ao carregar a configuração e envia as requisições ao primeiro endereço encontrado.

A diretiva é obrigatória: se ela não estiver definida nem no server nem no bloco mail, o teste de configuração falha com o erro no "auth_http" is defined for server. As requisições e respostas são descritas em Protocolo.

auth_http_header#

Sintaxe

auth_http_header header value;

Padrão

—

Contexto

mail, server

Adiciona o cabeçalho às requisições enviadas ao servidor de autenticação. A diretiva pode ser especificada várias vezes. Essas diretivas são herdadas do nível de configuração anterior se, e somente se, não houver diretivas auth_http_header definidas no nível atual.

Um cabeçalho secreto permite que o servidor de autenticação verifique que a requisição vem do Angie:

auth_http_header X-Auth-Key "secret_string";

auth_http_pass_client_cert#

Sintaxe

auth_http_pass_client_cert on | off;

Padrão

auth_http_pass_client_cert off;

Contexto

mail, server

Adiciona às requisições enviadas ao servidor de autenticação o cabeçalho Auth-SSL-Cert, com o certificado do cliente em formato PEM, codificado em URL. O Angie envia o cabeçalho somente quando a diretiva ssl_verify_client está habilitada e o cliente apresenta um certificado.

auth_http_timeout#

Sintaxe

auth_http_timeout tempo;

Padrão

auth_http_timeout 60s;

Contexto

mail, server

Define o timeout da troca com o servidor de autenticação: dentro desse tempo, o Angie deve conectar-se a ele, enviar a requisição e receber os cabeçalhos da resposta.

Protocolo#

A cada tentativa de login, o Angie abre uma nova conexão com o servidor de autenticação e envia uma requisição HTTP/1.0 GET para o URI definido por auth_http; os dados do cliente seguem nos cabeçalhos da requisição. Um cliente SMTP que envia email sem autenticação aciona a requisição depois do comando RCPT TO.

O servidor de autenticação responde nos cabeçalhos da resposta. O Angie ignora o código de status e o corpo da resposta. A linha de status, os cabeçalhos e a linha vazia depois deles devem caber em 1024 bytes: com um bloco de cabeçalhos maior, a sessão falha conforme descrito em Erros, e o cliente pode esperar até que o intervalo definido por auth_http_timeout se esgote antes de receber o erro.

Cabeçalhos de requisição#

Host

O host do URL de auth_http; localhost para um socket de domínio UNIX.

Auth-Method

O método de autenticação usado pelo cliente: plain (também para AUTH LOGIN, o comando IMAP LOGIN e os comandos POP3 USER e PASS), apop, cram-md5, external, xoauth2 ou oauthbearer; none para um cliente SMTP que envia email sem autenticação.

Auth-User

O nome de usuário enviado pelo cliente; para XOAUTH2 e OAUTHBEARER, a identidade do usuário na resposta SASL inicial.

Auth-Pass

A senha enviada pelo cliente; o digest do cliente para APOP e CRAM-MD5; o bearer token para XOAUTH2 e OAUTHBEARER; vazio para EXTERNAL.

Auth-Salt

Somente para APOP e CRAM-MD5: o desafio que o Angie enviou ao cliente.

Auth-Protocol

imap, pop3 ou smtp.

Auth-Login-Attempt

O número da tentativa de login do cliente na sessão, começando em 1.

Client-IP

O endereço IP do cliente.

Client-Host

Somente para SMTP: o nome do host do cliente encontrado pelo resolver; [UNAVAILABLE] se o resolver não estiver configurado, se o nome não existir ou não apontar de volta para o endereço do cliente; [TEMPUNAVAIL] em outros erros de resolução.

Auth-SMTP-Helo, Auth-SMTP-From, Auth-SMTP-To

Somente com Auth-Method: none: o argumento do comando HELO ou EHLO do cliente e os comandos completos MAIL FROM e RCPT TO do cliente.

Proxy-Protocol-Addr, Proxy-Protocol-Port, Proxy-Protocol-Server-Addr, Proxy-Protocol-Server-Port

Somente com o parâmetro proxy_protocol de listen: o endereço e a porta do cliente e o endereço e a porta do servidor, extraídos do cabeçalho do protocolo PROXY.

Auth-SSL

on se a conexão do cliente usa SSL/TLS, inclusive após STARTTLS.

Auth-SSL-Protocol, Auth-SSL-Cipher

O protocolo e a cifra da conexão SSL/TLS do cliente.

Auth-SSL-Verify

Somente com a diretiva ssl_verify_client habilitada: o resultado da verificação do certificado do cliente: SUCCESS, FAILED:reason ou NONE, se o cliente não apresentou certificado. FAILED chega somente com ssl_verify_client optional_no_ca e somente para um certificado autoassinado ou um cujo emissor é desconhecido; qualquer outra falha de verificação encerra a sessão antes da requisição.

Auth-SSL-Subject, Auth-SSL-Issuer, Auth-SSL-Serial, Auth-SSL-Fingerprint

Somente com a diretiva ssl_verify_client habilitada e um certificado de cliente apresentado: o DN do subject e o DN do emissor do certificado no formato RFC 2253, o número de série e a impressão digital SHA-1 do certificado.

Auth-SSL-Cert

Nas mesmas condições, se a diretiva auth_http_pass_client_cert também estiver habilitada: o certificado do cliente em formato PEM.

Os cabeçalhos definidos por auth_http_header vêm depois destes. Em Auth-User, Auth-Pass e Auth-SSL-Cert, o Angie substitui espaços, sinais de porcentagem e caracteres de controle por escapes %XX, portanto o servidor de autenticação precisa decodificar esses valores antes de usá-los.

Cabeçalhos de resposta#

Auth-Status

OK aceita o cliente. WAIT faz o Angie repetir a requisição após o atraso de Auth-Wait. Qualquer outro valor rejeita o cliente e se torna a mensagem de erro enviada ao cliente. O Angie compara OK e WAIT diferenciando maiúsculas de minúsculas; uma resposta sem Auth-Status também aceita o cliente.

Auth-Server

Com OK: o endereço IP do backend. Um nome de domínio não é aceito.

Auth-Port

Com OK: a porta do backend.

Auth-User

Com OK: o nome de usuário para fazer login no backend, no lugar do enviado pelo cliente.

Auth-Pass

Com OK: a senha para fazer login no backend, no lugar da enviada pelo cliente. Obrigatória após APOP, CRAM-MD5 e EXTERNAL: para IMAP e POP3, sempre; para SMTP, se a diretiva proxy_smtp_auth estiver habilitada.

Auth-Wait

Um atraso em segundos, usado somente com um erro ou com WAIT. Com um erro, o Angie espera esse tempo, envia o erro e deixa o cliente tentar de novo; sem o cabeçalho, o Angie envia o erro imediatamente e fecha a conexão. Com WAIT, é o atraso antes da repetição da requisição.

Auth-Error-Code

Somente para SMTP, com um erro: o código de resposta e o código de status estendido que precedem a mensagem; por padrão, 535 5.7.0.

Auth-Error-SASL

Somente para XOAUTH2 e OAUTHBEARER, com um erro: um desafio SASL que o Angie envia ao cliente antes do erro.

O Angie ignora os demais cabeçalhos de resposta. No entanto, o nome de um cabeçalho pode conter somente letras latinas, dígitos e hífens: um nome com qualquer outro caractere, como um sublinhado, faz o Angie rejeitar a resposta inteira.

Exemplos de requisições e respostas#

Login bem-sucedido#

Um cliente IMAP faz login com um nome de usuário e uma senha:

GET /auth HTTP/1.0
Host: localhost
Auth-Method: plain
Auth-User: user
Auth-Pass: password
Auth-Protocol: imap
Auth-Login-Attempt: 1
Client-IP: 192.0.2.42

O servidor de autenticação aceita o cliente e indica o backend:

HTTP/1.0 200 OK
Auth-Status: OK
Auth-Server: 198.51.100.1
Auth-Port: 143

O Angie se conecta a 198.51.100.1:143 e faz login com o nome de usuário e a senha do cliente.

Login com falha e novas tentativas#

O servidor de autenticação rejeita o cliente:

HTTP/1.0 200 OK
Auth-Status: Invalid login or password
Auth-Wait: 3

Após três segundos, o Angie envia ao cliente o erro no formato esperado pelo protocolo (-ERR Invalid login or password no POP3, uma resposta NO com tag no IMAP, 535 5.7.0 Invalid login or password no SMTP) e deixa o cliente tentar de novo; a requisição seguinte traz o valor incrementado de Auth-Login-Attempt.

O Angie aloca memória para cada tentativa e a libera somente quando a sessão termina, por isso o servidor de autenticação deve limitar as tentativas: após 10 a 20 delas, ele deve responder sem Auth-Wait, para que o Angie feche a conexão.

No SMTP, Auth-Error-Code substitui o código de resposta padrão. Esta resposta:

HTTP/1.0 200 OK
Auth-Status: Temporary server problem, try again later
Auth-Error-Code: 451 4.3.0
Auth-Wait: 3

gera este erro para o cliente SMTP:

451 4.3.0 Temporary server problem, try again later

Se o servidor de autenticação ainda não consegue decidir, ele pode responder com Auth-Status: WAIT. O Angie então envia a requisição de novo após o atraso de Auth-Wait, sem avisar o cliente, e Auth-Login-Attempt permanece o mesmo. Para APOP e CRAM-MD5, a requisição repetida traz um Auth-Pass vazio, portanto o servidor de autenticação precisa verificar o digest na primeira requisição e guardar o resultado. O Angie continua repetindo a requisição enquanto a resposta for WAIT, mesmo depois que o cliente se desconecta, por isso o servidor de autenticação deve parar de responder WAIT depois de um tempo razoável.

Aviso

Toda resposta WAIT deve conter Auth-Wait. Sem esse cabeçalho, o Angie repete a requisição imediatamente, em um loop sem pausas, e continua fazendo isso mesmo quando o servidor de autenticação depois responde OK.

APOP, CRAM-MD5 e EXTERNAL#

Com APOP ou CRAM-MD5, o cliente prova que conhece a senha sem enviá-la, e a requisição traz o desafio e o digest do cliente:

GET /auth HTTP/1.0
Host: localhost
Auth-Method: apop
Auth-User: user
Auth-Salt: <238188073.1163692009@mail.example.com>
Auth-Pass: auth_response
Auth-Protocol: pop3
Auth-Login-Attempt: 1
Client-IP: 192.0.2.42

O Angie faz login no backend somente com comandos em texto simples, por isso o próprio servidor de autenticação verifica o digest e devolve a senha do usuário:

HTTP/1.0 200 OK
Auth-Status: OK
Auth-Server: 198.51.100.1
Auth-Port: 110
Auth-Pass: plain-text-pass

Com EXTERNAL, a resposta também precisa de Auth-Pass; a requisição traz um Auth-Pass vazio.

XOAUTH2 e OAUTHBEARER#

Em caso de sucesso, o Angie faz login no backend com o bearer token como senha, a menos que a resposta contenha Auth-Pass.

Uma resposta de erro também pode incluir Auth-Error-SASL. O Angie envia o valor desse cabeçalho ao cliente como um desafio SASL adicional (SMTP: 334; IMAP e POP3: +). Depois que o cliente responde (com uma linha vazia para XOAUTH2 ou AQ== para OAUTHBEARER), o Angie devolve o erro de Auth-Status.

SMTP sem autenticação#

Se smtp_auth incluir none e o cliente enviar email sem autenticação, a requisição traz os comandos SMTP do cliente:

GET /auth HTTP/1.0
Host: localhost
Auth-Method: none
Auth-User:
Auth-Pass:
Auth-Protocol: smtp
Auth-Login-Attempt: 1
Client-IP: 192.0.2.42
Client-Host: client.example.org
Auth-SMTP-Helo: client.example.org
Auth-SMTP-From: MAIL FROM: <>
Auth-SMTP-To: RCPT TO: <postmaster@mail.example.com>

O servidor de autenticação ainda precisa indicar o backend em Auth-Server e Auth-Port; o Angie então repete os comandos MAIL FROM e RCPT TO do cliente para o backend.

Conexões de cliente SSL/TLS#

Um cliente IMAP conectado por TLS, com a diretiva ssl_verify_client habilitada:

GET /auth HTTP/1.0
Host: localhost
Auth-Method: plain
Auth-User: user
Auth-Pass: password
Auth-Protocol: imap
Auth-Login-Attempt: 1
Client-IP: 192.0.2.42
Auth-SSL: on
Auth-SSL-Protocol: TLSv1.3
Auth-SSL-Cipher: TLS_AES_256_GCM_SHA384
Auth-SSL-Verify: SUCCESS
Auth-SSL-Subject: CN=example.com
Auth-SSL-Issuer: CN=example.com
Auth-SSL-Serial: C07AD56B846B5BFF
Auth-SSL-Fingerprint: 29d6a80a123d13355ed16b4b04605e29cb55a5ad

Erros#

Se a troca com o servidor de autenticação falhar ou se a resposta do servidor de autenticação aceitar o cliente, mas não puder ser usada, o Angie envia ao cliente um erro interno e fecha a conexão:

IMAP

* BAD internal server error

POP3

-ERR internal server error

SMTP

451 4.3.2 Internal server error

O error_log indica a causa:

timed out

A troca não terminou dentro do intervalo definido por auth_http_timeout.

sent invalid response

A linha de status termina com um CR que não é seguido por LF.

sent invalid header in response

Um cabeçalho da resposta está malformado ou tem um nome com caractere diferente de letra latina, dígito ou hífen.

did not send server or port

A resposta não rejeita o cliente, mas não contém Auth-Server ou Auth-Port, como acontece com uma página de erro retornada para um URI incorreto.

sent invalid server address

Auth-Server não é um endereço IP.

sent invalid server port

Auth-Port não é um número de 1 a 65535.

did not send password

Uma resposta para IMAP ou POP3 aceita um cliente APOP, CRAM-MD5 ou EXTERNAL sem Auth-Pass.

no password available

Uma resposta para SMTP aceita um cliente CRAM-MD5 ou EXTERNAL sem Auth-Pass enquanto a diretiva proxy_smtp_auth está habilitada.

Todas essas mensagens, exceto no password available, começam com auth http server e o endereço do servidor de autenticação. Se o Angie não consegue se conectar ao servidor de autenticação, o log mostra o erro do sistema em uma mensagem connect() to ... failed, send() failed ou recv() failed. Uma resposta cujo bloco de cabeçalhos excede 1024 bytes é registrada como timed out, se chegar a ser registrada.