Новинка Виртуальный VDS сервер в Нидерландах от 390р
Выберите продукт

PostgreSQL pg_hba.conf на VDS: почему trust 0.0.0.0/0 опасен и как открыть доступ правильно

PostgreSQL не подключается извне, и хочется поставить trust для всех адресов? Разбираем безопасный путь: listen_addresses, точные правила pg_hba.conf, scram-sha-256, firewall и проверка psql на VDS.
PostgreSQL pg_hba.conf на VDS: почему trust 0.0.0.0/0 опасен и как открыть доступ правильно

Типичная ситуация на VDS: PostgreSQL установлен, приложение на другом сервере или рабочая машина администратора пытается подключиться к базе, а в ответ — connection refused, timeout или no pg_hba.conf entry. В поиске быстрых решений часто всплывает строка вида host all all 0.0.0.0/0 trust. Она действительно может «починить» подключение, но делает это самым опасным способом: любой, кто достучится до порта PostgreSQL, сможет войти без пароля под разрешенным пользователем.

В этой статье разберем, как устроен pg_hba.conf, чем отличаются trust, scram-sha-256 и другие методы, зачем нужен listen_addresses, как правильно включить доступ к PostgreSQL на VDS и где должен стоять firewall. Цель — не просто заставить порт 5432 отвечать, а сделать это контролируемо и безопасно.

Короткое правило: trust не должен использоваться для удаленного доступа. Строка 0.0.0.0/0 trust на публичном интерфейсе VDS — это фактически вход без ключа в серверную комнату.

Что именно настраивает pg_hba.conf

Файл pg_hba.conf отвечает не за то, слушает ли PostgreSQL сеть, а за то, кому и каким способом разрешено аутентифицироваться. Аббревиатура HBA расшифровывается как host-based authentication: правила доступа по типу соединения, базе, пользователю, адресу клиента и методу проверки.

Каждая значимая строка в pg_hba.conf читается слева направо и обычно имеет такую структуру:

TYPE  DATABASE  USER  ADDRESS  METHOD

Для локальных Unix-сокетов поле ADDRESS отсутствует:

local  all  postgres  peer

Для TCP/IP-подключений адрес указывается в CIDR-формате:

host  appdb  appuser  203.0.113.10/32  scram-sha-256

Ключевой нюанс: PostgreSQL применяет первое подходящее правило. Если выше стоит широкое правило host all all 0.0.0.0/0 trust, то более строгие строки ниже могут никогда не сработать. Поэтому порядок в pg_hba.conf так же важен, как и сами методы аутентификации.

Почему trust 0.0.0.0/0 почти всегда ошибка

Метод trust означает: «доверять клиенту без проверки пароля». Для локального одноразового стенда это иногда удобно: например, в тестовом контейнере, который живет несколько минут и не публикует порт наружу. Но на VDS с публичным IP-адресом такая настройка превращается в критическую дыру.

Строка ниже разрешает подключение к любой базе любому пользователю с любого IPv4-адреса без пароля:

host  all  all  0.0.0.0/0  trust

Если дополнительно PostgreSQL слушает внешний интерфейс через listen_addresses = '*', а порт 5432 открыт в firewall, база становится доступной всему интернету. Даже если кажется, что «имя пользователя никто не знает», это слабая защита: стандартные роли, утечки конфигов приложений, старые бэкапы, логи деплоя и перебор имен быстро превращают такую настройку в инцидент.

Для IPv6 аналогичная проблема выглядит так:

host  all  all  ::/0  trust

Иногда администратор открывает только IPv4 и забывает, что на VDS уже включен IPv6. В результате PostgreSQL может оказаться доступен через адрес, который не проверяли. Поэтому при аудите смотрите оба семейства адресов: IPv4 и IPv6.

Три слоя доступа: listen_addresses, pg_hba.conf и firewall

Чтобы удаленное подключение к PostgreSQL заработало, должны совпасть три условия. Первое — сам PostgreSQL должен слушать нужный адрес. За это отвечает параметр listen_addresses в postgresql.conf. Второе — в pg_hba.conf должно быть правило, которое разрешает клиенту аутентификацию. Третье — сетевой экран на VDS и, если используется, внешний firewall провайдера должны пропускать TCP-порт 5432 только от нужных источников.

Важно не путать эти уровни. Если listen_addresses оставлен равным localhost, PostgreSQL не будет принимать подключения на публичный IP, даже если в pg_hba.conf прописан весь интернет. Если pg_hba.conf не содержит подходящего правила, клиент увидит отказ после установления TCP-соединения. Если firewall закрыт, подключение обычно будет зависать по таймауту или сразу получать отказ на сетевом уровне.

Схема уровней доступа к PostgreSQL: listen_addresses, pg_hba.conf и firewall

Как найти реальные пути к конфигам

Пути к файлам зависят от дистрибутива, версии PostgreSQL и способа установки. Не угадывайте — спросите сам сервер PostgreSQL.

sudo -u postgres psql -c 'SHOW config_file;'
sudo -u postgres psql -c 'SHOW hba_file;'
sudo -u postgres psql -c 'SHOW data_directory;'

На Debian и Ubuntu при пакетной установке часто используются пути вида:

/etc/postgresql/16/main/postgresql.conf
/etc/postgresql/16/main/pg_hba.conf

Посмотреть кластеры PostgreSQL в Debian/Ubuntu удобно так:

pg_lsclusters

В RHEL-based дистрибутивах — AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux — и в Fedora путь часто находится в каталоге данных, например:

/var/lib/pgsql/16/data/postgresql.conf
/var/lib/pgsql/16/data/pg_hba.conf

Но для системных пакетов без PGDG-репозитория путь может отличаться, поэтому команды SHOW config_file; и SHOW hba_file; надежнее любых шпаргалок.

Настраиваем listen_addresses без лишнего расширения поверхности атаки

Параметр listen_addresses определяет, на каких IP-адресах PostgreSQL будет принимать TCP-подключения. Значение localhost безопасно по умолчанию: база доступна только с того же сервера. Значение * заставляет PostgreSQL слушать все доступные интерфейсы, включая публичный IPv4, IPv6 и приватные адреса.

Для продакшена лучше указывать конкретный адрес, если архитектура это позволяет. Например, если приложение подключается к PostgreSQL по приватной сети, слушайте приватный IP, а не все интерфейсы:

listen_addresses = '127.0.0.1,10.10.0.5'

Если отдельной приватной сети нет и подключение идет через публичный адрес VDS, можно указать публичный IP явно:

listen_addresses = '127.0.0.1,198.51.100.5'

Временное значение * допустимо для диагностики, но после проверки лучше заменить его на конкретный список адресов:

listen_addresses = '*'

Изменение listen_addresses требует перезапуска PostgreSQL, потому что это параметр уровня postmaster. Обычного reload недостаточно.

Перезапуск PostgreSQL

Debian/Ubuntu:

sudo systemctl restart postgresql

RHEL-based и Fedora при установке PostgreSQL из PGDG-пакетов часто используют unit с версией:

sudo systemctl restart postgresql-16

Если не уверены в имени сервиса, посмотрите доступные unit-файлы:

systemctl list-units 'postgresql*'
FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды

Безопасный pg_hba.conf: минимально нужные правила

Хороший pg_hba.conf начинается с принципа минимальных прав. Разрешайте не «всем ко всему», а конкретному пользователю доступ к конкретной базе с конкретного адреса или подсети. Для приложения это обычно выглядит так:

# Локальный администратор PostgreSQL через Unix-сокет
local  all  postgres  peer

# Локальные TCP-подключения
host  all  all  127.0.0.1/32  scram-sha-256
host  all  all  ::1/128  scram-sha-256

# Приложение с одного внешнего IP
host  appdb  appuser  203.0.113.10/32  scram-sha-256

Если приложение находится в приватной сети VDS, лучше разрешить именно приватную подсеть:

host  appdb  appuser  10.10.0.0/24  scram-sha-256

Если вы включили SSL в PostgreSQL и хотите принимать удаленные подключения только по TLS, используйте hostssl. Тогда обычные незашифрованные TCP-подключения не подойдут под это правило:

hostssl  appdb  appuser  203.0.113.10/32  scram-sha-256

Для hostssl в postgresql.conf должен быть включен параметр ssl, а серверу нужны корректные сертификат и ключ. Если TLS пока не настроен, используйте host вместе со строгим firewall, но запланируйте включение шифрования, особенно если трафик идет не по приватному каналу.

Что делать с широкими правилами

Иногда в старых инструкциях встречается компромиссный вариант:

host  all  all  0.0.0.0/0  md5

Он лучше, чем trust, потому что требует пароль, но все равно слишком широк для VDS. Любой внешний адрес сможет пытаться пройти аутентификацию. Это увеличивает шум в логах, поверхность атаки и риск подбора слабого пароля. Если нужен доступ с динамического домашнего IP, лучше использовать VPN, bastion-host, SSH-туннель или регулярно обновляемый allowlist, а не открывать 0.0.0.0/0. Для постоянных связок между серверами можно посмотреть подход с site-to-site VPN на WireGuard.

Включаем scram-sha-256 и обновляем пароль роли

Для современных PostgreSQL предпочтительный метод парольной аутентификации — scram-sha-256. Он безопаснее старого md5 и должен быть стандартом для новых инсталляций. Но есть нюанс: если роль уже имела пароль, сохраненный в старом формате, простая замена метода в pg_hba.conf может привести к ошибкам подключения. Нужно убедиться, что новые пароли сохраняются как SCRAM, и переустановить пароль роли.

Проверьте текущий режим:

sudo -u postgres psql -c 'SHOW password_encryption;'

Установите scram-sha-256 как режим для новых паролей:

sudo -u postgres psql -c "ALTER SYSTEM SET password_encryption = 'scram-sha-256';"
sudo -u postgres psql -c 'SELECT pg_reload_conf();'

Теперь задайте новый пароль приложению. Используйте длинный случайный пароль из менеджера секретов, а не пример из статьи:

sudo -u postgres psql -c "ALTER ROLE appuser WITH PASSWORD 'replace_with_long_random_password';"

После этого строка в pg_hba.conf с методом scram-sha-256 будет работать корректно для этой роли. Если у вас старые клиенты или драйверы PostgreSQL, проверьте их совместимость с SCRAM заранее: очень старые библиотеки могут поддерживать только md5.

Reload pg_hba.conf и проверка синтаксиса

После изменения pg_hba.conf обычно достаточно reload, перезапуск не нужен. PostgreSQL перечитает правила доступа без разрыва уже установленных соединений.

Debian/Ubuntu:

sudo systemctl reload postgresql

RHEL-based и Fedora для PGDG-пакетов:

sudo systemctl reload postgresql-16

Также можно выполнить reload из SQL:

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

Если в pg_hba.conf есть синтаксическая ошибка, PostgreSQL обычно оставит старые правила активными и запишет проблему в журнал. Поэтому после изменения сразу смотрите логи.

Debian/Ubuntu с systemd:

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

RHEL-based и Fedora:

journalctl -u postgresql-16 -n 100 --no-pager

Внутри PostgreSQL можно проверить, применились ли настройки:

sudo -u postgres psql -c "SELECT name, setting, context FROM pg_settings WHERE name IN ('listen_addresses', 'password_encryption');"

Firewall PostgreSQL: открываем порт только нужным адресам

Даже идеально настроенный pg_hba.conf не заменяет firewall. Сетевой экран должен отсекать лишние подключения до того, как они попадут в PostgreSQL. На VDS это особенно важно: публичный IP регулярно сканируется автоматическими ботами, и открытый 5432 быстро окажется в их списках.

Если используете UFW на Debian/Ubuntu, разрешите порт только от IP приложения или администратора:

sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp
sudo ufw status verbose

Если у вас firewalld на AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux или Fedora, можно добавить rich rule:

sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=203.0.113.10 port port=5432 protocol=tcp accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Для nftables правило зависит от вашей базовой структуры таблиц и цепочек. Пример для таблицы inet filter и цепочки input:

sudo nft add rule inet filter input ip saddr 203.0.113.10 tcp dport 5432 accept

Если на сервере параллельно работают контейнеры, проверьте, не меняет ли Docker ожидаемую логику фильтрации. Подробно этот нюанс разобран в статье про Docker, iptables и nftables на VDS.

Если у провайдера есть отдельный облачный firewall или security group, продублируйте ограничение там. Лучшая схема — когда порт 5432 закрыт для всего интернета и открыт только для конкретных IP или приватной сети. Тогда даже ошибка в pg_hba.conf не сразу становится доступной извне.

Проверяем, что PostgreSQL слушает нужный адрес

После изменения listen_addresses и перезапуска проверьте, на каких адресах открыт порт 5432:

ss -lntp | grep 5432

Если видите только 127.0.0.1:5432, удаленный клиент не подключится. Если видите 0.0.0.0:5432, PostgreSQL слушает все IPv4-интерфейсы. Это не всегда ошибка, но тогда firewall и pg_hba.conf должны быть особенно строгими. Если видите [::]:5432, проверьте IPv6-правила тоже.

С клиентской машины проверьте подключение:

psql -h 198.51.100.5 -p 5432 -U appuser -d appdb -c 'select current_user, inet_client_addr();'

Если подключение успешно, команда покажет текущего пользователя и адрес клиента, который видит PostgreSQL. Это полезно для проверки, совпадает ли реальный исходящий IP клиента с тем, что вы прописали в allowlist.

Настройка allowlist в firewall для сервера PostgreSQL

Разбор частых ошибок

connection refused

Ошибка connection refused означает, что TCP-соединение отвергнуто: PostgreSQL не слушает указанный адрес и порт, сервис не запущен или локальный firewall активно отклоняет соединение. Начинайте с проверки сервиса и сокетов:

systemctl status postgresql
ss -lntp | grep 5432

Для RHEL-based систем с версионным unit используйте имя своего сервиса, например postgresql-16.

timeout

Таймаут чаще всего связан с firewall, внешней security group, маршрутизацией или попыткой подключиться не к тому IP. На сервере проверьте, приходят ли пакеты на порт 5432:

sudo tcpdump -ni any tcp port 5432

Если пакеты не приходят, проблема до сервера: адрес, маршрут, внешний firewall, NAT или правило у клиента. Если приходят, но ответа нет, смотрите локальный firewall и состояние PostgreSQL.

no pg_hba.conf entry

Сообщение no pg_hba.conf entry означает, что TCP-соединение дошло до PostgreSQL, но ни одно правило pg_hba.conf не подошло по базе, пользователю, адресу, SSL-режиму или типу соединения. Проверьте реальный IP клиента, имя базы, имя роли и порядок строк. Часто проблема в том, что у клиента NAT, и PostgreSQL видит не тот адрес, который ожидал администратор.

password authentication failed

Если правило найдено, но пароль не принят, проверьте пароль роли, метод scram-sha-256, совместимость клиента и то, к той ли базе идет подключение. Для приложений также проверьте переменные окружения и секреты в systemd unit, Docker Compose или CI/CD: старый пароль часто остается именно там.

Практический безопасный сценарий для VDS

Соберем все в один понятный сценарий. Допустим, PostgreSQL работает на VDS с адресом 198.51.100.5, приложение подключается с адреса 203.0.113.10, база называется appdb, роль — appuser.

В postgresql.conf указываем адреса, которые должен слушать PostgreSQL:

listen_addresses = '127.0.0.1,198.51.100.5'
password_encryption = 'scram-sha-256'

В pg_hba.conf оставляем локальный доступ и добавляем точечное правило для приложения:

local  all  postgres  peer
host  all  all  127.0.0.1/32  scram-sha-256
host  all  all  ::1/128  scram-sha-256
host  appdb  appuser  203.0.113.10/32  scram-sha-256

Открываем firewall только для IP приложения:

sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp

Перезапускаем PostgreSQL, потому что меняли listen_addresses:

sudo systemctl restart postgresql

Задаем роли новый пароль в SCRAM-формате:

sudo -u postgres psql -c "ALTER ROLE appuser WITH PASSWORD 'replace_with_long_random_password';"

Проверяем с клиентской стороны:

psql -h 198.51.100.5 -U appuser -d appdb -c 'select current_user, inet_client_addr();'

Такой вариант не полагается на один-единственный барьер. Даже если пароль случайно утечет, подключиться сможет только разрешенный источник. Даже если firewall временно станет шире, pg_hba.conf не пустит произвольных пользователей ко всем базам. Именно многослойность делает настройку устойчивой.

Когда trust все-таки допустим

Метод trust не является «запрещенной командой», но у него очень узкая зона применения. Его можно встретить в локальной разработке, изолированных CI-контейнерах, одноразовых тестовых окружениях или при аварийном восстановлении доступа, когда порт PostgreSQL не опубликован наружу и сервер изолирован сетевыми правилами.

Даже в таких случаях лучше ограничивать trust локальным сокетом или loopback-адресом:

local  all  postgres  peer
host  all  all  127.0.0.1/32  trust

Но для постоянной работы PostgreSQL на VDS, особенно если база доступна с других серверов, используйте scram-sha-256, точные CIDR-адреса, отдельные роли для приложений и firewall. А строку host all all 0.0.0.0/0 trust лучше воспринимать как временный диагностический костыль, который нельзя оставлять после проверки.

Итоговый чек-лист

  • Не используйте host all all 0.0.0.0/0 trust и host all all ::/0 trust на VDS с публичным доступом.
  • Проверьте реальные пути к postgresql.conf и pg_hba.conf командами SHOW config_file; и SHOW hba_file;.
  • Настройте listen_addresses на конкретные IP-адреса, а не на *, если это возможно.
  • В pg_hba.conf разрешайте конкретную базу, конкретную роль и конкретный IP или подсеть.
  • Используйте scram-sha-256 и переустановите пароли ролей после включения password_encryption.
  • Ограничьте порт 5432 на уровне firewall: UFW, firewalld, nftables и внешний firewall провайдера должны пропускать только нужные источники.
  • После изменения listen_addresses перезапускайте PostgreSQL, после изменения pg_hba.conf обычно достаточно reload.
  • Проверяйте результат с обеих сторон: ss на сервере и psql с клиентской машины.

Главная мысль простая: удаленный доступ к PostgreSQL должен быть осознанным, а не «открытым на всякий случай». Настройте listen_addresses, pg_hba.conf, scram-sha-256 и firewall как одну систему — и база будет доступна приложению, но не всему интернету.

Поделиться статьей

Вам будет интересно

PostgreSQL на VDS: pg_hba.conf, SCRAM и TLS для безопасного доступа OpenAI Статья написана AI (GPT 5)

PostgreSQL на VDS: pg_hba.conf, SCRAM и TLS для безопасного доступа

PostgreSQL удобно держать на VDS, но открывать порт 5432 «как есть» нельзя. Разберём, как включить сетевые подключения, описать пр ...
Ansible на VDS: inventory, become, SSH-ключи и первый playbook OpenAI Статья написана AI (GPT 5)

Ansible на VDS: inventory, become, SSH-ключи и первый playbook

Разберём, как подготовить Ansible для управления VDS: собрать inventory, настроить SSH-ключи, проверить доступ, аккуратно включить ...
systemd-tmpfiles: безопасная очистка /tmp и кэшей вместо cron rm -rf OpenAI Статья написана AI (GPT 5)

systemd-tmpfiles: безопасная очистка /tmp и кэшей вместо cron rm -rf

Когда /tmp разрастается, рука тянется к cron и rm -rf. Разбираем, почему это рискованно, как работает systemd-tmpfiles, где лежат ...