Не подключается PostgreSQL по TCP/IP: причины и решение

    При попытке подключиться к PostgreSQL на удалённом сервере Ubuntu по протоколу TCP/IP возникает ошибка, хотя через SSH-туннель соединение работает отлично. Это частая проблема, связанная с настройками сетевого экрана, правилами iptables или конфигурацией самой базы данных. В этой статье разберём все возможные причины и пошагово устраним неполадки.

    Основные причины ошибки подключения к PostgreSQL по TCP/IP

    Если HeidiSQL или Python не могут соединиться с PostgreSQL по прямому TCP-соединению, но SSH-туннель работает - проблема не в сети, а в настройках сервера. Рассмотрим три главных блока.

    1. Проверка файла pg_hba.conf

    Файл pg_hba.conf управляет правилами аутентификации. Для удалённого доступа по TCP/IP необходимо разрешить подключения с внешних IP-адресов. В вашем примере строка host all all 0.0.0.0/0 md5 уже присутствует - это правильно. Однако убедитесь, что нет более строгих правил выше, которые блокируют доступ. Порядок строк важен: PostgreSQL использует первое совпадение.

    Рекомендуется разместить разрешающее правило для всех сетей до локальных ограничений:

    host    all             all             0.0.0.0/0               md5
    host    all             all             ::/0                    md5

    После изменения файла перезагрузите PostgreSQL командой sudo systemctl reload postgresql.

    2. Настройка ufw (Uncomplicated Firewall)

    Вы уже открыли порт 5432 в ufw, но обратите внимание: статус показывает 5432/tcp ALLOW Anywhere. Этого должно быть достаточно. Однако если на сервере есть другие сетевые интерфейсы (например, Docker), трафик может идти через них. Проверьте, что правило применяется к основному интерфейсу. Дополнительно убедитесь, что ufw не блокирует входящие соединения с вашего IP. В вашем списке есть строка Anywhere ALLOW {ip рабочего компьютера} - это корректно.

    3. Правила iptables

    Команда sudo iptables -A INPUT -p tcp --dport 5432 -j ACCEPT добавляет правило, но оно может быть переопределено другими правилами или сброшено после перезагрузки. Для постоянного применения используйте iptables-persistent или ufw. Рекомендуем полностью отключить iptables для теста: sudo iptables -P INPUT ACCEPT и sudo iptables -F. Если после этого подключение заработает - значит проблема в iptables.

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

    Шаг 1. Проверка слушающих адресов PostgreSQL

    В файле postgresql.conf параметр listen_addresses = '*' указывает, что сервер слушает на всех интерфейсах. Убедитесь, что эта строка не закомментирована. Проверьте логи PostgreSQL - в них должно быть listening on IPv4 address "0.0.0.0", port 5432. Если там указан конкретный IP, замените на '*'.

    Шаг 2. Тестирование подключения с сервера

    На самом сервере выполните psql -h 127.0.0.1 -U postgres -d postgres. Если это работает, значит PostgreSQL настроен правильно для локальных TCP-соединений. Затем проверьте с внешнего IP: psql -h <внешний IP сервера> -U postgres -d postgres. Если не работает - проблема в сетевом экране или маршрутизации.

    Шаг 3. Проверка telnet с сервера на себя

    Выполните на сервере telnet 127.0.0.1 5432. Должен появиться пустой экран или ответ от PostgreSQL. Если соединение отклоняется - PostgreSQL не слушает на этом порту. Проверьте, что сервис активен: sudo systemctl status postgresql. В вашем логе статус active (exited) - это нормально для основного процесса, но убедитесь, что дочерние процессы работают.

    Что делать, если ничего не помогло?

    Если после всех проверок подключение по TCP/IP всё ещё не работает, возможно, проблема на уровне провайдера или виртуальной машины (VPS). Некоторые хостинг-провайдеры блокируют порт 5432 на внешнем фаерволе. В таком случае используйте SSH-туннель как надёжную альтернативу. Для этого в HeidiSQL настройте SSH-соединение, указав хост, порт 22 и логин. Через туннель PostgreSQL будет доступен локально на порту 5432.

    Для Python используйте библиотеку sshtunnel:

    from sshtunnel import SSHTunnelForwarder
    import psycopg2
    
    with SSHTunnelForwarder(
        ('your_server_ip', 22),
        ssh_username='user',
        ssh_password='pass',
        remote_bind_address=('127.0.0.1', 5432)
    ) as tunnel:
        conn = psycopg2.connect(
            host='127.0.0.1',
            port=tunnel.local_bind_port,
            user='postgres',
            password='pass',
            database='mydb'
        )

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

    Заключение

    Ошибка подключения к PostgreSQL по TCP/IP при работающем SSH-туннеле чаще всего связана с настройками pg_hba.conf, ufw или iptables. Проверьте все три компонента, перезагрузите PostgreSQL и убедитесь, что сервер слушает на всех интерфейсах. Если проблема остаётся - используйте SSH-туннель как временное или постоянное решение. Надеемся, наша инструкция помогла вам восстановить удалённый доступ к базе данных.

    Часто задаваемые вопросы