Настройка pg_hba.conf и методов аутентификации PostgreSQL

Пошаговая настройка правил доступа в pg_hba.conf: local, host, CIDR, scram-sha-256, порядок правил и безопасная проверка подключений.

Файл pg_hba.conf определяет, кто, к какой базе, под какой ролью и с какого адреса может подключаться к PostgreSQL.

Аббревиатура HBA означает:

Host-Based Authentication

В этой инструкции рассматривается только настройка правил доступа и методов аутентификации в pg_hba.conf.

Проверено на: Ubuntu Server 24.04 LTS
Уровень сложности: средний
Время выполнения: около 20–30 минут
Требуемый доступ: пользователь с правами sudo и административный доступ к PostgreSQL

Что будет настроено

После выполнения инструкции:

  • будет найден активный файл pg_hba.conf;
  • будет разобран порядок обработки правил;
  • будет настроен доступ по Unix socket;
  • будет настроен доступ по TCP;
  • будет использован метод scram-sha-256;
  • будет ограничен доступ конкретной базой, ролью и подсетью;
  • будет выполнен reload без остановки PostgreSQL;
  • будут проверены типичные ошибки аутентификации;
  • будет показан безопасный откат.

Важное предупреждение

Ошибка в pg_hba.conf может заблокировать административный доступ.

Перед изменением:

  • оставьте открытое подключение psql;
  • создайте резервную копию;
  • не удаляйте рабочее локальное правило;
  • добавляйте разрешающее правило выше общего запрета;
  • проверяйте доступ из отдельного терминала;
  • не выполняйте restart без необходимости.

Определение активного файла

sudo -u postgres \
  psql \
  -Atc 'SHOW hba_file;'

Сохраните путь:

HBA_FILE="$(
  sudo -u postgres \
    psql \
    -Atc 'SHOW hba_file;'
)"

Проверьте:

printf '%s\n' "$HBA_FILE"

Создание резервной копии

sudo cp \
  "$HBA_FILE" \
  "${HBA_FILE}.before-auth-change"

Проверьте:

sudo ls -l \
  "${HBA_FILE}"*

Просмотр активных правил

sudo sed -n '1,240p' \
  "$HBA_FILE"

Без комментариев и пустых строк:

sudo grep -vE \
  '^[[:space:]]*(#|$)' \
  "$HBA_FILE"

Структура правила

Общий формат:

TYPE  DATABASE  USER  ADDRESS  METHOD  OPTIONS

Пример:

host  app_db  app_user  198.51.100.20/32  scram-sha-256

Поле TYPE

Основные типы:

local
host
hostssl
hostnossl

local

Подключение через Unix socket:

local  all  postgres  peer

host

TCP-подключение с TLS или без TLS:

host  app_db  app_user  198.51.100.20/32  scram-sha-256

hostssl

Только TCP-подключение с TLS:

hostssl  app_db  app_user  198.51.100.20/32  scram-sha-256

hostnossl

Только TCP-подключение без TLS:

hostnossl  app_db  app_user  198.51.100.20/32  reject

Поле DATABASE

Можно указать:

all
sameuser
samerole
replication
конкретную базу
список баз через запятую

Пример:

app_db

Несколько баз:

app_db,report_db

Поле USER

Можно указать:

all
конкретную роль
список ролей
+роль-группу

Пример:

app_user

Группа:

+readonly

Знак + означает членов групповой роли.

Поле ADDRESS

Один IPv4:

198.51.100.20/32

Подсеть IPv4:

198.51.100.0/24

Один IPv6:

2001:db8::20/128

Подсеть IPv6:

2001:db8:100::/64

Поле METHOD

Основные методы:

peer
scram-sha-256
md5
cert
trust
reject

Для обычных парольных подключений рекомендуется:

scram-sha-256

Порядок правил

PostgreSQL проверяет pg_hba.conf сверху вниз.

Используется первое совпавшее правило.

Если правило совпало, но аутентификация не прошла, PostgreSQL не переходит к следующему правилу.

Правильно:

host  app_db  app_user  198.51.100.20/32  scram-sha-256
host  all     all       0.0.0.0/0          reject

Неправильно:

host  all     all       0.0.0.0/0          reject
host  app_db  app_user  198.51.100.20/32  scram-sha-256

Во втором случае разрешающее правило никогда не будет достигнуто.

Локальный доступ администратора

Типовое правило:

local  all  postgres  peer

Оно позволяет Linux-пользователю postgres подключаться к одноимённой роли PostgreSQL без пароля.

Проверка:

sudo -u postgres psql

Метод peer

peer работает только для Unix socket.

PostgreSQL получает имя Linux-пользователя и сопоставляет его с ролью PostgreSQL.

Не используйте peer в строках host.

Разрешение удалённого клиента

Пример точного правила:

host  app_db  app_user  198.51.100.20/32  scram-sha-256

Оно разрешает:

  • TCP-подключение;
  • только к базе app_db;
  • только ролью app_user;
  • только с IP 198.51.100.20;
  • с парольной SCRAM-аутентификацией.

Разрешение подсети

host  app_db  app_user  198.51.100.0/24  scram-sha-256

Используйте подсеть только если все адреса в ней доверенные.

Несколько ролей

host  app_db  app_user,report_user  198.51.100.20/32  scram-sha-256

Несколько баз

host  app_db,report_db  app_user  198.51.100.20/32  scram-sha-256

Групповая роль

Создайте роль-группу:

CREATE ROLE app_clients
NOLOGIN;

Добавьте участника:

GRANT app_clients
TO app_user;

Правило:

host  app_db  +app_clients  198.51.100.0/24  scram-sha-256

Метод scram-sha-256

Проверьте формат для новых паролей:

sudo -u postgres \
  psql \
  -Atc 'SHOW password_encryption;'

Ожидается:

scram-sha-256

Настройка password_encryption

sudo -u postgres psql
ALTER SYSTEM
SET password_encryption = 'scram-sha-256';

Примените:

SELECT pg_reload_conf();

Проверьте:

SHOW password_encryption;

Пересоздание пароля роли

\password app_user

psql запросит новый пароль интерактивно.

После этого verifier будет создан в текущем формате password_encryption.

Проверка формата пароля

Только суперпользователь:

SELECT
    rolname,
    CASE
        WHEN rolpassword LIKE 'SCRAM-SHA-256$%'
            THEN 'SCRAM'
        WHEN rolpassword LIKE 'md5%'
            THEN 'MD5'
        WHEN rolpassword IS NULL
            THEN 'NO PASSWORD'
        ELSE 'OTHER'
    END AS password_format
FROM pg_authid
WHERE rolname = 'app_user';

Не выводите значение rolpassword полностью.

Метод md5

Пример:

host  app_db  app_user  198.51.100.20/32  md5

Для новых конфигураций лучше использовать scram-sha-256.

md5 допустим только как временная мера совместимости со старым клиентом.

Метод trust

Опасный пример:

host  all  all  0.0.0.0/0  trust

Он разрешает подключение без пароля.

Не используйте trust для сетевого доступа.

Метод reject

Явный запрет:

host  all  all  0.0.0.0/0  reject

Для IPv6:

host  all  all  ::/0  reject

Общие запреты должны располагаться после необходимых разрешающих правил.

Обязательный TLS через hostssl

Проверьте SSL:

sudo -u postgres \
  psql \
  -Atc 'SHOW ssl;'

Если возвращается:

on

можно использовать:

hostssl  app_db  app_user  198.51.100.20/32  scram-sha-256

И запретить незашифрованный доступ:

hostnossl  app_db  app_user  198.51.100.20/32  reject
hostssl    app_db  app_user  198.51.100.20/32  scram-sha-256

Проверка TLS-подключения

С клиента:

psql \
  'host=192.0.2.10
   port=5432
   dbname=app_db
   user=app_user
   sslmode=require'

Внутри:

\conninfo

Добавление правила

Откройте файл:

sudo nano "$HBA_FILE"

Добавьте перед общими правилами:

# Сервер приложения
host  app_db  app_user  198.51.100.20/32  scram-sha-256

Проверка синтаксиса

PostgreSQL предоставляет представление:

pg_hba_file_rules

Проверка всех строк:

sudo -u postgres \
  psql \
  -x \
  -c \
  "SELECT
       line_number,
       type,
       database,
       user_name,
       address,
       netmask,
       auth_method,
       error
   FROM pg_hba_file_rules
   ORDER BY line_number;"

Поиск ошибок

sudo -u postgres \
  psql \
  -c \
  "SELECT
       line_number,
       error
   FROM pg_hba_file_rules
   WHERE error IS NOT NULL;"

Если строк нет, синтаксические ошибки не обнаружены.

Применение без restart

sudo systemctl reload postgresql

Или:

sudo -u postgres \
  psql \
  -c 'SELECT pg_reload_conf();'

Для изменений pg_hba.conf restart обычно не требуется.

Проверка журнала

sudo tail -100 \
  /var/log/postgresql/postgresql-*.log

Или:

sudo journalctl -u postgresql \
  -n 100 \
  --no-pager

Тест с разрешённого клиента

psql \
  -h 192.0.2.10 \
  -p 5432 \
  -U app_user \
  -d app_db

Проверьте:

SELECT
    current_database(),
    current_user,
    inet_client_addr();

Проверка одной командой

psql \
  -h 192.0.2.10 \
  -U app_user \
  -d app_db \
  -c \
  'SELECT current_database(), current_user, inet_client_addr();'

Ошибка no pg_hba.conf entry

Пример:

no pg_hba.conf entry for host "198.51.100.20", user "app_user", database "app_db"

Это означает:

  • соединение дошло до PostgreSQL;
  • сервер слушает адрес;
  • firewall пропустил трафик;
  • подходящее HBA-правило отсутствует.

Ошибка password authentication failed

Проверьте:

  • пароль;
  • роль;
  • порядок правил;
  • формат verifier;
  • поддержку SCRAM клиентом.

Смените пароль:

\password app_user

Ошибка role does not exist

sudo -u postgres \
  psql \
  -Atc \
  "SELECT rolname
   FROM pg_roles
   WHERE rolname = 'app_user';"

Ошибка database does not exist

sudo -u postgres \
  psql \
  -Atc \
  "SELECT datname
   FROM pg_database
   WHERE datname = 'app_db';"

Connection refused и timeout

Эти ошибки не относятся к pg_hba.conf.

Проверьте:

sudo ss -lntp |
grep ':5432'

Проверьте listen_addresses, UFW, маршрутизацию и внешний firewall.

Проверка, какое правило может совпасть

SELECT *
FROM pg_hba_file_rules
ORDER BY line_number;

Сопоставьте:

  • type;
  • database;
  • role;
  • client IP;
  • SSL mode;
  • порядок строк.

Логирование подключений

Проверьте:

SHOW log_connections;

Временно включить:

ALTER SYSTEM
SET log_connections = on;

Применить:

SELECT pg_reload_conf();

Проверяйте журнал:

sudo tail -f \
  /var/log/postgresql/postgresql-*.log

Проверка активных клиентов

SELECT
    a.pid,
    a.usename,
    a.datname,
    a.client_addr,
    a.application_name,
    s.ssl
FROM pg_stat_activity AS a
LEFT JOIN pg_stat_ssl AS s
USING (pid)
WHERE a.client_addr IS NOT NULL
ORDER BY a.pid;

IPv4 и IPv6

Правило IPv4 не разрешает IPv6-подключение.

Проверьте адреса DNS:

getent ahosts db.example.internal

Для одного IPv6-клиента:

host  app_db  app_user  2001:db8::20/128  scram-sha-256

Точные правила предпочтительнее общих

Лучше:

host  app_db  app_user  198.51.100.20/32  scram-sha-256

Хуже:

host  all  all  198.51.100.0/24  scram-sha-256

Чем точнее база, роль и адрес, тем меньше область доступа.

Сохранение локального администрирования

Не удаляйте рабочее правило:

local  all  postgres  peer

Оно позволяет локально исправить пароль и сетевые правила.

Проверка прав файла

sudo stat "$HBA_FILE"

Проверьте владельца:

sudo ls -l "$HBA_FILE"

Не разрешайте обычным пользователям изменять этот файл.

Откат

Восстановите резервную копию:

sudo cp \
  "${HBA_FILE}.before-auth-change" \
  "$HBA_FILE"

Проверьте ошибки:

sudo -u postgres \
  psql \
  -c \
  "SELECT
       line_number,
       error
   FROM pg_hba_file_rules
   WHERE error IS NOT NULL;"

Примените:

sudo systemctl reload postgresql

Типичные ошибки

Разрешающее правило не работает

Выше находится более общее совпадающее правило.

peer указан в host

peer работает только для local.

Пароль сохранён в MD5, а правило требует SCRAM

Задайте пароль повторно после включения password_encryption = 'scram-sha-256'.

Клиент не поддерживает SCRAM

Обновите драйвер или клиентскую библиотеку.

Разрешающее правило размещено после reject

Переместите его выше.

Изменения не применились

Выполните reload и проверьте журнал.

Клиент подключается по IPv6

Добавьте точное IPv6-правило или используйте IPv4-адрес.

Ошибка в маске

Для одного IPv4:

/32

Для одного IPv6:

/128

Безопасный порядок настройки

  1. Найти активный pg_hba.conf.
  2. Создать резервную копию.
  3. Оставить открытое локальное подключение.
  4. Проверить password_encryption.
  5. Пересоздать пароль роли в SCRAM.
  6. Добавить точное правило для базы, роли и IP.
  7. Проверить pg_hba_file_rules.
  8. Выполнить reload.
  9. Проверить подключение с разрешённого клиента.
  10. Проверить отказ с другого адреса.
  11. Проверить журнал.
  12. Только после этого добавлять общий reject.

Быстрый пример

local  all     postgres  peer
host   app_db  app_user  198.51.100.20/32  scram-sha-256
host   all     all       0.0.0.0/0          reject
host   all     all       ::/0               reject

Проверка:

sudo -u postgres \
  psql \
  -c \
  "SELECT
       line_number,
       type,
       database,
       user_name,
       address,
       auth_method,
       error
   FROM pg_hba_file_rules
   ORDER BY line_number;"

Применение:

sudo systemctl reload postgresql

Тест:

psql \
  -h 192.0.2.10 \
  -U app_user \
  -d app_db

Итог

После выполнения инструкции:

  • найден и сохранён активный pg_hba.conf;
  • разобран порядок обработки правил;
  • сохранён локальный административный доступ;
  • настроено точное TCP-правило;
  • включена SCRAM-аутентификация;
  • проверен формат пароля;
  • выполнен reload без остановки сервера;
  • проверены разрешённые и запрещённые подключения;
  • разобраны основные ошибки.

Следующим этапом можно настроить резервное копирование одной базы данных через pg_dump.

← Предыдущая статья Настройка удалённого подключения к PostgreSQL Следующая статья → Резервное копирование одной базы PostgreSQL через pg_dump