On 12/13/18 7:43 AM, Pablo Iranzo Gómez wrote:
haproxy is what is used behind, the idea is that haproxy by default when
enabled via a 'route' does allow http or https protocol ONLY, BUT
(https://docs.openshift.com/container-platform/3.9/architecture/networking/routes.html),
routers do support TLS with SNI.
As PSQL by default tries TLS and fallbacks to plain psql protocol the
idea behind is that we tell OpenShift route to be 'Secure' and
'passtrough', in this way, when PSQL does speak to '443' port in the
route that goes to the 'pod' running postgres using TLS and SNI, the
connection goes thru without any special protocol change.
Sadly that confirms what I feared. Adding SNI to the PostgreSQL protocol
wont help with solving your use case because the PostgreSQL protocol has
its own handshake which happens before the SSL handshake so the session
will not look like SSL to HA Proxy.
Just like HA Proxy does not support STARTTLS for IMAP[1] I do not think
that it will ever support SSL for the PostgreSQL protocol, SNI or not.
To solve your use case I recommend using something like stunnel, which
does support SNI, to wrap the unencrypted PostgreSQL protocol in SSL.
This all makes me very skeptical to if there is any realistic use case
for adding SNI support to libpq, and just adding SNI support feels like
adding a trap to people who do not know that they should rather use
stunnel than PostgreSQL's built-in SSL support of they want to route on
SNI with HA Proxy.
But I will attach my small patch for this, which I am now opposed to,
anyway so the code exists if a use case turns up in the future (or if it
turns out my reasoning above is incorrect).
Notes
1.
https://www.haproxy.com/documentation/haproxy/deployment-guides/exchange-2010/imap4/
Andreas
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index d2e5b08541e..528757f775d 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1460,6 +1460,23 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
</listitem>
</varlistentry>
+ <varlistentry id="libpq-connect-sslsni" xreflabel="sslsni">
+ <term><literal>sslcompression</literal></term>
+ <listitem>
+ <para>
+ If set to 1, the host name is sent to the server using SSL's
+ <acronym>SNI</acronym> (Server Name Indication) extension. If set
+ to 0, no <acronym>SNI</acronym> extension will be sent. The default is
+ 0. This parameter is ignored if a connection without SSL is made.
+ </para>
+
+ <para>
+ The PostgreSQL server ignores the <acronym>SNI</acronym> extension,
+ but it can be used by SSL-aware proxy software.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="libpq-connect-sslcert" xreflabel="sslcert">
<term><literal>sslcert</literal></term>
<listitem>
@@ -7373,6 +7390,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
</para>
</listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary><envar>PGSSLSNI</envar></primary>
+ </indexterm>
+ <envar>PGSSLSNI</envar> behaves the same as the <xref
+ linkend="libpq-connect-sslsni"/> connection parameter.
+ </para>
+ </listitem>
+
<listitem>
<para>
<indexterm>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index bc456fec0c2..4587e5ebb5a 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -278,6 +278,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
"SSL-Compression", "", 1,
offsetof(struct pg_conn, sslcompression)},
+ {"sslsni", "PGSSLSNI", "0", NULL,
+ "SSL-SNI", "", 1,
+ offsetof(struct pg_conn, sslsni)},
+
{"sslcert", "PGSSLCERT", NULL, NULL,
"SSL-Client-Cert", "", 64,
offsetof(struct pg_conn, sslcert)},
@@ -3690,6 +3694,8 @@ freePGconn(PGconn *conn)
free(conn->sslcrl);
if (conn->sslcompression)
free(conn->sslcompression);
+ if (conn->sslsni)
+ free(conn->sslsni);
if (conn->requirepeer)
free(conn->requirepeer);
if (conn->connip)
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index beca3492e8d..fdae2eac74f 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -781,6 +781,7 @@ initialize_SSL(PGconn *conn)
char homedir[MAXPGPATH];
char fnbuf[MAXPGPATH];
char sebuf[PG_STRERROR_R_BUFLEN];
+ char *host;
bool have_homedir;
bool have_cert;
bool have_rootcert;
@@ -1183,6 +1184,11 @@ initialize_SSL(PGconn *conn)
#endif
#endif
+ host = conn->connhost[conn->whichhost].host;
+
+ if (conn->sslsni && conn->sslsni[0] == '1' && host)
+ SSL_set_tlsext_host_name(conn->ssl, host);
+
return 0;
}
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 66fd317b949..9f69fbdf5fc 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -353,6 +353,7 @@ struct pg_conn
* retransmits */
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
char *sslcompression; /* SSL compression (0 or 1) */
+ char *sslsni; /* SSL SNI extension (0 or 1) */
char *sslkey; /* client key filename */
char *sslcert; /* client certificate filename */
char *sslrootcert; /* root certificate filename */