Обсуждение: Direct SSL connection and ALPN loose ends
There's been a bunch of bugs, and discussion on the intended behavior of sslnegotiation and ALPN. This email summarizes the current status: ## Status and loose ends for beta1 All reported bugs have now been fixed. We now enforce ALPN in all the right places. Please let me know if I missed something. There are two open items remaining that I intend to address in the next few days, before beta1: - I am going to rename sslnegotiation=requiredirect to sslnegotiation=directonly. I acknowledge that there is still some debate on this: Jacob (and Robert?) would prefer to change the behavior instead, so that sslnegotiation=requiredirect would also imply or require sslmode=require, while IMHO the settings should be orthogonal so that sslmode controls whether SSL is used or not, and sslnegotiation controls how the SSL layer is negotiated when SSL is used. Given that they are orthogonal, "directonly" is a better name. I will also take another look at the documentation, if it needs clarification on that point. If you have more comments on whether this is a good idea or not or how sslnegotiation should work, please reply on the other thread, let's keep this one focused on the overall status. [1] - The registration of the ALPN name with IANA hasn't been finished yet [2]. I originally requested the name "pgsql", but after Peter's comment, I changed the request to "postgresql". The string we have in 'master' is currently "TBD-pgsql". I'm very confident that the registration will go through with "postgresql", so my plan is to commit that change before beta1, even if the IANA process hasn't completed by then. ## V18 material - Add an option to disable traditional SSL negotiation in the server. There was discussion on doing this via HBA rules or as a global option, and the consensus seems to be for a global option. This would be just to reduce the attach surface, there is no known vulnerabilities or other issues with the traditional negotiation. And maybe to help with testing. [3] These are not directly related to sslnegotiation, but came up in the discussion: - Clarify the situation with sslmode=require and gssencmode=require combination, by replacing sslmode and gssencmode options with a single "encryption=[ssl|gss|none], [...]" option. [4] - Make sslmode=require the default. This is orthogonal to the SSL negotiation, but I think the root cause for the disagreements on sslnegotiation is actually that we'd like SSL to be the default. [5] The details of these need to be hashed out, in particular the backwards-compatibility and migration aspects, but the consensus seems to be that it's the right direction. ## V19 and beyond In the future, once v17 is ubiquitous and the ecosystem (pgbouncer etc) have added direct SSL support, we can change the default sslnegotiation from 'postgres' to 'direct'. I'm thinking 3-5 years from now. In the more distant future, we could remove the traditional SSLRequest negotiation altogether and always use direct SSL negotiation. There's no rush on these. ## Retrospective There were a lot more cleanups required for this work than I expected, given that there were little changes to the patches between January and March commitfests. I was mostly worried about the refactoring of the retry logic in libpq (and about the pre-existing logic too to be honest, it was complicated before these changes already). That's why I added a lot more tests for that. However, I did not foresee all the ALPN related issues. In hindsight, it would have been good to commit most of the ALPN changes first, and with more tests. Jacob wrote a python test suite; I should've played more with that, that could have demonstrated the ALPN issues earlier. [1] https://www.postgresql.org/message-id/CA%2BTgmobV9JEk4AFy61Xw%2B2%2BcCTBqdTsDopkeB%2Bgb81kq3f-o6A%40mail.gmail.com [2] https://mailarchive.ietf.org/arch/msg/tls-reg-review/9LWPzQfOpbc8dTT7vc9ahNeNaiw/ [3] https://www.postgresql.org/message-id/CA%2BTgmoaLpDVY2ywqQUfxvKEQZ%2Bnwkabcw_f%3Di4Zyivt9CLjcmA%40mail.gmail.com [4] https://www.postgresql.org/message-id/3a6f126c-e1aa-4dcc-9252-9868308f6cf0%40iki.fi [5] https://www.postgresql.org/message-id/CA%2BTgmoaNkRerEmB9JPgW0FhcJAe337AA%3D5kp6je9KekQhhRbmA%40mail.gmail.com -- Heikki Linnakangas Neon (https://neon.tech)
Hi,
With TLS 1.3 and others there is possibly a security flaw using ALPN [1].
It seems to me that the ALPN protocol can be bypassed if the client does not correctly inform the ClientHello header.
So, the suggestion is to check the ClientHello header in the server and
terminate the TLS handshake early.
Patch attached.
best regards,
Ranier Vilela
Вложения
On 29/04/2024 20:10, Ranier Vilela wrote: > Hi, > > With TLS 1.3 and others there is possibly a security flaw using ALPN [1]. > > It seems to me that the ALPN protocol can be bypassed if the client does > not correctly inform the ClientHello header. > > So, the suggestion is to check the ClientHello header in the server and > terminate the TLS handshake early. Sounds to me like it's working as designed. ALPN in general is optional; if the client doesn't request it, then you proceed without it. We do require ALPN for direct SSL connections though. We can, because direct SSL connections is a new feature in Postgres. But we cannot require it for the connections negotiated with SSLRequest, or we break compatibility with old clients that don't use ALPN. There is a check in direct SSL mode that ALPN was used (ProcessSSLStartup in backend_startup.c): > if (!port->alpn_used) > { > ereport(COMMERROR, > (errcode(ERRCODE_PROTOCOL_VIOLATION), > errmsg("received direct SSL connection request without ALPN protocol negotiation extension"))); > goto reject; > } That happens immediately after the SSL connection has been established. Hmm. I guess it would be better to abort the connection earlier, without completing the TLS handshake. Otherwise the client might send the first message in wrong protocol to the PostgreSQL server. That's not a security issue for the PostgreSQL server: the server disconnects without reading the message. And I don't see any way for an ALPACA attack when the server ignores the client's message. Nevertheless, from the point of view of keeping the attack surface as small as possible, aborting earlier seems better. -- Heikki Linnakangas Neon (https://neon.tech)
Em seg., 29 de abr. de 2024 às 14:56, Heikki Linnakangas <hlinnaka@iki.fi> escreveu:
On 29/04/2024 20:10, Ranier Vilela wrote:
> Hi,
>
> With TLS 1.3 and others there is possibly a security flaw using ALPN [1].
>
> It seems to me that the ALPN protocol can be bypassed if the client does
> not correctly inform the ClientHello header.
>
> So, the suggestion is to check the ClientHello header in the server and
> terminate the TLS handshake early.
Sounds to me like it's working as designed. ALPN in general is optional;
if the client doesn't request it, then you proceed without it. We do
require ALPN for direct SSL connections though. We can, because direct
SSL connections is a new feature in Postgres. But we cannot require it
for the connections negotiated with SSLRequest, or we break
compatibility with old clients that don't use ALPN.
Ok.
But what if I have a server configured for TLS 1.3 and that requires ALPN to allow access?
What about a client configured without ALPN requiring connection?
What about a client configured without ALPN requiring connection?
There is a check in direct SSL mode that ALPN was used
(ProcessSSLStartup in backend_startup.c):
> if (!port->alpn_used)
> {
> ereport(COMMERROR,
> (errcode(ERRCODE_PROTOCOL_VIOLATION),
> errmsg("received direct SSL connection request without ALPN protocol negotiation extension")));
> goto reject;
> }
That happens immediately after the SSL connection has been established.
Hmm. I guess it would be better to abort the connection earlier, without
completing the TLS handshake. Otherwise the client might send the first
message in wrong protocol to the PostgreSQL server. That's not a
security issue for the PostgreSQL server: the server disconnects without
reading the message. And I don't see any way for an ALPACA attack when
the server ignores the client's message. Nevertheless, from the point of
view of keeping the attack surface as small as possible, aborting
earlier seems better.
So the ClientHello callback is the correct way to determine the end.
best regards,
Ranier Vilela
On 29/04/2024 21:06, Ranier Vilela wrote: > Em seg., 29 de abr. de 2024 às 14:56, Heikki Linnakangas > <hlinnaka@iki.fi <mailto:hlinnaka@iki.fi>> escreveu: > > On 29/04/2024 20:10, Ranier Vilela wrote: > > Hi, > > > > With TLS 1.3 and others there is possibly a security flaw using > ALPN [1]. > > > > It seems to me that the ALPN protocol can be bypassed if the > client does > > not correctly inform the ClientHello header. > > > > So, the suggestion is to check the ClientHello header in the > server and > > terminate the TLS handshake early. > > Sounds to me like it's working as designed. ALPN in general is > optional; > if the client doesn't request it, then you proceed without it. We do > require ALPN for direct SSL connections though. We can, because direct > SSL connections is a new feature in Postgres. But we cannot require it > for the connections negotiated with SSLRequest, or we break > compatibility with old clients that don't use ALPN. > > Ok. > But what if I have a server configured for TLS 1.3 and that requires > ALPN to allow access? > What about a client configured without ALPN requiring connection? Sorry, I don't understand the questions. What about them? -- Heikki Linnakangas Neon (https://neon.tech)
Em seg., 29 de abr. de 2024 às 15:36, Heikki Linnakangas <hlinnaka@iki.fi> escreveu:
On 29/04/2024 21:06, Ranier Vilela wrote:
> Em seg., 29 de abr. de 2024 às 14:56, Heikki Linnakangas
> <hlinnaka@iki.fi <mailto:hlinnaka@iki.fi>> escreveu:
>
> On 29/04/2024 20:10, Ranier Vilela wrote:
> > Hi,
> >
> > With TLS 1.3 and others there is possibly a security flaw using
> ALPN [1].
> >
> > It seems to me that the ALPN protocol can be bypassed if the
> client does
> > not correctly inform the ClientHello header.
> >
> > So, the suggestion is to check the ClientHello header in the
> server and
> > terminate the TLS handshake early.
>
> Sounds to me like it's working as designed. ALPN in general is
> optional;
> if the client doesn't request it, then you proceed without it. We do
> require ALPN for direct SSL connections though. We can, because direct
> SSL connections is a new feature in Postgres. But we cannot require it
> for the connections negotiated with SSLRequest, or we break
> compatibility with old clients that don't use ALPN.
>
> Ok.
> But what if I have a server configured for TLS 1.3 and that requires
> ALPN to allow access?
> What about a client configured without ALPN requiring connection?
Sorry, I don't understand the questions. What about them?
Sorry, I'll try to be clearer.
The way it is designed, can we impose TLS 1.3 and ALPN to allow access to a public server?
And if on the other side we have a client, configured without ALPN,
The way it is designed, can we impose TLS 1.3 and ALPN to allow access to a public server?
And if on the other side we have a client, configured without ALPN,
when requesting access, the server will refuse?
best regards,
Ranier Vilela