MAATRIX / Блог / Удалённый доступ к базе данных: SSH-туннель и TLS

Удалённый доступ к базе данных: SSH-туннель и TLS

Блог MAATRIX · 2026-07-07

Открыть порт 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-туннель. Порт СУБД тогда недоступен из интернета в принципе.