Настройка удалённого подключения к PostgreSQL

Пошаговая настройка PostgreSQL для подключения с другого сервера: listen_addresses, порт 5432, firewall и проверка доступности.

По умолчанию PostgreSQL в Ubuntu обычно принимает подключения только локально. Чтобы приложение на другом сервере могло подключиться к базе данных, нужно разрешить прослушивание сетевого интерфейса, открыть доступ в firewall и проверить маршрут.

В этой инструкции рассматривается только сетевой уровень удалённого подключения:

  • параметр listen_addresses;
  • порт PostgreSQL;
  • UFW;
  • проверка доступности;
  • диагностика сетевых ошибок.

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

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

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

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

  • будет определён адрес сервера PostgreSQL;
  • PostgreSQL начнёт слушать нужный сетевой интерфейс;
  • будет открыт порт 5432/tcp только для доверенного клиента;
  • будет проверен маршрут между серверами;
  • будет выполнена проверка через pg_isready и psql;
  • будут разобраны ошибки connection refused и timeout.

Исходная схема

В примерах используется:

PostgreSQL-сервер: 192.0.2.10
Сервер приложения: 198.51.100.20
Порт PostgreSQL: 5432
База данных: app_db
Роль: app_user

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

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

Не открывайте PostgreSQL для всего интернета.

Опасный вариант:

0.0.0.0/0

или правило firewall:

sudo ufw allow 5432/tcp

без ограничения источника.

Безопаснее разрешать доступ:

  • одному IP;
  • подсети приложения;
  • VPN-подсети;
  • приватной сети;
  • отдельному bastion host.

Проверка текущего состояния

Проверьте кластеры:

pg_lsclusters

Проверьте готовность:

sudo -u postgres pg_isready

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

sudo -u postgres   psql   -Atc 'SHOW port;'

Проверка listen_addresses

sudo -u postgres   psql   -Atc 'SHOW listen_addresses;'

На локальной установке часто используется:

localhost

Это означает, что сервер не принимает подключения с других узлов.

Определение конфигурационного файла

sudo -u postgres   psql   -Atc 'SHOW config_file;'

Пример:

/etc/postgresql/VERSION/main/postgresql.conf

Определение сетевых интерфейсов

ip -br addr

Пример:

lo       UNKNOWN  127.0.0.1/8
ens18    UP       192.0.2.10/24

Выберите адрес интерфейса, через который сервер приложения достигает PostgreSQL.

Проверка маршрута до клиента

С PostgreSQL-сервера:

ip route get 198.51.100.20

Проверьте:

  • используемый интерфейс;
  • исходный адрес;
  • шлюз;
  • наличие маршрута.

Проверка маршрута с клиента

На сервере приложения:

ip route get 192.0.2.10

Маршрут должен вести к PostgreSQL-серверу.

Создание резервной копии конфигурации

CONFIG_FILE="$(
  sudo -u postgres     psql     -Atc 'SHOW config_file;'
)"
sudo cp   "$CONFIG_FILE"   "${CONFIG_FILE}.before-remote-access"

Проверьте:

sudo ls -l   "${CONFIG_FILE}"*

Настройка одного IP-адреса

Откройте конфигурацию:

sudo nano "$CONFIG_FILE"

Найдите:

listen_addresses

Задайте:

listen_addresses = '127.0.0.1,192.0.2.10'

Так PostgreSQL будет слушать:

  • localhost;
  • внутренний адрес сервера.

Прослушивание всех интерфейсов

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

listen_addresses = '*'

Это разрешает PostgreSQL слушать все доступные интерфейсы.

Такой вариант допустим только при строгом firewall и корректном pg_hba.conf.

Для небольших инфраструктур предпочтительнее указывать конкретные адреса.

Прослушивание IPv6

Пример:

listen_addresses = '127.0.0.1,::1,2001:db8::10'

Проверьте, что IPv6 действительно используется и защищён firewall.

Проверка параметра port

В конфигурации:

port = 5432

Если стандартный порт подходит, менять его не требуется.

Изменение порта не является полноценной мерой безопасности.

Проверка значения в конфигурации

sudo grep -nE   '^[[:space:]]*listen_addresses|^[[:space:]]*port'   "$CONFIG_FILE"

Применение конфигурации

Изменение listen_addresses требует restart.

sudo systemctl restart postgresql

Проверьте:

systemctl status postgresql --no-pager

Проверьте кластер:

pg_lsclusters

Проверка журнала после restart

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

Для systemd:

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

Проверка фактического значения

sudo -u postgres   psql   -Atc 'SHOW listen_addresses;'

Проверка прослушиваемого порта

sudo ss -lntp |
grep ':5432'

Ожидается:

127.0.0.1:5432
192.0.2.10:5432

или:

0.0.0.0:5432

при listen_addresses = '*'.

Проверка IPv6

sudo ss -lntp6 |
grep ':5432'

Проверка UFW

sudo ufw status verbose

Если UFW неактивен, проверьте внешний firewall, security group или сетевые ACL.

Разрешение одного IP

sudo ufw allow   from 198.51.100.20   to any port 5432   proto tcp

Проверьте:

sudo ufw status numbered

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

sudo ufw allow   from 198.51.100.0/24   to any port 5432   proto tcp

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

Разрешение на конкретный интерфейс

sudo ufw allow in on ens18   from 198.51.100.20   to any port 5432   proto tcp

Проверьте имя интерфейса:

ip -br link

Ограничение приватной сетью

Если приложение и PostgreSQL находятся в одной приватной сети, используйте внутренние адреса.

Пример:

PostgreSQL: 10.10.0.10
Приложение: 10.10.0.20

Правило:

sudo ufw allow   from 10.10.0.20   to 10.10.0.10 port 5432   proto tcp

Проверка внешнего firewall

В облачной или виртуальной инфраструктуре дополнительно проверьте:

  • security group;
  • provider firewall;
  • VLAN ACL;
  • router ACL;
  • NAT;
  • Proxmox firewall;
  • межсетевой экран гипервизора.

Локальное правило UFW может быть корректным, но трафик всё равно блокируется на другом уровне.

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

На сервере приложения:

nc -zv 192.0.2.10 5432

Если nc отсутствует:

sudo apt update
sudo apt install -y netcat-openbsd

Успешный результат:

succeeded

Проверка через pg_isready

На клиентском сервере:

pg_isready   -h 192.0.2.10   -p 5432

Пример успешного сетевого ответа:

192.0.2.10:5432 - accepting connections

pg_isready проверяет доступность сервера, но не подтверждает, что конкретная роль имеет доступ к базе.

Установка клиента PostgreSQL

На сервере приложения:

sudo apt update
sudo apt install -y postgresql-client

Проверьте:

psql --version

Попытка подключения

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

На этом этапе возможно сообщение:

no pg_hba.conf entry

Это означает, что сетевой доступ уже работает, но правило аутентификации ещё не настроено.

Настройка pg_hba.conf рассматривается в следующей статье.

Разница между сетевой и аутентификационной ошибкой

Connection refused

could not connect to server: Connection refused

Обычно означает:

  • PostgreSQL не слушает внешний адрес;
  • служба не запущена;
  • неверный IP;
  • неверный порт;
  • соединение активно отклоняется.

Timeout

connection timed out

Обычно означает:

  • firewall блокирует трафик;
  • отсутствует маршрут;
  • security group не разрешает порт;
  • сервер недоступен;
  • неверный NAT.

No pg_hba.conf entry

no pg_hba.conf entry for host

Означает:

  • TCP-соединение дошло до PostgreSQL;
  • сервер работает;
  • сетевой доступ разрешён;
  • отсутствует подходящее правило аутентификации.

Password authentication failed

Означает:

  • соединение дошло до сервера;
  • правило pg_hba.conf найдено;
  • пароль или роль неверны.

Проверка через tcpdump

На PostgreSQL-сервере:

sudo tcpdump   -ni any   host 198.51.100.20   and port 5432

Затем повторите подключение с клиента.

Если пакеты не появляются, проблема находится до PostgreSQL-сервера.

Остановить:

Ctrl+C

Проверка SYN-пакетов

sudo tcpdump   -nn   -i any   'tcp port 5432 and tcp[tcpflags] & tcp-syn != 0'

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

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

Повторите подключение с клиента.

Если сервер получил запрос, в журнале может появиться запись об ошибке аутентификации.

Проверка bind через lsof

sudo lsof   -nP   -iTCP:5432   -sTCP:LISTEN

Проверка firewall через nftables

UFW использует backend firewall системы.

Проверьте:

sudo nft list ruleset |
grep -n 5432

Не изменяйте правила nftables вручную, если сервер управляется через UFW, без чёткого понимания порядка правил.

Проверка iptables

На системах с совместимым frontend:

sudo iptables -S |
grep 5432

Проверка localhost после изменения

sudo -u postgres   psql   -h 127.0.0.1   -d postgres   -c 'SELECT 1;'

Локальные приложения не должны потерять доступ после изменения listen_addresses.

Проверка Unix socket

sudo -u postgres   psql   -d postgres   -c 'SELECT 1;'

Unix socket работает независимо от внешнего TCP bind.

Подключение по DNS-имени

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

psql   -h db.example.internal   -U app_user   -d app_db

Проверьте DNS:

getent hosts db.example.internal

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

dig +short db.example.internal

DNS должен возвращать нужный адрес PostgreSQL-сервера.

Использование внутреннего DNS

Для приватной инфраструктуры лучше использовать внутреннее имя:

db01.example.internal

Это упрощает перенос сервиса без изменения конфигурации приложения.

Подключение через VPN

Безопасный вариант:

Приложение → VPN → PostgreSQL

PostgreSQL слушает VPN-адрес:

listen_addresses = '127.0.0.1,10.20.0.10'

Firewall разрешает только VPN-подсеть.

Подключение через SSH-туннель

Для временного административного доступа можно использовать:

ssh   -L 15432:127.0.0.1:5432   ADMIN_USER@SERVER_IP

Затем локально:

psql   -h 127.0.0.1   -p 15432   -U app_user   -d app_db

В этом случае PostgreSQL может продолжать слушать только localhost.

SSH-туннель удобен для администрирования, но не всегда подходит как постоянное соединение приложения.

Проверка established-соединений

После подключения:

sudo ss -ntp |
grep ':5432'

В PostgreSQL:

sudo -u postgres   psql   -c   "SELECT
       usename,
       datname,
       client_addr,
       client_port,
       application_name
   FROM pg_stat_activity
   WHERE client_addr IS NOT NULL;"

application_name клиента

Подключение:

PGAPPNAME=app-server psql   -h 192.0.2.10   -U app_user   -d app_db

Проверка на сервере:

SELECT
    usename,
    application_name,
    client_addr
FROM pg_stat_activity
WHERE application_name = 'app-server';

Несколько сетевых интерфейсов

Если сервер имеет:

public IP
private IP
VPN IP

не используйте * без необходимости.

Пример:

listen_addresses = '127.0.0.1,10.10.0.10,10.20.0.10'

Так PostgreSQL не будет слушать публичный интерфейс.

Проверка публичного экспонирования

С внешнего недоверенного узла:

nc -zv PUBLIC_SERVER_IP 5432

Соединение должно быть заблокировано.

Не используйте port change как основную защиту

Перенос PostgreSQL на:

15432

может уменьшить шум автоматического сканирования, но не заменяет:

  • firewall;
  • pg_hba.conf;
  • сильные пароли;
  • TLS;
  • приватную сеть;
  • мониторинг.

Проверка после перезагрузки сервера

После плановой перезагрузки:

pg_lsclusters
sudo ss -lntp |
grep ':5432'

С клиента:

pg_isready   -h 192.0.2.10   -p 5432

Откат listen_addresses

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

sudo cp   "${CONFIG_FILE}.before-remote-access"   "$CONFIG_FILE"

Перезапустите:

sudo systemctl restart postgresql

Проверьте:

sudo -u postgres   psql   -Atc 'SHOW listen_addresses;'

Удаление правила UFW

Покажите правила:

sudo ufw status numbered

Удалите по номеру:

sudo ufw delete RULE_NUMBER

Повторно проверьте:

sudo ufw status numbered

Типичные проблемы

PostgreSQL продолжает слушать только localhost

Проверьте фактический файл:

sudo -u postgres   psql   -Atc 'SHOW config_file;'

Проверьте значение:

sudo -u postgres   psql   -Atc 'SHOW listen_addresses;'

Убедитесь, что выполнен restart, а не только reload.

Порт доступен локально, но недоступен удалённо

Проверьте:

  • UFW;
  • provider firewall;
  • маршрут;
  • VLAN ACL;
  • security group;
  • адрес bind;
  • NAT.

nc показывает timeout

Проверьте пакеты через tcpdump.

Если SYN не приходит, проблема вне PostgreSQL.

nc показывает connection refused

Проверьте:

sudo ss -lntp |
grep ':5432'

Проверьте адрес, на котором слушает PostgreSQL.

pg_isready отвечает, но psql не подключается

Сеть работает.

Проверьте:

  • pg_hba.conf;
  • роль;
  • пароль;
  • базу;
  • SSL mode.

Подключение работает по IP, но не по имени

Проверьте DNS:

getent hosts db.example.internal

Проверьте /etc/hosts, resolver и DNS TTL.

После restart PostgreSQL не запускается

Проверьте:

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

Проверьте синтаксис строки listen_addresses.

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

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

  1. Определить доверенный IP клиента.
  2. Проверить маршрут между серверами.
  3. Создать резервную копию postgresql.conf.
  4. Указать конкретный адрес в listen_addresses.
  5. Выполнить restart.
  6. Проверить ss.
  7. Открыть UFW только для клиента.
  8. Проверить nc.
  9. Проверить pg_isready.
  10. Выполнить тест psql.
  11. Проверить журнал PostgreSQL.
  12. Перейти к настройке pg_hba.conf.

Быстрый набор команд

Проверить конфигурацию:

sudo -u postgres   psql   -Atc 'SHOW config_file;'

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

sudo -u postgres   psql   -Atc 'SHOW listen_addresses;'

После изменения:

sudo systemctl restart postgresql

Проверить bind:

sudo ss -lntp |
grep ':5432'

Разрешить клиент:

sudo ufw allow   from 198.51.100.20   to any port 5432   proto tcp

Проверить с клиента:

pg_isready   -h 192.0.2.10   -p 5432

Итог

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

  • определён сетевой адрес PostgreSQL-сервера;
  • настроен listen_addresses;
  • проверен порт 5432;
  • создано ограниченное правило firewall;
  • проверены маршрут и доступность;
  • выполнена диагностика через nc, pg_isready и tcpdump;
  • разобраны сетевые и аутентификационные ошибки.

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

← Предыдущая статья Основы работы с psql