Scope pg_hba.conf rules to real clients
pg_hba.conf# TYPE DATABASE USER ADDRESS METHODlocal all all peerhostssl appdb appuser 10.0.1.0/24 scram-sha-256hostssl appdb readonly 10.0.2.5/32 scram-sha-256host all all 127.0.0.1/32 scram-sha-256# no catch-all rule below this lineSELECT pg_reload_conf();Why it matters
Section titled “Why it matters”host all all 0.0.0.0/0 scram-sha-256 is a rule that says: any role may
connect to any database from anywhere, provided they have the password. It
appears in a great many clusters because it is the rule that stops the errors.
It also throws away three of the four columns Postgres gives you. A password is
the only thing left between an attacker and every database on the server — and
passwords leak. pg_hba.conf is where you decide that a leaked reporting
credential cannot be used to reach production data from an unknown address.
Every column you narrow is a layer that survives a credential leak:
- ADDRESS — the leaked password is useless from outside your subnet.
- DATABASE — the reporting role cannot touch the app database at all.
- USER — one role, one rule; revoking one client doesn’t disturb others.
The first matching rule wins
Section titled “The first matching rule wins”This is the behaviour that defeats otherwise careful configs, and it is worth stating precisely: PostgreSQL walks the file top to bottom and uses the first rule whose type, database, user and address all match. It does not look for the most specific match, and it does not keep looking if authentication fails.
Two consequences:
- A broad rule near the top shadows every specific rule below it. Your
carefully scoped
hostssl appdb appuser 10.0.1.0/24line does nothing ifhost all all 0.0.0.0/0 trustsits above it. - If the first matching rule rejects you, that is the end. Postgres will not fall through to a later rule that would have let you in — which is why “I added a rule and it still fails” is nearly always a shadowing problem.
Order specific rules above general ones, and keep the catch-all — if you need one at all — at the bottom.
Use hostssl, not host
Section titled “Use hostssl, not host”host matches both encrypted and unencrypted connections. A rule written as
host permits a client to connect in plaintext even with ssl = on, because
enabling TLS offers it rather than requiring it.
hostssl matches only TLS connections. For anything crossing a network, that is
the type to use — see Enable TLS.
Related
Section titled “Related”- Remove trust authentication — the worst thing a wide rule can be paired with.
- Enable TLS — why these rules say
hostssl.