postgresql/src/backend/libpq
Daniel Gustafsson 4f433025f6 ssl: Serverside SNI support for libpq
Support for SNI was added to clientside libpq in 5c55dc8b47 with the
sslsni parameter, but there was no support for utilizing it serverside.
This adds support for serverside SNI such that certificate/key handling
is available per host.  A new config file, $datadir/pg_hosts.conf, is
used for configuring which certificate and key should be used for which
hostname.  In order to use SNI the ssl_sni GUC must be set to on, when
it is off the ssl configuration works just like before.  If ssl_sni is
enabled and pg_hosts.conf is non-empty it will take precedence over
the regular SSL GUCs, if it is empty or missing the regular GUCs will
be used just as before this commit with no hostname specific handling.
The TLS init hook is not compatible with ssl_sni since it operates on
a single TLS configuration and SNI break that assumption.  If the init
hook and ssl_sni are both enabled, a WARNING will be issued.

Host configuration can either be for a literal hostname to match, non-
SNI connections using the no_sni keyword or a default fallback matching
all connections.  By omitting no_sni and the fallback a strict mode
can be achieved where only connections using sslsni=1 and a specified
hostname are allowed.

CRL file(s) are applied from postgresql.conf to all configured hostnames.

Serverside SNI requires OpenSSL, currently LibreSSL does not support
the required infrastructure to update the SSL context during the TLS
handshake.

Author: Daniel Gustafsson <daniel@yesql.se>
Co-authored-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Dewei Dai <daidewei1970@163.com>
Reviewed-by: Cary Huang <cary.huang@highgo.ca>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://postgr.es/m/1C81CD0D-407E-44F9-833A-DD0331C202E5@yesql.se
2026-03-18 12:37:11 +01:00
..
auth-oauth.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
auth-sasl.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
auth-scram.c Fix accidentally cast away qualifiers 2026-01-26 16:02:31 +01:00
auth.c Use fallthrough attribute instead of comment 2026-02-19 08:51:12 +01:00
be-fsstubs.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
be-gssapi-common.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
be-secure-common.c ssl: Serverside SNI support for libpq 2026-03-18 12:37:11 +01:00
be-secure-gssapi.c Don't include wait_event.h in pgstat.h 2026-03-06 16:24:58 +01:00
be-secure-openssl.c ssl: Serverside SNI support for libpq 2026-03-18 12:37:11 +01:00
be-secure.c ssl: Serverside SNI support for libpq 2026-03-18 12:37:11 +01:00
crypt.c Warn upon successful MD5 password authentication. 2026-02-23 11:22:04 -06:00
hba.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
ifaddr.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
Makefile Add support for OAUTHBEARER SASL mechanism 2025-02-20 16:25:17 +01:00
meson.build ssl: Serverside SNI support for libpq 2026-03-18 12:37:11 +01:00
pg_hba.conf.sample Remove no-longer-useful markers in pg_hba.conf.sample. 2026-02-19 11:09:00 -05:00
pg_hosts.conf.sample ssl: Serverside SNI support for libpq 2026-03-18 12:37:11 +01:00
pg_ident.conf.sample Doc: clarify description of regexp fields in pg_ident.conf. 2025-07-15 18:53:00 -04:00
pqcomm.c Don't include latch.h in libpq/libpq.h 2026-02-26 18:04:13 +01:00
pqformat.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
pqmq.c Don't include wait_event.h in pgstat.h 2026-03-06 16:24:58 +01:00
pqsignal.c Update copyright for 2026 2026-01-01 13:24:10 -05:00
README.SSL Move EDH support to common files 2018-01-23 07:11:38 -05:00

src/backend/libpq/README.SSL

SSL
===

>From the servers perspective:


  Receives StartupPacket
           |
           |
 (Is SSL_NEGOTIATE_CODE?) -----------  Normal startup
           |                  No
           |
           | Yes
           |
           |
 (Server compiled with USE_SSL?) ------- Send 'N'
           |                       No        |
           |                                 |
           | Yes                         Normal startup
           |
           |
        Send 'S'
           |
           |
      Establish SSL
           |
           |
      Normal startup





>From the clients perspective (v6.6 client _with_ SSL):


      Connect
         |
         |
  Send packet with SSL_NEGOTIATE_CODE
         |
         |
  Receive single char  ------- 'S' -------- Establish SSL
         |                                       |
         | '<else>'                              |
         |                                  Normal startup
         |
         |
   Is it 'E' for error  ------------------- Retry connection
         |                  Yes             without SSL
         | No
         |
   Is it 'N' for normal ------------------- Normal startup
         |                  Yes
         |
   Fail with unknown

---------------------------------------------------------------------------

Ephemeral DH
============

Since the server static private key ($DataDir/server.key) will
normally be stored unencrypted so that the database backend can
restart automatically, it is important that we select an algorithm
that continues to provide confidentiality even if the attacker has the
server's private key.  Ephemeral DH (EDH) keys provide this and more
(Perfect Forward Secrecy aka PFS).

N.B., the static private key should still be protected to the largest
extent possible, to minimize the risk of impersonations.

Another benefit of EDH is that it allows the backend and clients to
use DSA keys.  DSA keys can only provide digital signatures, not
encryption, and are often acceptable in jurisdictions where RSA keys
are unacceptable.

The downside to EDH is that it makes it impossible to use ssldump(1)
if there's a problem establishing an SSL session.  In this case you'll
need to temporarily disable EDH (see initialize_dh()).