Security
Upgrade if you take AUTH from the public internet, or if you run behind a
proxy.
-
Server.MaxAuthAttemptscloses a connection whoseAUTHcommands keep
failing. RFC 4954 section 6 asks for such a limit.PLAINandLOGIN
both carry a password, and one connection took as many guesses as the client
cared to send.Only a refusal from the
Authenticatehooks counts, and a successfulAUTH
sets the count back to zero.This changes behavior. The default is 5, so a client that fails five
times now gets a421reply and a closed connection, where it could go on
before. Set the field to-1for the behavior of earlier versions. -
Server.TrustedProxiesholds the addresses that may restate the identity
of the client, with a PROXY protocol header or anXCLIENTcommand. Both
writePeer.Addr, which the greylist, the RBL check, the rate limit and the
SPF check all read, so a client that reached either one took the identity of
any client it named.The server reads the address of the connection, and never
Peer.Addr: a
header that arrived already wrote that one, so a client could otherwise name
a trusted address and then act on it.This changes behavior. An empty list trusts the addresses that the public
internet does not reach: the loopback addresses, the private ranges of RFC
1918 and RFC 4193, and the link-local addresses. A proxy that reaches the
server from any other address, such as a load balancer with a public one,
has to be named:srv.TrustedProxies = []netip.Prefix{ netip.MustParsePrefix("203.0.113.7/32"), }
The list replaces the default rule rather than adding to it, so a server
that names its proxies and still takes connections over the loopback
interface names that range too.
Added
-
middleware.AuthRateLimitlimits the failed authentication attempts of one
address, across the connections of that address.Server.MaxAuthAttempts
bounds a single connection alone. A client that opens a new connection for
every guess gets around that limit.A failed attempt takes a token, and a successful one takes none, so a client
that always sends the right password never spends the bucket of its address.
An address with no tokens left gets a454reply.
Fixed
-
middleware.Greylistholds the three parts of a triple apart. The key
put the address of the client, the sender and the recipient in one string
with a|between them, and RFC 5321 gives|to the local part of an
address, so two triples could meet on one entry. The second of them read the
entry of the first, and it passed a delay that it never waited. -
One
AUTHcommand can succeed in a session, and everyAUTHcommand
after it gets a503reply. RFC 4954 section 4 asks for that. The server
took every one of them, so a client could take a second identity on a
session whose earlier commands ran under the first.This changes behavior. A client that sends
AUTHtwice gets a503for
the second one, where the server authenticated it again before. -
Server.Shutdowncloses the connection that the listener gave, and not
the one that the session holds.STARTTLSputs a TLS connection in the place
of that one, on the goroutine of the session.Shutdownread the same field
from the goroutine of its caller, and nothing ordered the two.
The changelog carries
the whole text of each entry.