1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Support TLS handshake directly without SSLRequest negotiation

By skipping SSLRequest, you can eliminate one round-trip when
establishing a TLS connection. It is also more friendly to generic TLS
proxies that don't understand the PostgreSQL protocol.

This is disabled by default in libpq, because the direct TLS handshake
will fail with old server versions. It can be enabled with the
sslnegotation=direct option. It will still fall back to the negotiated
TLS handshake if the server rejects the direct attempt, either because
it is an older version or the server doesn't support TLS at all, but
the fallback can be disabled with the sslnegotiation=requiredirect
option.

Author: Greg Stark, Heikki Linnakangas
Reviewed-by: Matthias van de Meent, Jacob Champion
This commit is contained in:
Heikki Linnakangas
2024-04-08 04:24:49 +03:00
parent 05fd30c0e7
commit d39a49c1e4
12 changed files with 604 additions and 162 deletions

View File

@ -1740,8 +1740,8 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
encryption, regardless of the value of <literal>sslmode</literal>.
To force use of <acronym>SSL</acronym> encryption in an
environment that has working <acronym>GSSAPI</acronym>
infrastructure (such as a Kerberos server), also
set <literal>gssencmode</literal> to <literal>disable</literal>.
infrastructure (such as a Kerberos server), also set
<literal>gssencmode</literal> to <literal>disable</literal>.
</para>
</listitem>
</varlistentry>
@ -1768,6 +1768,67 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-sslnegotiation" xreflabel="sslnegotiation">
<term><literal>sslnegotiation</literal></term>
<listitem>
<para>
This option controls whether <productname>PostgreSQL</productname>
will perform its protocol negotiation to request encryption from the
server or will just directly make a standard <acronym>SSL</acronym>
connection. Traditional <productname>PostgreSQL</productname>
protocol negotiation is the default and the most flexible with
different server configurations. If the server is known to support
direct <acronym>SSL</acronym> connections then the latter requires one
fewer round trip reducing connection latency and also allows the use
of protocol agnostic SSL network tools.
</para>
<variablelist>
<varlistentry>
<term><literal>postgres</literal></term>
<listitem>
<para>
perform <productname>PostgreSQL</productname> protocol
negotiation. This is the default if the option is not provided.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>direct</literal></term>
<listitem>
<para>
first attempt to establish a standard SSL connection and if that
fails reconnect and perform the negotiation. This fallback
process adds significant latency if the initial SSL connection
fails.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>requiredirect</literal></term>
<listitem>
<para>
attempt to establish a standard SSL connection and if that fails
return a connection failure immediately.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Note that if <literal>gssencmode</literal> is set
to <literal>prefer</literal>, a <acronym>GSS</acronym> connection is
attempted first. If the server ejectes GSS encryption, SSL is
negotiated over the same TCP connection using the traditional postgres
protocol, regardless of <literal>sslnegotiation</literal>. 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.
</para>
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-sslcompression" xreflabel="sslcompression">
<term><literal>sslcompression</literal></term>
<listitem>
@ -2001,11 +2062,13 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<para>
The Server Name Indication can be used by SSL-aware proxies to route
connections without having to decrypt the SSL stream. (Note that this
requires a proxy that is aware of the PostgreSQL protocol handshake,
not just any SSL proxy.) However, <acronym>SNI</acronym> makes the
destination host name appear in cleartext in the network traffic, so
it might be undesirable in some cases.
connections without having to decrypt the SSL stream. (Note that
unless the proxy is aware of the PostgreSQL protocol handshake this
would require setting <literal>sslnegotiation</literal>
to <literal>direct</literal> or <literal>requiredirect</literal>.)
However, <acronym>SNI</acronym> makes the destination host name appear
in cleartext in the network traffic, so it might be undesirable in
some cases.
</para>
</listitem>
</varlistentry>
@ -8676,6 +8739,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary><envar>PGSSLNEGOTIATION</envar></primary>
</indexterm>
<envar>PGSSLNEGOTIATION</envar> behaves the same as the <xref
linkend="libpq-connect-sslnegotiation"/> connection parameter.
</para>
</listitem>
<listitem>
<para>
<indexterm>

View File

@ -1529,11 +1529,47 @@ SELCT 1/0;<!-- this typo is intentional -->
bytes.
</para>
<para>
Likewise the server expects the client to not begin
the <acronym>SSL</acronym> negotiation until it receives the server's
single byte response to the <acronym>SSL</acronym> request. If the
client begins the <acronym>SSL</acronym> negotiation immediately without
waiting for the server response to be received it can reduce connection
latency by one round-trip. However this comes at the cost of not being
able to handle the case where the server sends a negative response to the
<acronym>SSL</acronym> request. In that case instead of continuing with either GSSAPI or an
unencrypted connection or a protocol error the server will simply
disconnect.
</para>
<para>
An initial SSLRequest can also be used in a connection that is being
opened to send a CancelRequest message.
</para>
<para>
A second alternate way to initiate <acronym>SSL</acronym> encryption is
available. The server will recognize connections which immediately
begin <acronym>SSL</acronym> negotiation without any previous SSLRequest
packets. Once the <acronym>SSL</acronym> connection is established the
server will expect a normal startup-request packet and continue
negotiation over the encrypted channel. In this case any other requests
for encryption will be refused. This method is not preferred for general
purpose tools as it cannot negotiate the best connection encryption
available or handle unencrypted connections. However it is useful for
environments where both the server and client are controlled together.
In that case it avoids one round trip of latency and allows the use of
network tools that depend on standard <acronym>SSL</acronym> connections.
When using <acronym>SSL</acronym> connections in this style the client is
required to use the ALPN extension defined
by <ulink url="https://tools.ietf.org/html/rfc7301">RFC 7301</ulink> to
protect against protocol confusion attacks.
The <productname>PostgreSQL</productname> protocol is "TBD-pgsql" as
registered
at <ulink url="https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids">IANA
TLS ALPN Protocol IDs</ulink> registry.
</para>
<para>
While the protocol itself does not provide a way for the server to
force <acronym>SSL</acronym> encryption, the administrator can