Proposal: sslmode=tls-only
From 53.2.9. SSL Session Encryption:
When SSL encryption can be performed, the server is expected to send only
the single S byte and then wait for the frontend to initiate an SSL
handshake. If additional bytes are available to read at this point, it
likely means that a man-in-the-middle is attempting to perform a
buffer-stuffing attack (CVE-2021-23222). Frontends should be coded either
to read exactly one byte from the socket before turning the socket over to
their SSL library, or to treat it as a protocol violation if they find they
have read additional bytes.
An initial SSLRequest can also be used in a connection that is being
opened to send a CancelRequest message.
While the protocol itself does not provide a way for the server to force
SSL encryption, the administrator can configure the server to reject
unencrypted sessions as a byproduct of authentication checking.
Has consideration been given to having something like ssl-mode=tls-only
where the SSLRequest message is skipped and the TLS handshake starts
immediately with the protocol continuing after that?
This has several advantages:
1) One less round-trip when establishing the connection, speeding this up.
TLS 1.3 removed a round-trip and this was significant so it could help.
2) No possibility of downgrading to non-TLS. (Not sure this is an issue
though.)
3) Connections work through normal TLS proxies and SNI can be used for
routing.
This final advantage is the main reason I'd like to see this implemented.
Postgres is increasingly being run in multi-tenant Kubernetes clusters
where load-balancers and node ports are not available, cost or don't scale
and it is currently difficult to connect to databases running there. If it
was possible to use normal ingress TLS proxies, running Postgres in
Kubernetes would be much easier and there are other use cases where just
using TLS would be beneficial as well.
Questions about TLS SNI support have been asked for several years now and
this would be a big usability improvement. SNI support was recently added
to the client-side and this seems like the next logical step.
Thoughts?
- Keith
On 12/24/21 09:08, Keith Burdis wrote:
From 53.2.9. SSL Session Encryption:
When SSL encryption can be performed, the server is expected to
send only the single S byte and then wait for the frontend to
initiate an SSL handshake. If additional bytes are available to
read at this point, it likely means that a man-in-the-middle is
attempting to perform a buffer-stuffing attack (CVE-2021-23222).
Frontends should be coded either to read exactly one byte from the
socket before turning the socket over to their SSL library, or to
treat it as a protocol violation if they find they have read
additional bytes.An initial SSLRequest can also be used in a connection that is
being opened to send a CancelRequest message.While the protocol itself does not provide a way for the server to
force SSL encryption, the administrator can configure the server
to reject unencrypted sessions as a byproduct of authentication
checking.Has consideration been given to having something like
ssl-mode=tls-only where the SSLRequest message is skipped and the TLS
handshake starts immediately with the protocol continuing after that?This has several advantages:
1) One less round-trip when establishing the connection, speeding this
up. TLS 1.3 removed a round-trip and this was significant so it could
help.
2) No possibility of downgrading to non-TLS. (Not sure this is an
issue though.)
3) Connections work through normal TLS proxies and SNI can be used for
routing.This final advantage is the main reason I'd like to see this
implemented. Postgres is increasingly being run in multi-tenant
Kubernetes clusters where load-balancers and node ports are not
available, cost or don't scale and it is currently difficult to
connect to databases running there. If it was possible to use normal
ingress TLS proxies, running Postgres in Kubernetes would be much
easier and there are other use cases where just using TLS would be
beneficial as well.Questions about TLS SNI support have been asked for several years now
and this would be a big usability improvement. SNI support was
recently added to the client-side and this seems like the next logical
step.Thoughts?
Isn't that going to break every existing client? How is a client
supposed to know which protocol to follow?
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
Servers that use sslmode=tls-only would not be compatible with clients
that do not yet support it, but that is same for any similar server-side
change, for example if the server requires a minimum of TLS 1.3 but the
client only supports TLS 1.2.
IIUC with the default sslmode=prefer a client currently first tries to
connect using SSL by sending an SSLRequest and if the response is not an S
then it tries with a plain StartupMessage. If we wanted this new mode to
work by default as well, this could be changed to try a TLS handshake after
the SSLRequest and StartupMessage. Similarly for the other existing
sslmode values an SSLRequest could be sent and if that fails then a TLS
handshake could be initiated.
But this is "only provided as the default for backwards compatibility, and
is not recommended in secure deployments". I'd expect that most secure
deployments set an explicit sslmode=verify-full, so having them set an
explicit sslmode=tls-only would not be an issue once the client and server
support it.
There is already precedent for having clients handle something new [1]https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.11:"The
frontend should also be prepared to handle an ErrorMessage response to
SSLRequest from the server. This would only occur if the server predates
the addition of SSL support to PostgreSQL. (Such servers are now very
ancient, and likely do not exist in the wild anymore.) In this case the
connection must be closed, but the frontend might choose to open a fresh
connection and proceed without requesting SSL."
[1]: https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.11
On Fri, 24 Dec 2021 at 19:16, Andrew Dunstan <andrew@dunslane.net> wrote:
Show quoted text
On 12/24/21 09:08, Keith Burdis wrote:
From 53.2.9. SSL Session Encryption:
When SSL encryption can be performed, the server is expected to
send only the single S byte and then wait for the frontend to
initiate an SSL handshake. If additional bytes are available to
read at this point, it likely means that a man-in-the-middle is
attempting to perform a buffer-stuffing attack (CVE-2021-23222).
Frontends should be coded either to read exactly one byte from the
socket before turning the socket over to their SSL library, or to
treat it as a protocol violation if they find they have read
additional bytes.An initial SSLRequest can also be used in a connection that is
being opened to send a CancelRequest message.While the protocol itself does not provide a way for the server to
force SSL encryption, the administrator can configure the server
to reject unencrypted sessions as a byproduct of authentication
checking.Has consideration been given to having something like
ssl-mode=tls-only where the SSLRequest message is skipped and the TLS
handshake starts immediately with the protocol continuing after that?This has several advantages:
1) One less round-trip when establishing the connection, speeding this
up. TLS 1.3 removed a round-trip and this was significant so it could
help.
2) No possibility of downgrading to non-TLS. (Not sure this is an
issue though.)
3) Connections work through normal TLS proxies and SNI can be used for
routing.This final advantage is the main reason I'd like to see this
implemented. Postgres is increasingly being run in multi-tenant
Kubernetes clusters where load-balancers and node ports are not
available, cost or don't scale and it is currently difficult to
connect to databases running there. If it was possible to use normal
ingress TLS proxies, running Postgres in Kubernetes would be much
easier and there are other use cases where just using TLS would be
beneficial as well.Questions about TLS SNI support have been asked for several years now
and this would be a big usability improvement. SNI support was
recently added to the client-side and this seems like the next logical
step.Thoughts?
Isn't that going to break every existing client? How is a client
supposed to know which protocol to follow?cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
Keith Burdis <keith@burdis.org> writes:
Has consideration been given to having something like ssl-mode=tls-only
where the SSLRequest message is skipped and the TLS handshake starts
immediately with the protocol continuing after that?
/messages/by-id/fcc3ebeb7f05775b63f3207ed52a54ea5d17fb42.camel@vmware.com
regards, tom lane
On Fri, 2021-12-24 at 14:08 +0000, Keith Burdis wrote:
Has consideration been given to having something like ssl-mode=tls-
only where the SSLRequest message is skipped and the TLS handshake
starts immediately with the protocol continuing after that?
From an implementation standpoint, I think I'd prefer to keep sslmode
independent from the new implicit-TLS setting, so that any existing
deployments can migrate to the new handshake without needing to change
their certificate setup. (That said, any sslmodes weaker than `require`
would be incompatible with the new setting.)
--Jacob