Re: Experiments with Postgres and SSL
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: PostgreSQL-development <pgsql-hackers@postgresql.org>
Cc: Greg Stark <stark@mit.edu>, Andrey Borodin <amborodin86@gmail.com>,
Jacob Champion <jchampion@timescale.com>,
Vladimir Sitnikov <sitnikov.vladimir@gmail.com>,
Michael Paquier <michael@paquier.xyz>
Date: 2024-01-10T08:30:49Z
Lists: pgsql-hackers
Attachments
- v7-0001-Move-Kerberos-module.patch (text/x-patch) patch v7-0001
- v7-0002-Add-enc-tests.patch (text/x-patch) patch v7-0002
- v7-0003-Direct-SSL-connections-postmaster-support.patch (text/x-patch) patch v7-0003
- v7-0004-WIP-refactorings-to-backend-support.patch (text/x-patch) patch v7-0004
- v7-0005-Direct-SSL-connections-client-support.patch (text/x-patch) patch v7-0005
- v7-0006-Direct-SSL-connections-documentation.patch (text/x-patch) patch v7-0006
- v7-0007-Direct-SSL-connections-ALPN-support.patch (text/x-patch) patch v7-0007
- v7-0008-Allow-pipelining-data-after-ssl-request.patch (text/x-patch) patch v7-0008
- v7-0009-Direct-SSL-connections-some-additional-docs.patch (text/x-patch) patch v7-0009
- v7-0010-Move-code-to-check-for-alpn.patch (text/x-patch) patch v7-0010
- v7-0011-WIP-refactor-state-machine-in-libpq.patch (text/x-patch) patch v7-0011
- v7-0012-Add-tests-for-sslnegotiation.patch (text/x-patch) patch v7-0012
Some more comments on this: 1. It feels weird that the combination of "gssencmode=require sslnegotiation=direct" combination is forbidden. Sure, the ssl negotiation will never happen with gssencmode=require, so the sslnegotiation option has no effect. But by that token, should we also forbid the combination "sslmode=disable sslnegotiation=direct"? I think not. The sslnegotiation option should mean "if we are going to try SSL, should we try it in direct or negotiated mode?" 2. Should we allow direct SSL only at the very beginning of a TCP connection, or should we also allow it after we have requested GSS and the server said no? Like this: Client: GSSENCRequest Server: 'N' (gss not supported) Client: TLS client Hello On one hand, why not? It saves you a round-trip in this case too. If we don't allow it, the client will have to send SSLRequest and wait for response, or reconnect to try direct SSL. On the other hand, flexibility is not necessarily a good thing in security-critical code like this. The patch set is confused on whether that's allowed or not. The server rejects it. But if you use "gssencmode=prefer sslnegotiation=requiredrect", libpq will attempt to do it, and fail. 3. With "sslmode=verify-full sslnegotiation=direct", if the direct SSL connection fails because of a problem with the certificate, libpq will try again in negotiated SSL mode. That seems pointless. If the server responded to the direct TLS Client Hello message with a valid ServerHello, that indicates that the server supports direct SSL. If anything goes wrong after that, retrying in negotiated mode is not going to help. 4. The number of combinations of sslmode, gssencmode and sslnegotiation settings is scary. And we have very few tests for them. Attached patch set addresses the above, but is very much WIP. I refactored the state machine in libpq, to make the states and transitions more clear. I think that helps, but it's still pretty complex. I'm all ears for ideas on how to simplify it further. I added a new test suite to test the different libpq options. See src/test/libpq_encryption. I think this is very much needed, but I'm still not very happy with the implementation. Some combinations are still impossible to test, like connecting to an older server that doesn't support direct SSL, or having the server respond with 'N' to GSSEncRequest. I'd also like to check more details of each connection attempt, like how many TCP connections are established, to check for things like 3. above. Maybe we need to add more logging to libpq or the server and check the logs after each test. I'm tempted to implement a mock server from scratch that could easily be instructed to accept/reject the connection at just the right places. But that's a lot of work. I'm going to put this down for now. The attached patch set is even more raw than v6, but I'm including it here to "save the work". -- Heikki Linnakangas Neon (https://neon.tech)
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Enhance libpq encryption negotiation tests with new GUC
- 705843d294d5 17.0 landed
-
With gssencmode='require', check credential cache before connecting
- 20f9b61cc192 17.0 landed
-
Add tests for libpq gssencmode and sslmode options
- 1169920ff770 17.0 landed
-
Move Kerberos module
- 9f899562d420 17.0 landed
-
Give nicer error message when connecting to a v10 server requiring SCRAM.
- 96d0f988b150 9.4.12 cited