Direct SSL connection with ALPN and HBA rules
Hi all,
(Heikki in CC.)
Since 91044ae4baea (require ALPN for direct SSL connections) and
d39a49c1e459 (direct hanshake), direct SSL connections are supported
(yeah!), still the thread where this has been discussed does not cover
the potential impact on HBA rules:
/messages/by-id/CAM-w4HOEAzxyY01ZKOj-iq=M4-VDk=vzQgUsuqiTFjFDZaebdg@mail.gmail.com
My point is, would there be a point in being able to enforce that ALPN
is used from the server rather than just relying on the client-side
sslnegotiation to decide if direct SSL connections should be forced or
not?
Hence, I'd imagine that we could have an HBA option for hostssl rules,
like a negotiation={direct,postgres,all} that cross-checks
Port->alpn_used with the option value in a hostssl entry, rejecting
the use of connections using direct connections or the default
protocol if these are not used, giving users a way to avoid one. As
this is a new thing, there may be an argument in this option for
security reasons, as well, so as it would be possible for operators to
turn that off in the server.
Thoughts or comments?
--
Michael
On 19/04/2024 08:06, Michael Paquier wrote:
Hi all,
(Heikki in CC.)
(Adding Jacob)
Since 91044ae4baea (require ALPN for direct SSL connections) and
d39a49c1e459 (direct hanshake), direct SSL connections are supported
(yeah!), still the thread where this has been discussed does not cover
the potential impact on HBA rules:
/messages/by-id/CAM-w4HOEAzxyY01ZKOj-iq=M4-VDk=vzQgUsuqiTFjFDZaebdg@mail.gmail.comMy point is, would there be a point in being able to enforce that ALPN
is used from the server rather than just relying on the client-side
sslnegotiation to decide if direct SSL connections should be forced or
not?Hence, I'd imagine that we could have an HBA option for hostssl rules,
like a negotiation={direct,postgres,all} that cross-checks
Port->alpn_used with the option value in a hostssl entry, rejecting
the use of connections using direct connections or the default
protocol if these are not used, giving users a way to avoid one. As
this is a new thing, there may be an argument in this option for
security reasons, as well, so as it would be possible for operators to
turn that off in the server.
I don't think ALPN gives any meaningful security benefit, when used with
the traditional 'postgres' SSL negotiation. There's little possibility
of mixing that up with some other protocol, so I don't see any need to
enforce it from server side. This was briefly discussed on that original
thread [1]/messages/by-id/CAAWbhmjetCVgu9pHJFkQ4ejuXuaz2mD1oniXokRHft0usCa7Yg@mail.gmail.com. With direct SSL negotiation, we always require ALPN.
I don't see direct SSL negotiation as a security feature. Rather, the
point is to reduce connection latency by saving one round-trip. For
example, if gssencmode=prefer, but the server refuses GSS encryption, it
seems fine to continue with negotiated SSL, instead of establishing a
new connection with direct SSL. What would be the use case of requiring
direct SSL in the server? What extra security do you get?
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user, the client would still establish a
direct SSL connection, send the startup packet, and only then get
rejected. The client would not know if it was rejected because of the
direct SSL or for some reason, so it needs to retry with negotiated SSL.
Currently, as it is master, if the TLS layer is established with direct
SSL, you never need to retry with traditional negotiation, or vice versa.
[1]: /messages/by-id/CAAWbhmjetCVgu9pHJFkQ4ejuXuaz2mD1oniXokRHft0usCa7Yg@mail.gmail.com
/messages/by-id/CAAWbhmjetCVgu9pHJFkQ4ejuXuaz2mD1oniXokRHft0usCa7Yg@mail.gmail.com
--
Heikki Linnakangas
Neon (https://neon.tech)
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
On 19/04/2024 08:06, Michael Paquier wrote:
Since 91044ae4baea (require ALPN for direct SSL connections) and
d39a49c1e459 (direct hanshake), direct SSL connections are supported
(yeah!), still the thread where this has been discussed does not cover
the potential impact on HBA rules:
/messages/by-id/CAM-w4HOEAzxyY01ZKOj-iq=M4-VDk=vzQgUsuqiTFjFDZaebdg@mail.gmail.comMy point is, would there be a point in being able to enforce that ALPN
is used from the server rather than just relying on the client-side
sslnegotiation to decide if direct SSL connections should be forced or
not?
I'm a little confused about whether we're talking about requiring ALPN
or requiring direct connections. I think you mean the latter, Michael?
Personally, I was hoping that we'd have a postgresql.conf option to
reject every network connection that wasn't direct SSL, but I ran out
of time to review the patchset for 17. I would like to see server-side
enforcement of direct SSL in some way, eventually. I hadn't given much
thought to HBA, though.
I don't think ALPN gives any meaningful security benefit, when used with
the traditional 'postgres' SSL negotiation. There's little possibility
of mixing that up with some other protocol, so I don't see any need to
enforce it from server side. This was briefly discussed on that original
thread [1].
Agreed. By the time you've issued a traditional SSL startup packet,
and the server responds with a go-ahead, it's pretty much understood
what protocol is in use.
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1]/messages/by-id/CAOYmi+=cnV-8V8TndSkEF6Htqa7qHQUL_KnQU8-DrT0Jjnm3_Q@mail.gmail.com.)
I don't see direct SSL negotiation as a security feature.
`direct` mode is not, since it's opportunistic, but I think people are
going to use `requiredirect` as a security feature. At least, I was
hoping to do that myself...
Rather, the
point is to reduce connection latency by saving one round-trip. For
example, if gssencmode=prefer, but the server refuses GSS encryption, it
seems fine to continue with negotiated SSL, instead of establishing a
new connection with direct SSL.
Well, assuming the user is okay with plaintext negotiation at all.
(Was that fixed before the patch went in? Is GSS negotiation still
allowed even with requiredirect?)
What would be the use case of requiring
direct SSL in the server? What extra security do you get?
You get protection against attacks that could have otherwise happened
during the plaintext portion of the handshake. That has architectural
implications for more advanced uses of SCRAM, and it should prevent
any repeats of CVE-2021-23222/23214. And if the peer doesn't pass the
TLS handshake, they can't send you anything that you might forget is
untrusted (like, say, an error message).
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user,
Hopefully disabling direct SSL piecemeal is not a desired use case?
I'm not sure it makes sense to focus on that. Forcing it to be enabled
shouldn't have the same problem, should it?
--Jacob
[1]: /messages/by-id/CAOYmi+=cnV-8V8TndSkEF6Htqa7qHQUL_KnQU8-DrT0Jjnm3_Q@mail.gmail.com
On 19/04/2024 19:48, Jacob Champion wrote:
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1].)
Ah, good catch, that fell through the cracks. Agreed, the client should
reject a direct SSL connection if the server didn't send ALPN. I'll add
that to the Open Items so we don't forget again.
I don't see direct SSL negotiation as a security feature.
`direct` mode is not, since it's opportunistic, but I think people are
going to use `requiredirect` as a security feature. At least, I was
hoping to do that myself...Rather, the
point is to reduce connection latency by saving one round-trip. For
example, if gssencmode=prefer, but the server refuses GSS encryption, it
seems fine to continue with negotiated SSL, instead of establishing a
new connection with direct SSL.Well, assuming the user is okay with plaintext negotiation at all.
(Was that fixed before the patch went in? Is GSS negotiation still
allowed even with requiredirect?)
To disable sending the startup packet in plaintext, you need to use
sslmode=require. Same as before the patch. GSS is still allowed, as it
takes precedence over SSL if both are enabled in libpq. Per the docs:
Note that if gssencmode is set to prefer, a GSS connection is
attempted first. If the server rejects GSS encryption, SSL is
negotiated over the same TCP connection using the traditional
postgres protocol, regardless of sslnegotiation. In other words, the
direct SSL handshake is not used, if a TCP connection has already
been established and can be used for the SSL handshake.
What would be the use case of requiring
direct SSL in the server? What extra security do you get?You get protection against attacks that could have otherwise happened
during the plaintext portion of the handshake. That has architectural
implications for more advanced uses of SCRAM, and it should prevent
any repeats of CVE-2021-23222/23214. And if the peer doesn't pass the
TLS handshake, they can't send you anything that you might forget is
untrusted (like, say, an error message).
Can you elaborate on the more advanced uses of SCRAM?
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user,Hopefully disabling direct SSL piecemeal is not a desired use case?
I'm not sure it makes sense to focus on that. Forcing it to be enabled
shouldn't have the same problem, should it?
Forcing it to be enabled piecemeal based on role or database has similar
problems. Forcing it enabled for all connections seems sensible, though.
Forcing it enabled based on the client's source IP address, but not
user/database would be somewhat sensible too, but we don't currently
have the HBA code to check the source IP and accept/reject SSLRequest
based on that. The HBA rejection always happens after the client has
sent the startup packet.
--
Heikki Linnakangas
Neon (https://neon.tech)
On Sat, Apr 20, 2024 at 12:43:24AM +0300, Heikki Linnakangas wrote:
On 19/04/2024 19:48, Jacob Champion wrote:
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1].)Ah, good catch, that fell through the cracks. Agreed, the client should
reject a direct SSL connection if the server didn't send ALPN. I'll add that
to the Open Items so we don't forget again.
Would somebody like to write a patch for that? I'm planning to look
at this code more closely, as well.
You get protection against attacks that could have otherwise happened
during the plaintext portion of the handshake. That has architectural
implications for more advanced uses of SCRAM, and it should prevent
any repeats of CVE-2021-23222/23214. And if the peer doesn't pass the
TLS handshake, they can't send you anything that you might forget is
untrusted (like, say, an error message).Can you elaborate on the more advanced uses of SCRAM?
I'm not sure what you mean here, either, Jacob.
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user,Hopefully disabling direct SSL piecemeal is not a desired use case?
I'm not sure it makes sense to focus on that. Forcing it to be enabled
shouldn't have the same problem, should it?
I'd get behind the case where a server rejects everything except
direct SSL, yeah. Sticking that into a format similar to HBA rules
would easily give the flexibility to be able to accept or reject
direct or default SSL, though, while making it easy to parse. The
implementation is not really complicated, and not far from the
existing hostssl and nohostssl.
As a whole, I can get behind a unique GUC that forces the use of
direct. Or, we could extend the existing "ssl" GUC with a new
"direct" value to accept only direct connections and restrict the
original protocol (and a new "postgres" for the pre-16 protocol,
rejecting direct?), while "on" is able to accept both.
Forcing it to be enabled piecemeal based on role or database has similar
problems. Forcing it enabled for all connections seems sensible, though.
Forcing it enabled based on the client's source IP address, but not
user/database would be somewhat sensible too, but we don't currently have
the HBA code to check the source IP and accept/reject SSLRequest based on
that. The HBA rejection always happens after the client has sent the startup
packet.
Hmm. Splitting the logic checking HBA entries (around check_hba) so
as we'd check for a portion of its contents depending on what the
server has received or not from the client would not be that
complicated. I'd question whether it makes sense to mix this
information within the same configuration files as the ones holding
the current HBA rules. If the same rules are used for the
pre-startup-packet phase and the post-startup-packet phase, we'd want
new keywords for these HBA rules, something different than the
existing sslmode and no sslmode?
--
Michael
On 22/04/2024 10:19, Michael Paquier wrote:
On Sat, Apr 20, 2024 at 12:43:24AM +0300, Heikki Linnakangas wrote:
On 19/04/2024 19:48, Jacob Champion wrote:
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1].)Ah, good catch, that fell through the cracks. Agreed, the client should
reject a direct SSL connection if the server didn't send ALPN. I'll add that
to the Open Items so we don't forget again.Would somebody like to write a patch for that? I'm planning to look
at this code more closely, as well.
I plan to write the patch later today.
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user,Hopefully disabling direct SSL piecemeal is not a desired use case?
I'm not sure it makes sense to focus on that. Forcing it to be enabled
shouldn't have the same problem, should it?I'd get behind the case where a server rejects everything except
direct SSL, yeah. Sticking that into a format similar to HBA rules
would easily give the flexibility to be able to accept or reject
direct or default SSL, though, while making it easy to parse. The
implementation is not really complicated, and not far from the
existing hostssl and nohostssl.As a whole, I can get behind a unique GUC that forces the use of
direct. Or, we could extend the existing "ssl" GUC with a new
"direct" value to accept only direct connections and restrict the
original protocol (and a new "postgres" for the pre-16 protocol,
rejecting direct?), while "on" is able to accept both.
I'd be OK with that, although I still don't really see the point of
forcing this from the server side. We could also add this later.
Forcing it to be enabled piecemeal based on role or database has similar
problems. Forcing it enabled for all connections seems sensible, though.
Forcing it enabled based on the client's source IP address, but not
user/database would be somewhat sensible too, but we don't currently have
the HBA code to check the source IP and accept/reject SSLRequest based on
that. The HBA rejection always happens after the client has sent the startup
packet.Hmm. Splitting the logic checking HBA entries (around check_hba) so
as we'd check for a portion of its contents depending on what the
server has received or not from the client would not be that
complicated. I'd question whether it makes sense to mix this
information within the same configuration files as the ones holding
the current HBA rules. If the same rules are used for the
pre-startup-packet phase and the post-startup-packet phase, we'd want
new keywords for these HBA rules, something different than the
existing sslmode and no sslmode?
Sounds complicated, and I don't really see the use case for controlling
the direct SSL support in such a fine-grained fashion.
It would be nice if we could reject non-SSL connections before the
client sends the startup packet, but that's not possible because in a
plaintext connection, that's the first packet that the client sends. The
reverse would be possible: reject SSLRequest or direct SSL connection
immediately, if HBA doesn't allow non-SSL connections from that IP
address. But that's not very interesting.
HBA-based control would certainly be v18 material.
--
Heikki Linnakangas
Neon (https://neon.tech)
On 22/04/2024 10:47, Heikki Linnakangas wrote:
On 22/04/2024 10:19, Michael Paquier wrote:
On Sat, Apr 20, 2024 at 12:43:24AM +0300, Heikki Linnakangas wrote:
On 19/04/2024 19:48, Jacob Champion wrote:
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1].)Ah, good catch, that fell through the cracks. Agreed, the client should
reject a direct SSL connection if the server didn't send ALPN. I'll add that
to the Open Items so we don't forget again.Would somebody like to write a patch for that? I'm planning to look
at this code more closely, as well.I plan to write the patch later today.
Here's the patch for that. The error message is:
"direct SSL connection was established without ALPN protocol negotiation
extension"
That's accurate, but I wonder if we could make it more useful to a user
who's wondering what went wrong. I'd imagine that if the server doesn't
support ALPN, it's because you have some kind of a (not necessarily
malicious) generic SSL man-in-the-middle that doesn't support it. Or
you're trying to connect to an HTTPS server. Suggestions welcome.
--
Heikki Linnakangas
Neon (https://neon.tech)
Attachments:
require-alpn-in-direct-mode.patchtext/x-patch; charset=UTF-8; name=require-alpn-in-direct-mode.patchDownload+34-0
On Mon, Apr 22, 2024 at 10:47:51AM +0300, Heikki Linnakangas wrote:
On 22/04/2024 10:19, Michael Paquier wrote:
As a whole, I can get behind a unique GUC that forces the use of
direct. Or, we could extend the existing "ssl" GUC with a new
"direct" value to accept only direct connections and restrict the
original protocol (and a new "postgres" for the pre-16 protocol,
rejecting direct?), while "on" is able to accept both.I'd be OK with that, although I still don't really see the point of forcing
this from the server side. We could also add this later.
I'd be OK with doing something only in v18, if need be. Jacob, what
do you think?
Hmm. Splitting the logic checking HBA entries (around check_hba) so
as we'd check for a portion of its contents depending on what the
server has received or not from the client would not be that
complicated. I'd question whether it makes sense to mix this
information within the same configuration files as the ones holding
the current HBA rules. If the same rules are used for the
pre-startup-packet phase and the post-startup-packet phase, we'd want
new keywords for these HBA rules, something different than the
existing sslmode and no sslmode?Sounds complicated, and I don't really see the use case for controlling the
direct SSL support in such a fine-grained fashion.It would be nice if we could reject non-SSL connections before the client
sends the startup packet, but that's not possible because in a plaintext
connection, that's the first packet that the client sends. The reverse would
be possible: reject SSLRequest or direct SSL connection immediately, if HBA
doesn't allow non-SSL connections from that IP address. But that's not very
interesting.
I'm not completely sure, actually. We have the APIs to do that in
simple ways with existing keywords and new options. And there is some
merit being able to have more complex connection policies. If both of
you object to that, I won't insist.
HBA-based control would certainly be v18 material.
Surely.
--
Michael
On Tue, Apr 23, 2024 at 01:48:04AM +0300, Heikki Linnakangas wrote:
Here's the patch for that. The error message is:
"direct SSL connection was established without ALPN protocol negotiation
extension"
WFM.
That's accurate, but I wonder if we could make it more useful to a user
who's wondering what went wrong. I'd imagine that if the server doesn't
support ALPN, it's because you have some kind of a (not necessarily
malicious) generic SSL man-in-the-middle that doesn't support it. Or you're
trying to connect to an HTTPS server. Suggestions welcome.
Hmm. Is there any point in calling SSL_get0_alpn_selected() in
open_client_SSL() to get the ALPN if current_enc_method is not
ENC_DIRECT_SSL?
In the documentation of PQsslAttribute(), it is mentioned that empty
string is returned for "alpn" if ALPN was not used, however the code
returns NULL in this case:
SSL_get0_alpn_selected(conn->ssl, &data, &len);
if (data == NULL || len == 0 || len > sizeof(alpn_str) - 1)
return NULL;
--
Michael
On Fri, Apr 19, 2024 at 2:43 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
On 19/04/2024 19:48, Jacob Champion wrote:
On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
With direct SSL negotiation, we always require ALPN.
(As an aside: I haven't gotten to test the version of the patch that
made it into 17 yet, but from a quick glance it looks like we're not
rejecting mismatched ALPN during the handshake as noted in [1].)Ah, good catch, that fell through the cracks. Agreed, the client should
reject a direct SSL connection if the server didn't send ALPN. I'll add
that to the Open Items so we don't forget again.
Yes, the client should also reject, but that's not what I'm referring
to above. The server needs to fail the TLS handshake itself with the
proper error code (I think it's `no_application_protocol`?); otherwise
a client implementing a different protocol could consume the
application-level bytes coming back from the server and act on them.
That's the protocol confusion attack from ALPACA we're trying to
avoid.
Well, assuming the user is okay with plaintext negotiation at all.
(Was that fixed before the patch went in? Is GSS negotiation still
allowed even with requiredirect?)To disable sending the startup packet in plaintext, you need to use
sslmode=require. Same as before the patch. GSS is still allowed, as it
takes precedence over SSL if both are enabled in libpq. Per the docs:Note that if gssencmode is set to prefer, a GSS connection is
attempted first. If the server rejects GSS encryption, SSL is
negotiated over the same TCP connection using the traditional
postgres protocol, regardless of sslnegotiation. In other words, the
direct SSL handshake is not used, if a TCP connection has already
been established and can be used for the SSL handshake.
Oh. That's actually disappointing, since gssencmode=prefer is the
default. A question I had in the original thread was, what's the
rationale behind a "require direct ssl" option that doesn't actually
require it?
What would be the use case of requiring
direct SSL in the server? What extra security do you get?You get protection against attacks that could have otherwise happened
during the plaintext portion of the handshake. That has architectural
implications for more advanced uses of SCRAM, and it should prevent
any repeats of CVE-2021-23222/23214. And if the peer doesn't pass the
TLS handshake, they can't send you anything that you might forget is
untrusted (like, say, an error message).Can you elaborate on the more advanced uses of SCRAM?
If you're using SCRAM to authenticate the server, as opposed to just a
really strong password auth, then it really helps an analysis of the
security to know that there are no plaintext bytes that have been
interpreted by the client. This came up briefly in the conversations
that led to commit d0f4824a.
To be fair, it's a more academic concern at the moment; my imagination
can only come up with problems for SCRAM-based TLS that would also be
vulnerabilities for standard certificate-based TLS. But whether or not
it's an advantage for the code today is also kind of orthogonal to my
point. The security argument of direct SSL mode is that it reduces
risk for the system as a whole, even in the face of future code
changes or regressions. If you can't force its use, you're not
reducing that risk very much. (If anything, a "require" option that
doesn't actually require it makes the analysis more complicated, not
less...)
Controlling these in HBA is a bit inconvenient, because you only find
out after authentication if it's allowed or not. So if e.g. direct SSL
connections are disabled for a user,Hopefully disabling direct SSL piecemeal is not a desired use case?
I'm not sure it makes sense to focus on that. Forcing it to be enabled
shouldn't have the same problem, should it?Forcing it to be enabled piecemeal based on role or database has similar
problems.
Hm. For some reason I thought it was easier the other direction, but I
can't remember why I thought that. I'll withdraw the comment for now
:)
--Jacob
On Mon, Apr 22, 2024 at 10:42 PM Michael Paquier <michael@paquier.xyz> wrote:
On Mon, Apr 22, 2024 at 10:47:51AM +0300, Heikki Linnakangas wrote:
On 22/04/2024 10:19, Michael Paquier wrote:
As a whole, I can get behind a unique GUC that forces the use of
direct. Or, we could extend the existing "ssl" GUC with a new
"direct" value to accept only direct connections and restrict the
original protocol (and a new "postgres" for the pre-16 protocol,
rejecting direct?), while "on" is able to accept both.I'd be OK with that, although I still don't really see the point of forcing
this from the server side. We could also add this later.I'd be OK with doing something only in v18, if need be. Jacob, what
do you think?
I think it would be nice to have an option like that. Whether it's
done now or in 18, I don't have a strong opinion about. But I do think
it'd be helpful to have a consensus on whether or not this is a
security improvement, or a performance enhancement only, before adding
said option. As it's implemented, if the requiredirect option doesn't
actually requiredirect, I think it looks like security but isn't
really.
(My ideal server-side option removes all plaintext negotiation and
forces the use of direct SSL for every connection, paired with a new
postgresqls:// scheme for the client. But I don't have any experience
making a switchover like that at scale, and I'd like to avoid a
StartTLS-vs-LDAPS sort of situation. That's obviously not a
conversation for 17.)
As for HBA control: overall, I don't see a burning need for an
HBA-based configuration, honestly. I'd prefer to reduce the number of
knobs and make it easier to apply the strongest security with a broad
brush.
--Jacob
On Tue, Apr 23, 2024 at 1:22 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
On Mon, Apr 22, 2024 at 10:42 PM Michael Paquier <michael@paquier.xyz> wrote:
On Mon, Apr 22, 2024 at 10:47:51AM +0300, Heikki Linnakangas wrote:
On 22/04/2024 10:19, Michael Paquier wrote:
As a whole, I can get behind a unique GUC that forces the use of
direct. Or, we could extend the existing "ssl" GUC with a new
"direct" value to accept only direct connections and restrict the
original protocol (and a new "postgres" for the pre-16 protocol,
rejecting direct?), while "on" is able to accept both.I'd be OK with that, although I still don't really see the point of forcing
this from the server side. We could also add this later.I'd be OK with doing something only in v18, if need be. Jacob, what
do you think?I think it would be nice to have an option like that. Whether it's
done now or in 18, I don't have a strong opinion about. But I do think
it'd be helpful to have a consensus on whether or not this is a
security improvement, or a performance enhancement only, before adding
said option. As it's implemented, if the requiredirect option doesn't
actually requiredirect, I think it looks like security but isn't
really.
I've not followed this thread closely enough to understand the comment
about requiredirect maybe not actually requiring direct, but if that
were true it seems like it might be concerning.
But as far as having a GUC to force direct SSL or not, I agree that's
a good idea, and that it's better than only being able to control the
behavior through pg_hba.conf, because it removes room for any possible
doubt about whether you're really enforcing the behavior you want to
be enforcing. It might also mean that the connection can be rejected
earlier in the handshaking process on the basis of the GUC value,
which could conceivably prevent a client from reaching some piece of
code that turns out to have a security vulnerability. For example, if
we found out that direct SSL connections let you take over the
Pentagon before reaching the authentication stage, but for some reason
regular connections don't have the same problem, being able to
categorically shut off direct SSL would be valuable.
However, I don't really see why this has to be done for this release.
It seems like a separate feature from direct SSL itself. If direct SSL
hadn't been committed at the very last minute, then it would have been
great if this had been done for this release, too. But it was. The
moral we ought to take from that is "perhaps get the big features in a
bit further in advance of the freeze," not "well we'll just keep
hacking after the freeze."
--
Robert Haas
EDB: http://www.enterprisedb.com
On Tue, Apr 23, 2024 at 10:43 AM Robert Haas <robertmhaas@gmail.com> wrote:
I've not followed this thread closely enough to understand the comment
about requiredirect maybe not actually requiring direct, but if that
were true it seems like it might be concerning.
It may be my misunderstanding. This seems to imply bad behavior:
If the server rejects GSS encryption, SSL is
negotiated over the same TCP connection using the traditional postgres
protocol, regardless of <literal>sslnegotiation</literal>.
As does this comment:
+ /* + * If enabled, try direct SSL. Unless we have a valid TCP connection that + * failed negotiating GSSAPI encryption or a plaintext connection in case + * of sslmode='allow'; in that case we prefer to reuse the connection with + * negotiated SSL, instead of reconnecting to do direct SSL. The point of + * direct SSL is to avoid the roundtrip from the negotiation, but + * reconnecting would also incur a roundtrip. + */
but when I actually try those cases, I see that requiredirect does
actually cause a direct SSL connection to be done, even with
sslmode=allow. So maybe it's just misleading documentation (or my
misreading of it) that needs to be expanded? Am I missing a different
corner case where requiredirect is ignored, Heikki?
I still question the utility of allowing sslmode=allow with
sslnegotiation=requiredirect, because it seems like you've made both
the performance and security characteristics actively worse if you
choose that combination. But I want to make sure I understand the
current behavior correctly before I derail the discussion too much...
Thanks,
--Jacob
On 23/04/2024 22:33, Jacob Champion wrote:
On Tue, Apr 23, 2024 at 10:43 AM Robert Haas <robertmhaas@gmail.com> wrote:
I've not followed this thread closely enough to understand the comment
about requiredirect maybe not actually requiring direct, but if that
were true it seems like it might be concerning.It may be my misunderstanding. This seems to imply bad behavior:
If the server rejects GSS encryption, SSL is
negotiated over the same TCP connection using the traditional postgres
protocol, regardless of <literal>sslnegotiation</literal>.As does this comment:
+ /* + * If enabled, try direct SSL. Unless we have a valid TCP connection that + * failed negotiating GSSAPI encryption or a plaintext connection in case + * of sslmode='allow'; in that case we prefer to reuse the connection with + * negotiated SSL, instead of reconnecting to do direct SSL. The point of + * direct SSL is to avoid the roundtrip from the negotiation, but + * reconnecting would also incur a roundtrip. + */but when I actually try those cases, I see that requiredirect does
actually cause a direct SSL connection to be done, even with
sslmode=allow. So maybe it's just misleading documentation (or my
misreading of it) that needs to be expanded? Am I missing a different
corner case where requiredirect is ignored, Heikki?
You're right, the comment is wrong about sslmode=allow. There is no
negotiation of a plaintext connection, the client just sends the startup
packet directly. The HBA rules can reject it, but the client will have
to disconnect and reconnect in that case.
The documentation and that comment are misleading about failed GSSAPI
encryption too, and I also misremembered that. With
sslnegotiation=requiredirect, libpq never uses negotiated SSL mode. It
will reconnect after a rejected GSSAPI request. So that comment applies
to sslnegotiation=direct, but not sslnegotiation=requiredirect.
Attached patch tries to fix and clarify those.
(Note that the client will only attempt GSSAPI encryption if it can find
kerberos credentials in the environment.)
--
Heikki Linnakangas
Neon (https://neon.tech)
Attachments:
0001-Fix-documentation-and-comments-on-what-happens-after.patchtext/x-patch; charset=UTF-8; name=0001-Fix-documentation-and-comments-on-what-happens-after.patchDownload+15-16
On Tue, Apr 23, 2024 at 2:20 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
Attached patch tries to fix and clarify those.
s/negotiatied/negotiated/ in the attached patch, but other than that
this seems like a definite improvement. Thanks!
(Note that the client will only attempt GSSAPI encryption if it can find
kerberos credentials in the environment.)
Right. I don't like that it still happens with
sslnegotiation=requiredirect, but I suspect that this is not the
thread to complain about it in. Maybe I can propose a
sslnegotiation=forcedirect or something for 18, to complement a
postgresqls:// scheme.
That leaves the ALPACA handshake correction, I think. (Peter had some
questions on the original thread [1]/messages/by-id/e782e9f4-a0cd-49f5-800b-5e32a1b29183@eisentraut.org that I've tried to answer.) And
the overall consensus, or lack thereof, on whether or not
`requiredirect` should be considered a security feature.
Thanks,
--Jacob
[1]: /messages/by-id/e782e9f4-a0cd-49f5-800b-5e32a1b29183@eisentraut.org
On Thu, Apr 25, 2024 at 12:16 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote
Right. I don't like that it still happens with
sslnegotiation=requiredirect, but I suspect that this is not the
thread to complain about it in. Maybe I can propose a
sslnegotiation=forcedirect or something for 18, to complement a
postgresqls:// scheme.
It is difficult to imagine a world in which we have both requiredirect
and forcedirect and people are not confused.
--
Robert Haas
EDB: http://www.enterprisedb.com
On Thu, Apr 25, 2024 at 9:17 AM Robert Haas <robertmhaas@gmail.com> wrote:
It is difficult to imagine a world in which we have both requiredirect
and forcedirect and people are not confused.
Yeah... Any thoughts on a better scheme? require_auth was meant to
lock down overly general authentication; maybe a require_proto or
something could do the same for the transport?
I hate that we have so many options that most people don't need but
take precedence, especially when they're based on the existence of
magic third-party environmental cues (e.g. Kerberos caches). And it
was nice that we got sslrootcert=system to turn on strong security and
reject nonsensical combinations. If someone sets `requiredirect` and
leaves the default sslmode, or chooses a weaker one... Is that really
useful to someone?
--Jacob
On Thu, Apr 25, 2024 at 12:28 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
On Thu, Apr 25, 2024 at 9:17 AM Robert Haas <robertmhaas@gmail.com> wrote:
It is difficult to imagine a world in which we have both requiredirect
and forcedirect and people are not confused.Yeah... Any thoughts on a better scheme? require_auth was meant to
lock down overly general authentication; maybe a require_proto or
something could do the same for the transport?
I don't understand the difference between the two sets of semantics
myself, so I'm not in a good position to comment.
I hate that we have so many options that most people don't need but
take precedence, especially when they're based on the existence of
magic third-party environmental cues (e.g. Kerberos caches). And it
was nice that we got sslrootcert=system to turn on strong security and
reject nonsensical combinations. If someone sets `requiredirect` and
leaves the default sslmode, or chooses a weaker one... Is that really
useful to someone?
Maybe I'm missing something here, but why doesn't sslnegotiation
override sslmode completely? Or alternatively, why not remove
sslnegotiation entirely and just have more sslmode values? I mean
maybe this shouldn't happen categorically, but if I say I want to
require a direct SSL connection, to me that implies that I don't want
an indirect SSL connection, and I really don't want a non-SSL
connection.
I think it's pretty questionable in 2024 whether sslmode=allow and
sslmode=prefer make any sense at all. I don't think it would be crazy
to remove them entirely. But I certainly don't think that they should
be allowed to bleed into the behavior of new, higher-security
configurations. Surely if I say I want direct SSL, it's that or
nothing, right?
--
Robert Haas
EDB: http://www.enterprisedb.com
On Thu, Apr 25, 2024 at 10:35 AM Robert Haas <robertmhaas@gmail.com> wrote:
Maybe I'm missing something here, but why doesn't sslnegotiation
override sslmode completely? Or alternatively, why not remove
sslnegotiation entirely and just have more sslmode values? I mean
maybe this shouldn't happen categorically, but if I say I want to
require a direct SSL connection, to me that implies that I don't want
an indirect SSL connection, and I really don't want a non-SSL
connection.
I think that comes down to the debate upthread, and whether you think
it's a performance tweak or a security feature. My take on it is,
`direct` mode is performance, and `requiredirect` is security.
(Especially since, with the current implementation, requiredirect can
slow things down?)
I think it's pretty questionable in 2024 whether sslmode=allow and
sslmode=prefer make any sense at all. I don't think it would be crazy
to remove them entirely. But I certainly don't think that they should
be allowed to bleed into the behavior of new, higher-security
configurations. Surely if I say I want direct SSL, it's that or
nothing, right?
I agree, but I more or less lost the battle at [1]/messages/by-id/CAOYmi+=cnV-8V8TndSkEF6Htqa7qHQUL_KnQU8-DrT0Jjnm3_Q@mail.gmail.com. Like Matthias
mentioned in [2]/messages/by-id/CAEze2Wi9j5Q3mRnuoD2Hr=eOFV-cMzWAUZ88YmSXSwsiJLQOWA@mail.gmail.com:
I'm not sure about this either. The 'gssencmode' option is already
quite weird in that it seems to override the "require"d priority of
"sslmode=require", which it IMO really shouldn't.
Thanks,
--Jacob
[1]: /messages/by-id/CAOYmi+=cnV-8V8TndSkEF6Htqa7qHQUL_KnQU8-DrT0Jjnm3_Q@mail.gmail.com
[2]: /messages/by-id/CAEze2Wi9j5Q3mRnuoD2Hr=eOFV-cMzWAUZ88YmSXSwsiJLQOWA@mail.gmail.com
On 25/04/2024 21:13, Jacob Champion wrote:
On Thu, Apr 25, 2024 at 10:35 AM Robert Haas <robertmhaas@gmail.com> wrote:
Maybe I'm missing something here, but why doesn't sslnegotiation
override sslmode completely? Or alternatively, why not remove
sslnegotiation entirely and just have more sslmode values? I mean
maybe this shouldn't happen categorically, but if I say I want to
require a direct SSL connection, to me that implies that I don't want
an indirect SSL connection, and I really don't want a non-SSL
connection.
My thinking with sslnegotiation is that it controls how SSL is
negotiated with the server, if SSL is to be used at all. It does not
control whether SSL is used or required; that's what sslmode is for.
I think that comes down to the debate upthread, and whether you think
it's a performance tweak or a security feature. My take on it is,
`direct` mode is performance, and `requiredirect` is security.
Agreed, although the the security benefits from `requiredirect` are
pretty vague. It reduces the attack surface, but there are no known
issues with the 'postgres' or 'direct' negotiation either.
Perhaps 'requiredirect' should be renamed to 'directonly'?
(Especially since, with the current implementation, requiredirect can
slow things down?)
Yes: the case is gssencmode=prefer, kerberos credentical cache present
in client, and server doesn't support GSS. With
sslnegotiation='postgres' or 'direct', libpq can do the SSL negotiation
over the same TCP connection after the server rejected the GSSRequest.
With sslnegotiation='requiredirect', it needs to open a new TCP connection.
I think it's pretty questionable in 2024 whether sslmode=allow and
sslmode=prefer make any sense at all. I don't think it would be crazy
to remove them entirely. But I certainly don't think that they should
be allowed to bleed into the behavior of new, higher-security
configurations. Surely if I say I want direct SSL, it's that or
nothing, right?I agree, but I more or less lost the battle at [1]. Like Matthias
mentioned in [2]:I'm not sure about this either. The 'gssencmode' option is already
quite weird in that it seems to override the "require"d priority of
"sslmode=require", which it IMO really shouldn't.
Yeah, that combination is weird. I think we should forbid it. But that's
separate from sslnegotiation.
--
Heikki Linnakangas
Neon (https://neon.tech)