Thread: Refuse SSL patch

Refuse SSL patch

From
Jon Jensen
Date:
PostgreSQL hackers,

This patch allows the PostgreSQL server to refuse SSL connections
selectively, and the clients to not initiate SSL connections.

The point is for me to be able to choose non-SSL connections over SSL,
even when SSL is available, for maximum performance. I've got a PostgreSQL
server that has a separate private network link to an application server,
and I want database connections there to always be non-SSL for speed. But
I also connect to the same PostgreSQL instance from a remote site, and
always want that connection to be SSL only for security.

I haven't seen any previous mention of a similar patch, though I found the
following idea proposed by Magnus Hagander which I like:

> Perhaps we shuold replace PGREQUIRE_SSL with "PGSSLMODE", being:
> 0 - Refuse SSL
> 1 - Negotiate, Prefer non-SSL
> 2 - Negotiate, Prefer SSL (default)
> 3 - Require SSL

http://archives.postgresql.org/pgsql-hackers/2000-08/msg00639.php

He also notes the desire to be able to disable SSL for speed.

Magnus's post was over two years ago and it doesn't appear anything along
these lines was done. Since then the current setup of 'host'/'hostssl' in
pg_hba.conf and the client connect option 'requiressl' is pretty firmly
engrained, so to keep compatibility I added 'hostnossl' to pg_hba and a
'nossl' option to the client library.

Patch against PostgreSQL 7.2.3 is attached.

Is this useful to others? If you'd like me to make some changes to make it
acceptable, please let me know.

Thanks,
Jon

Attachment

Re: Refuse SSL patch

From
Tom Lane
Date:
Jon Jensen <jon@endpoint.com> writes:
> I haven't seen any previous mention of a similar patch, though I found the
> following idea proposed by Magnus Hagander which I like:

>> Perhaps we shuold replace PGREQUIRE_SSL with "PGSSLMODE", being:
>> 0 - Refuse SSL
>> 1 - Negotiate, Prefer non-SSL
>> 2 - Negotiate, Prefer SSL (default)
>> 3 - Require SSL

Hm, I like that better than two independent boolean vars (it's not
obvious which should override the other, or why); moreover it adds
more functionality (your approach does not provide a way to do mode 1).
For backwards compatibility, if PGSSLMODE is not set then you could look
for PGREQUIRE_SSL, and assume mode 3 (rather than the default 2) if
PGREQUIRE_SSL is set.

It might be better to use keywords or mnemonics of some kind in place of
these arbitrary numeric codes.  No strong feeling about that.

> Is this useful to others? If you'd like me to make some changes to make it
> acceptable, please let me know.

Patches to the relevant documentation would be a minimum requirement.
(In looking at this, I observe the original patch neglected to document
the PGREQUIRE_SSL environment variable; don't emulate that bad example.)

            regards, tom lane

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Mon, 9 Dec 2002, Tom Lane wrote:

> Jon Jensen <jon@endpoint.com> writes:
> > I haven't seen any previous mention of a similar patch, though I found the
> > following idea proposed by Magnus Hagander which I like:
>
> >> Perhaps we shuold replace PGREQUIRE_SSL with "PGSSLMODE", being:
> >> 0 - Refuse SSL
> >> 1 - Negotiate, Prefer non-SSL
> >> 2 - Negotiate, Prefer SSL (default)
> >> 3 - Require SSL
>
> Hm, I like that better than two independent boolean vars (it's not
> obvious which should override the other, or why); moreover it adds
> more functionality (your approach does not provide a way to do mode 1).
> For backwards compatibility, if PGSSLMODE is not set then you could look
> for PGREQUIRE_SSL, and assume mode 3 (rather than the default 2) if
> PGREQUIRE_SSL is set.

I'm working on implementing this now.

> It might be better to use keywords or mnemonics of some kind in place of
> these arbitrary numeric codes.  No strong feeling about that.

I wish I could think of some decent keywords, but the concepts don't lend
themselves well to short descriptions. I'll start with the numbers Magnus
suggested, and we can switch to names for the modes later if we want.

> > Is this useful to others? If you'd like me to make some changes to make it
> > acceptable, please let me know.
>
> Patches to the relevant documentation would be a minimum requirement.

Ok.

Jon

Re: Refuse SSL patch

From
Bruce Momjian
Date:
Jon, I just documented the service/PGSERVICE capability in the CVS tree.
It allows a pg_service.conf file that controls additional libpq
connection options.  In your app, you just do:

    connectdb("service=conn1")

and "conn1" is looked up in pg_service.conf and it gets its other
connection parameters from there.  The code is already in 7.3.  I just
documented it, and changed auto-dbname setting to be active only when
they don't specify a dbname.  Also, I created a sample file called
pg_service.conf.sample.

This may provide a better way for you to control SSL rather than
changing PGREQUIRE_SSL, which was also recently documented in the CVS
tree.

I don't think overloading REQUIRE to mean something else is really the
way to go.  Looking at your options, we have:

> > 0 - Refuse SSL

Hard to imagine why someone would pick this one.

> > 1 - Negotiate, Prefer non-SSL

This is the only new valid one. My question is why you would specify ssl
on the host if you don't need ssl?

> > 2 - Negotiate, Prefer SSL (default)

Already the default for no requiressl.

> > 3 - Require SSL

Already requiressl.

If the problem is that some apps need requiressl and others don't, I
think the service file may be your cleanest option.

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

Jon Jensen wrote:
> PostgreSQL hackers,
>
> This patch allows the PostgreSQL server to refuse SSL connections
> selectively, and the clients to not initiate SSL connections.
>
> The point is for me to be able to choose non-SSL connections over SSL,
> even when SSL is available, for maximum performance. I've got a PostgreSQL
> server that has a separate private network link to an application server,
> and I want database connections there to always be non-SSL for speed. But
> I also connect to the same PostgreSQL instance from a remote site, and
> always want that connection to be SSL only for security.
>
> I haven't seen any previous mention of a similar patch, though I found the
> following idea proposed by Magnus Hagander which I like:
>
> > Perhaps we shuold replace PGREQUIRE_SSL with "PGSSLMODE", being:
> > 0 - Refuse SSL
> > 1 - Negotiate, Prefer non-SSL
> > 2 - Negotiate, Prefer SSL (default)
> > 3 - Require SSL
>
> http://archives.postgresql.org/pgsql-hackers/2000-08/msg00639.php
>
> He also notes the desire to be able to disable SSL for speed.
>
> Magnus's post was over two years ago and it doesn't appear anything along
> these lines was done. Since then the current setup of 'host'/'hostssl' in
> pg_hba.conf and the client connect option 'requiressl' is pretty firmly
> engrained, so to keep compatibility I added 'hostnossl' to pg_hba and a
> 'nossl' option to the client library.
>
> Patch against PostgreSQL 7.2.3 is attached.
>
> Is this useful to others? If you'd like me to make some changes to make it
> acceptable, please let me know.
>
> Thanks,
> Jon

Content-Description:

[ Attachment, skipping... ]

Content-Description:

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Tue, 7 Jan 2003, Bruce Momjian wrote:

> Jon, I just documented the service/PGSERVICE capability in the CVS tree.
> It allows a pg_service.conf file that controls additional libpq
> connection options.  In your app, you just do:
>
>     connectdb("service=conn1")
>
> and "conn1" is looked up in pg_service.conf and it gets its other
> connection parameters from there.  The code is already in 7.3.  I just
> documented it, and changed auto-dbname setting to be active only when
> they don't specify a dbname.  Also, I created a sample file called
> pg_service.conf.sample.
>
> This may provide a better way for you to control SSL rather than
> changing PGREQUIRE_SSL, which was also recently documented in the CVS
> tree.

I will take a look at the pg_service.conf file.

> I don't think overloading REQUIRE to mean something else is really the
> way to go.  Looking at your options, we have:
>
> > > 0 - Refuse SSL
>
> Hard to imagine why someone would pick this one.

But this is the exact reason I started my patch -- I need a server that
can do SSL to allow *only* SSL connections to an off-site IP address, but
*only* non-SSL connections to an internal IP address on a private network.
Speed would suffer greatly if I were to allow SSL connections internally,
but security would suffer if I disabled all SSL connections.

> > > 1 - Negotiate, Prefer non-SSL
>
> This is the only new valid one. My question is why you would specify ssl
> on the host if you don't need ssl?

This is the one I don't see much need for, but I don't want to
second-guess people's needs if I can help it. Might as well put in all the
possibilities.

> > > 2 - Negotiate, Prefer SSL (default)
>
> Already the default for no requiressl.
>
> > > 3 - Require SSL
>
> Already requiressl.
>
> If the problem is that some apps need requiressl and others don't, I
> think the service file may be your cleanest option.

I hadn't heard of that before you checked in the docs patch yesterday, so
I'll check it out.

Thanks,
Jon

Re: Refuse SSL patch

From
Bruce Momjian
Date:
Jon Jensen wrote:
> > I don't think overloading REQUIRE to mean something else is really the
> > way to go.  Looking at your options, we have:
> >
> > > > 0 - Refuse SSL
> >
> > Hard to imagine why someone would pick this one.
>
> But this is the exact reason I started my patch -- I need a server that
> can do SSL to allow *only* SSL connections to an off-site IP address, but
> *only* non-SSL connections to an internal IP address on a private network.
> Speed would suffer greatly if I were to allow SSL connections internally,
> but security would suffer if I disabled all SSL connections.

But doesn't pg_hba.conf do that already, in that you say 'host' for the
local ip, but ssl for the remote ip's?

The only value I see to the existing REQUIRESSL is to say "I am a client
and only want to do SSL", and in that case you can use the services file
to use the same binary on different hosts, and control whether you want
that host to require SSL or not.  It doesn't make the switching based on
who the host is connecting to, but your proposal doesn't do that either.

I have to say I am just still confused over this.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Tue, 7 Jan 2003, Bruce Momjian wrote:

> Jon Jensen wrote:
> > > I don't think overloading REQUIRE to mean something else is really the
> > > way to go.  Looking at your options, we have:
> > >
> > > > > 0 - Refuse SSL
> > >
> > > Hard to imagine why someone would pick this one.
> >
> > But this is the exact reason I started my patch -- I need a server that
> > can do SSL to allow *only* SSL connections to an off-site IP address, but
> > *only* non-SSL connections to an internal IP address on a private network.
> > Speed would suffer greatly if I were to allow SSL connections internally,
> > but security would suffer if I disabled all SSL connections.
>
> But doesn't pg_hba.conf do that already, in that you say 'host' for the
> local ip, but ssl for the remote ip's?

The proposed SSLMODE is a client-side configuration option to supercede
REQUIRESSL, which is also a client configuration option. Here's the
problem:

1. The client always tries to connect via SSL if SSL support was compiled
in. There is no way to change this presently.
2. If the server can do SSL *at all*, it negotiates an SSL connection with
the client.
3. End of story -- we have an SSL connection when I don't want one. The
only way around it is to have the server have no SSL support at all.

So it's a client problem. The client needs to be configured to not try an
SSL connection at all, when I don't want it to. Hence SSLMODE=0, which
means forbid SSL.

But on the other hand, we want some control on the server as well -- we
may want to disallow SSL connections from a certain IP address, if nothing
else just to make sure a client doesn't accidentally use SSL over the
local network because someone forgets not to use it. Otherwise we could be
accidentally using SSL on the local network and killing performance. So I
added a 'hostnossl' option to pg_hba.conf, which will allow only non-SSL
connections from certain IP addresses.

Only the client changes are really necessary for my setup to work, but the
server change allows me to guarantee that other developers don't
accidentally connect via SSL when it's not wanted.

Does that make more sense?

Jon

Re: Refuse SSL patch

From
Bruno Wolff III
Date:
On Tue, Jan 07, 2003 at 16:04:45 +0000,
  Jon Jensen <jon@endpoint.com> wrote:
>
> 1. The client always tries to connect via SSL if SSL support was compiled
> in. There is no way to change this presently.
> 2. If the server can do SSL *at all*, it negotiates an SSL connection with
> the client.

Can't you use a "reject" hostssl line in hba.conf to keep SSL connections
from working for particular IP addresses? Does the client not fall back
in this case?

Re: Refuse SSL patch

From
Tom Lane
Date:
Bruno Wolff III <bruno@wolff.to> writes:
> Can't you use a "reject" hostssl line in hba.conf to keep SSL connections
> from working for particular IP addresses? Does the client not fall back
> in this case?

I think it won't --- the fallback is only at the initial attempt to open
the connection, not if the startup packet is rejected.

A more global question is whether the overhead of SSL is really large
enough to justify any concern about avoiding it.  I have never measured
it, but even a local LAN is a lot slower than modern CPUs.  It doesn't
seem to me to be a foregone conclusion that we need to worry about
providing a way to avoid it.

            regards, tom lane

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Tue, 7 Jan 2003, Bruno Wolff III wrote:

> On Tue, Jan 07, 2003 at 16:04:45 +0000,
>   Jon Jensen <jon@endpoint.com> wrote:
> >
> > 1. The client always tries to connect via SSL if SSL support was compiled
> > in. There is no way to change this presently.
> > 2. If the server can do SSL *at all*, it negotiates an SSL connection with
> > the client.
>
> Can't you use a "reject" hostssl line in hba.conf to keep SSL connections
> from working for particular IP addresses? Does the client not fall back
> in this case?

No, the client doesn't fall back if it makes a successful connection to
the server in SSL mode, but the server denies access. It only falls back
if the server can't do SSL at all.

And in any case, that still wouldn't allow me to decide on the client side
whether I want SSL or not, on a per-connection basis, because the client
always chooses SSL.

Jon

Re: Refuse SSL patch

From
Bruce Momjian
Date:
Jon Jensen wrote:
> > But doesn't pg_hba.conf do that already, in that you say 'host' for the
> > local ip, but ssl for the remote ip's?
>
> The proposed SSLMODE is a client-side configuration option to supercede
> REQUIRESSL, which is also a client configuration option. Here's the
> problem:
>
> 1. The client always tries to connect via SSL if SSL support was compiled
> in. There is no way to change this presently.
> 2. If the server can do SSL *at all*, it negotiates an SSL connection with
> the client.

Oh, that is a key thing I didn't know.  Seems we should just add a libpq
PREVENTSSL option and be done with it.  Seems clearer than numbers, and
hits the most useful functionality.  If they set REQUIRESSL and
PREVENTSSL, we throw an error.

Right now, if they set 'host' in pg_hba.conf, and the client knows SSL,
we use it.  Your idea had the additional functionality of preferring
non-SSL if the server knew SSL but had 'host' in pg_hba.conf.

> But on the other hand, we want some control on the server as well -- we
> may want to disallow SSL connections from a certain IP address, if nothing
> else just to make sure a client doesn't accidentally use SSL over the
> local network because someone forgets not to use it. Otherwise we could be
> accidentally using SSL on the local network and killing performance. So I
> added a 'hostnossl' option to pg_hba.conf, which will allow only non-SSL
> connections from certain IP addresses.

Perhaps your idea of 'hostnossl' in pg_hba.conf is a good one.  That
way, both client and server would have the ability to say never or only
SSL. It allows more central control.

So, in negotiation, that only leaves open the question of what happens
when none of those are set, and it seems we prefer SSL in such cases.
Is that the correct default?

In fact, once we have 'hostnossl' why do we need PREVENTSSL in libpq?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Tue, 7 Jan 2003, Tom Lane wrote:

> Bruno Wolff III <bruno@wolff.to> writes:
> > Can't you use a "reject" hostssl line in hba.conf to keep SSL connections
> > from working for particular IP addresses? Does the client not fall back
> > in this case?
>
> I think it won't --- the fallback is only at the initial attempt to open
> the connection, not if the startup packet is rejected.

That's right.

> A more global question is whether the overhead of SSL is really large
> enough to justify any concern about avoiding it.  I have never measured
> it, but even a local LAN is a lot slower than modern CPUs.  It doesn't
> seem to me to be a foregone conclusion that we need to worry about
> providing a way to avoid it.

Not at all. SSL has significant overhead. Here's a quick test that runs
three SELECT queries returning about 50,000 rows:

bash-2.05$ time ./timeit
real    0m10.527s
user    0m5.290s
sys     0m0.420s
bash-2.05$ time ./timeit nossl=1
real    0m6.947s
user    0m1.720s
sys     0m0.350s

This is with a client and server on separate machines on the same local
network, each with 2+ GB RAM and Xeon 2.4 GHz processors (dual, though
that's not relevant). The slowdown will be worse with slower CPUs, of
course.

I can't imagine why I'd want to tolerate wasting CPU on both ends of the
connection and slowing down data transfer, when my original purpose in
moving the database off the app server box was to increase capacity.

I will of course continue using my working patched versions of PostgreSQL
that allow me the flexibility of deciding on client and server whether I
will talk via SSL or not. My question is whether the mainline PostgreSQL
software will give users the same flexibility. I'll finish up my SSLMODE
patch and submit it, and it's up to you all from there.

Jon

Re: Refuse SSL patch

From
Jon Jensen
Date:
On Tue, 7 Jan 2003, Bruce Momjian wrote:

> > The proposed SSLMODE is a client-side configuration option to supercede
> > REQUIRESSL, which is also a client configuration option. Here's the
> > problem:
> >
> > 1. The client always tries to connect via SSL if SSL support was compiled
> > in. There is no way to change this presently.
> > 2. If the server can do SSL *at all*, it negotiates an SSL connection with
> > the client.
>
> Oh, that is a key thing I didn't know.  Seems we should just add a libpq
> PREVENTSSL option and be done with it.

That's exactly what my original patch did! :)

Tom thought that having conflicting REFUSESSL and REQUIRESSL directives
would be confusing, and since I dug up someone's old discussion in the
list archives of the four possible modes, we could move to that.

> > But on the other hand, we want some control on the server as well -- we
> > may want to disallow SSL connections from a certain IP address, if nothing
> > else just to make sure a client doesn't accidentally use SSL over the
> > local network because someone forgets not to use it. Otherwise we could be
> > accidentally using SSL on the local network and killing performance. So I
> > added a 'hostnossl' option to pg_hba.conf, which will allow only non-SSL
> > connections from certain IP addresses.
>
> Perhaps your idea of 'hostnossl' in pg_hba.conf is a good one.  That
> way, both client and server would have the ability to say never or only
> SSL. It allows more central control.
>
> So, in negotiation, that only leaves open the question of what happens
> when none of those are set, and it seems we prefer SSL in such cases.
> Is that the correct default?
>
> In fact, once we have 'hostnossl' why do we need PREVENTSSL in libpq?

Because hostnossl is only an authentication control, not a connection
control. libpq will *always* connect SSL if it can, which guarantees that
the authentication will fail with hostnossl. We have to have configuration
options on both ends to make this work.

Jon

Re: Refuse SSL patchf

From
Bruce Momjian
Date:
Jon Jensen wrote:
> On Tue, 7 Jan 2003, Bruce Momjian wrote:
>
> > > The proposed SSLMODE is a client-side configuration option to supercede
> > > REQUIRESSL, which is also a client configuration option. Here's the
> > > problem:
> > >
> > > 1. The client always tries to connect via SSL if SSL support was compiled
> > > in. There is no way to change this presently.
> > > 2. If the server can do SSL *at all*, it negotiates an SSL connection with
> > > the client.
> >
> > Oh, that is a key thing I didn't know.  Seems we should just add a libpq
> > PREVENTSSL option and be done with it.
>
> That's exactly what my original patch did! :)
>
> Tom thought that having conflicting REFUSESSL and REQUIRESSL directives
> would be confusing, and since I dug up someone's old discussion in the
> list archives of the four possible modes, we could move to that.

Oh.  I find two params clearer than one with meaningless numbers.  :-)

> > > But on the other hand, we want some control on the server as well -- we
> > > may want to disallow SSL connections from a certain IP address, if nothing
> > > else just to make sure a client doesn't accidentally use SSL over the
> > > local network because someone forgets not to use it. Otherwise we could be
> > > accidentally using SSL on the local network and killing performance. So I
> > > added a 'hostnossl' option to pg_hba.conf, which will allow only non-SSL
> > > connections from certain IP addresses.
> >
> > Perhaps your idea of 'hostnossl' in pg_hba.conf is a good one.  That
> > way, both client and server would have the ability to say never or only
> > SSL. It allows more central control.
> >
> > So, in negotiation, that only leaves open the question of what happens
> > when none of those are set, and it seems we prefer SSL in such cases.
> > Is that the correct default?
> >
> > In fact, once we have 'hostnossl' why do we need PREVENTSSL in libpq?
>
> Because hostnossl is only an authentication control, not a connection
> control. libpq will *always* connect SSL if it can, which guarantees that
> the authentication will fail with hostnossl. We have to have configuration
> options on both ends to make this work.

Well, your 0-3 valued patch must have had some code that fell back to
non-SSL when SSL failed.  Can't we do that by default?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Refuse SSL patchf

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> > Tom thought that having conflicting REFUSESSL and REQUIRESSL directives
> > would be confusing, and since I dug up someone's old discussion in the
> > list archives of the four possible modes, we could move to that.
>
> Oh.  I find two params clearer than one with meaningless numbers.  :-)

But the numeric model provides four modes (refuse ssl, prefer no ssl,
prefer ssl, require ssl) whereas the refuse/require combination only
provides three modes (refuse ssl, require ssl, and one other depending on
how you define it when neither is set).  If you don't like numbers, make
them words.

--
Peter Eisentraut   peter_e@gmx.net


Re: Refuse SSL patchf

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > > Tom thought that having conflicting REFUSESSL and REQUIRESSL directives
> > > would be confusing, and since I dug up someone's old discussion in the
> > > list archives of the four possible modes, we could move to that.
> >
> > Oh.  I find two params clearer than one with meaningless numbers.  :-)
>
> But the numeric model provides four modes (refuse ssl, prefer no ssl,
> prefer ssl, require ssl) whereas the refuse/require combination only
> provides three modes (refuse ssl, require ssl, and one other depending on
> how you define it when neither is set).  If you don't like numbers, make
> them words.

OK, that works:

    require
    prevent
    prefer
    noprefer

This allows us to subsume PGREQUIRE_SSL into the new variable.  Do we
still need additional functionality in pg_hba.conf?  I am only asking if
pushing these decisions out to the client makes sense?

For performance reasons, it is good to push this information out to the
clients so the proper connection method is used the first time.

However, for easier maintenance, we could have all of this in
pg_hba.conf only, and have clients try SSL first, and fall back to
non-SSL if the server doesn't want SSL.  It would require two new
pg_hba.conf line types.  We have prefer-SSL (host) and SSL-only (ssl)
now.

    require (ssl)
    prevent (nossl)
    prefer  (hostpreferssl)
    noprefer(host)

This would change 'host' to not prefer SSL.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073