Repository navigation
mail-auth-proxy 0.3.0
·
32 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Added
SIGHUP(systemctl reload) reloads the configuration file without closing any
connection. The file passes the checks of--check-config(warnings logged) and is
taken over as a whole: legacy rules,[legacy], users and domains files, issuers
(a new issuer's JWKS is fetched by the reload),[limits],[auth_ratelimit],
[timeouts],[session],[scope],server.hostname, the certificates in[tls]
and[[tls.certificates]], the backends and the submission and sieve settings.
Connections accepted afterwards use the new configuration; open ones keep the one they
were accepted with until they end. Rate-limit counts and blocks, the legacy throttle,
the backends' cached capabilities and the keys of issuers that stay are carried over.
A change of a listener address, a listener added or removed, or of the metrics
endpoint needs a restart: such a file, and one that is invalid, is refused as a whole
with oneERROR reload: configuration not loaded …line, and the configuration in use
stays. Package upgrades still restart the service (a new binary).mail_auth_proxy_config_reload_total{result="ok|error"}and
mail_auth_proxy_config_last_reload_success_timestamp_seconds(set at startup and by
each successful reload).- IMAP
LOGINtakes its user name and password as literals (RFC 9051 §6.2.3, §9): a
synchronising{n}after a+continuation, a non-synchronising{n+}at once, up
to 16384 octets each. A password a client sends as a literal (for example one with
8-bit characters) was refused withBAD. Where the connection offers no LOGIN, a
synchronising literal is refused withNObefore the continuation. - XCLIENT to the submission backend carries the client's post-TLS EHLO or HELO name
(HELO=),PROTO=ESMTPorSMTPand the client's source port (PORT=), each where
the backend lists it, so itsReceived:header names the client's greeting instead
of the proxy's (RFC 5321 §4.4).smtpd_helo_restrictionson the submission service
now apply to the client's name. oauth.issuers[].identity_domains: the domains an issuer may log in to. A token whose
identity is not an address in one of them is abad_token. With more than one issuer,
each issuer without it gives a configuration warning: every issuer could otherwise log
in to every other issuer's mailboxes (OIDC Core §5.7).- ALPN on the IMAP and ManageSieve listeners (
imap,managesieve, RFC 7301): a client
that offers ALPN without the listener's identifier is refused in the TLS handshake, so
a TLS session meant for another service cannot be redirected to them (RFC 9325 §3.8,
ALPACA). Clients without ALPN are unaffected; SMTP has no identifier and ignores it. - Certificates by SNI (RFC 6066 §3):
[[tls.certificates]](cert,key) next to the
[tls]default. A client gets the certificate that carries the name it asks for, an
exact subjectAltName DNS name first, then a wildcard for one leftmost label (RFC 9525
§6.3); a client without SNI getstls.cert.SIGHUPreloads each certificate on its
own;--check-configloads every pair and warns about alegacy.rules[].sniname no
certificate carries. The[tls] cert/keyform is unchanged.
Changed
SIGHUPre-reads the configuration file as well as the certificates and the JWKS.
After a refused reload each certificate is still re-read on its own as before, so a
renewal works while the configuration file is broken. The series of
mail_auth_proxy_jwks_*andmail_auth_proxy_tls_cert_expiry_timestamp_seconds
follow the issuers and certificate files of the configuration in use.- A source added to
auth_ratelimit.exempt_networks(or covered byexempt_internal)
is no longer blocked, also when its block started before. - A client that asks (SNI) for a name that no configured certificate carries is refused
in the TLS handshake with the fatal alertunrecognized_name(RFC 9325 §3.7); it got
the one certificate before. The accepted names are the subjectAltName DNS names of the
certificates. Clients without SNI are unaffected. mail_auth_proxy_tls_cert_expiry_timestamp_secondshas the labelcert(the
certificate file), one series per certificate. With one certificate there is still one
series, now labelled; a query or an exact series match on the unlabelled series must
be adjusted, and with several certificates an alert takes the earliest (min).- The EHLO reply after STARTTLS lists the submission backend's own extensions instead of
a static list (RFC 5321 §4.2.4), as far as the proxy handles each one: PIPELINING,
SIZE (with the backend's limit, advertised now), 8BITMIME, SMTPUTF8, DSN,
ENHANCEDSTATUSCODES and CHUNKING; never XCLIENT, XFORWARD, VRFY, ETRN or unknown
ones. The proxy reads them with a probe connection of its own, at startup and then at
most once persubmission.capability_cache_secs(new, default 600), one at a time;
failed probes count inbackend_errors_total{proto="smtp"}, and the last list stays
in use.submission.ehlo_extensionsis now optional and narrows the list by keyword:
existing lists keep working, their parameters are ignored and keywords the proxy
never passes on give a warning. BDATbefore AUTH is answered with530, then421and the close: its chunk was
read as commands (RFC 3030 §2).- A connection takes up to
limits.max_auth_attemptsauthentication attempts (new,
default 3, 1-10) instead of one (RFC 9051 §6.2.2, RFC 4954 §4, RFC 5804 §2.1), so
clients that fall back from one mechanism to another on the same connection (Python
smtplibfrom PLAIN to LOGIN, Thunderbird) or retry with a refreshed token no longer
lose it. Each attempt gets its ownauthresultline (format unchanged), counts for
the rate limit and passes the legacy gate and the refusal timing like one on a new
connection; the pre-auth budget andmax_preauth_commandsspan all of them. A source
the rate limit blocks while the connection is open is closed at its next credential,
before it is judged. After an outage, the last attempt, an unknown command or a
malformed one, the connection closes as before. Set 1 for the old behaviour. - The ManageSieve backend's capabilities are probed once at startup, so the first
greetings no longer wait for a probe. A failure there is logged and counted in
mail_auth_proxy_backend_errors_total{proto="sieve"}; the start goes on. - IMAP advertises
IMAP4rev1withoutIMAP4rev2before login. The proxy does not know
whether the backend speaks IMAP4rev2; after login the backend's own list is relayed as
before, withIMAP4rev2where the backend offers it. Dovecot enables IMAP4rev2 only
withimap4rev2_enable.
Fixed
- Client lines are read without arming the idle timer for every byte that has already
arrived. A long line (a 10 KB password) took several times longer to read than to
receive, and under CPU load its refusal came measurably later than that of a short
wrong password. - SMTP replies before authentication: before TLS every command other than NOOP, EHLO,
STARTTLS and QUIT gets530 5.7.0(RFC 3207 §4; HELO and RSET got250), STARTTLS
with parameters501 5.5.4; after TLS and before AUTH530 5.7.0for every command
other than AUTH, EHLO, HELO, NOOP, RSET and QUIT (RFC 4954 §6) and503 5.5.1for
STARTTLS; an unrecognised command500 5.5.1instead of502(RFC 5321 §4.2.4);
250 2.0.0 OKwith an enhanced status code for NOOP and RSET (RFC 2034 §4). - A JWK whose
key_opsdoes not includeverifyis skipped like one with auseother
thansig(RFC 7517 §4.3). - The PROXY v2 header carries IPv4-mapped IPv6 addresses (a dual-stack listener) as
TCP over IPv4, so the backend logs192.0.2.7, not::ffff:192.0.2.7. - ManageSieve answers the pre-TLS command limit with
BYEinstead ofNObefore it
closes the connection (RFC 5804 §1.2), as after TLS. - A client and local address of different families, which cannot be put in one PROXY
header, fail the backend connection as an outage. The connection went ahead without
the header, which the backend refuses or logs with the proxy's address. - A TLS session the proxy ends before the relay (a refused credential, an outage, a
pre-authentication timeout, LOGOUT or QUIT) ends with a TLS close_notify (RFC 8314
§3.4). The connection was dropped without one, which clients report as a truncated
session.
Install
Debian and Ubuntu: APT repository, see INSTALL.md.
Other systems: download the package or archive and SHA256SUMS, SHA256SUMS.asc and
release-signing-key.asc, then:
gpg --import release-signing-key.asc # 0B58 3E99 144D CD9B 5A34 D96B E52C 6D1E FB67 927B
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS