Удалённый доступ к базе данных: SSH-туннель и TLS
Открыть порт 5432 или 3306 наружу — самый быстрый способ поймать взлом. Базу данных нельзя выставлять в интернет напрямую. Правильные варианты — SSH-туннель и шифрование TLS. Разберём оба подхода на рабочих командах для PostgreSQL и MySQL.
Содержание
Почему нельзя открывать порт БД наружу
['Порты СУБД сканируются ботами непрерывно. Открытый 3306 или 5432 — это перебор паролей, попытки эксплойтов и утечка данных. Базу держат закрытой, а доступ дают через защищённый канал.', 'Первым делом убедитесь, что СУБД слушает только localhost, если внешний доступ не нужен приложениям на других серверах:', "# PostgreSQL, postgresql.conf\nlisten_addresses = 'localhost'\n# MySQL, my.cnf\nbind-address = 127.0.0.1", 'И закройте порты фаерволом на всякий случай:', 'sudo ufw allow OpenSSH\nsudo ufw deny 5432\nsudo ufw deny 3306\nsudo ufw enable']
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK и США. Оплата картой РФ и по СБП.
Арендовать VPS для базы данныхSSH-туннель: самый простой способ
['SSH-туннель заворачивает трафик БД в уже зашифрованное SSH-соединение. Ничего дополнительно настраивать на сервере не нужно — только доступ по SSH.', 'Для PostgreSQL пробрасываем локальный порт 6432 на удалённый 5432:', 'ssh -N -L 6432:localhost:5432 user@SERVER_IP\n# в другом терминале подключаемся как к локальной БД:\npsql -h 127.0.0.1 -p 6432 -U dbuser dbname', 'Для MySQL всё аналогично:', 'ssh -N -L 3307:localhost:3306 user@SERVER_IP\nmysql -h 127.0.0.1 -P 3307 -u dbuser -p dbname', 'Флаг -N означает «не выполнять команду, только пробросить порт». Пока сессия открыта, работает и туннель. Локальный порт (6432, 3307) выбирайте любой свободный — важно лишь, чтобы приложение обращалось именно к нему на 127.0.0.1, а не к реальному порту БД на удалённой машине.', 'Такой подход хорош тем, что не требует ни единой правки на стороне сервера БД: раз есть SSH-доступ, есть и защищённый канал к базе. Весь трафик уже зашифрован алгоритмами SSH, а аутентификация по ключу надёжнее пароля СУБД. Графические клиенты (DBeaver, TablePlus, pgAdmin) умеют поднимать такой туннель встроенными средствами — достаточно указать SSH-хост, пользователя и ключ в настройках подключения.']
Постоянный туннель через autossh и systemd
['Для приложения, которое должно держать соединение постоянно, ручной ssh не годится. Используем autossh, который переподнимает туннель при обрыве, и оборачиваем его в systemd.', 'sudo apt install -y autossh\nsudo nano /etc/systemd/system/db-tunnel.service', '[Unit]\nDescription=SSH tunnel to database\nAfter=network.target\n\n[Service]\nUser=appuser\nExecStart=/usr/bin/autossh -M 0 -N -o ServerAliveInterval=30 \\\n -o ServerAliveCountMax=3 -L 6432:localhost:5432 user@SERVER_IP\nRestart=always\n\n[Install]\nWantedBy=multi-user.target', 'sudo systemctl daemon-reload\nsudo systemctl enable --now db-tunnel', 'Для беспарольной авторизации заранее настройте ключи SSH (ssh-copy-id), иначе сервис зависнет на запросе пароля.']
Вариант с TLS напрямую
['Если БД должна принимать внешние подключения (например, реплика или BI-инструмент), включите TLS и разрешите только шифрованные соединения. Для PostgreSQL:', "# postgresql.conf\nssl = on\nssl_cert_file = '/etc/postgresql/16/main/server.crt'\nssl_key_file = '/etc/postgresql/16/main/server.key'", 'В pg_hba.conf используйте hostssl вместо host, чтобы отклонять нешифрованные подключения:', 'hostssl dbname dbuser CLIENT_IP/32 scram-sha-256', 'Клиент подключается с требованием проверки сертификата:', 'psql "host=SERVER_IP dbname=dbname user=dbuser sslmode=verify-full sslrootcert=root.crt"', 'Режим verify-full здесь принципиален: он не только шифрует канал, но и сверяет сертификат сервера и его имя хоста, закрывая атаку «человек посередине». Даже при прямом TLS-доступе ограничьте круг разрешённых IP в pg_hba.conf или на фаерволе — шифрование защищает канал, но не отменяет необходимости фильтровать, кто вообще может стучаться в порт. Комбинация «список IP + hostssl + сильный пароль или клиентский сертификат» даёт практичный уровень безопасности для боевой базы.']
Проверка и частые ошибки
['Убедитесь, что снаружи порт БД действительно закрыт, — проверьте с другой машины:', 'nmap -p 5432,3306 SERVER_IP\n# порты должны быть filtered/closed', '- Открыли порт в интернет «на время» — боты найдут его за минуты.
- sslmode=require без verify-full — шифрование есть, но защиты от MITM нет.
- Туннель без autossh — оборвался, приложение потеряло БД.
- Пароль вместо ключа в systemd-туннеле — сервис виснет на старте.
Где держать защищённую БД
['Root-доступ у MAATRIX позволяет настроить фаервол, SSH-ключи и TLS так, как нужно именно вам. Быстрый NVMe на AMD EPYC не создаёт узкого места при шифровании соединений, а локации UK и США подходят для доступа из разных стран. Оплата картой РФ, СБП, криптой или токеном MAAT удобна, когда зарубежные провайдеры недоступны, а ежедневные бэкапы страхуют данные.']Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK и США. Оплата картой РФ и по СБП.
Арендовать VPS для базы данныхЧастые вопросы
SSH-туннель или TLS — что выбрать?
Для доступа администратора и разработчика проще SSH-туннель — не нужны сертификаты. Для постоянных подключений между сервисами удобнее прямой TLS с проверкой сертификата.
Чем sslmode=require хуже verify-full?
require только шифрует канал, но не проверяет подлинность сервера — возможна атака «человек посередине». verify-full сверяет сертификат и имя хоста, закрывая эту брешь.
Можно ли вообще не открывать порт БД?
Да, и это лучший вариант: слушайте только localhost, а весь внешний доступ давайте через SSH-туннель. Порт СУБД тогда недоступен из интернета в принципе.