Настройка 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
Безопасный порядок настройки
- Найти активный
pg_hba.conf. - Создать резервную копию.
- Оставить открытое локальное подключение.
- Проверить
password_encryption. - Пересоздать пароль роли в SCRAM.
- Добавить точное правило для базы, роли и IP.
- Проверить
pg_hba_file_rules. - Выполнить reload.
- Проверить подключение с разрешённого клиента.
- Проверить отказ с другого адреса.
- Проверить журнал.
- Только после этого добавлять общий
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.