Настройка SSL-шифрования подключений к базе данных
SSL/TLS шифрование соединений с БД защищает данные при передаче между приложением и сервером базы данных. Обязательно для compliance (PCI DSS, GDPR, SOC 2) и необходимо, когда приложение и БД находятся в разных сетях.
PostgreSQL SSL
Генерация самоподписанного сертификата
# Для production используйте Let's Encrypt или внутренний CA
openssl req -new -x509 -days 365 -nodes \
-out /etc/ssl/certs/postgresql.crt \
-keyout /etc/ssl/private/postgresql.key \
-subj "/CN=db.company.internal"
# Права
chmod 600 /etc/ssl/private/postgresql.key
chown postgres:postgres /etc/ssl/certs/postgresql.crt /etc/ssl/private/postgresql.key
Конфигурация сервера
# postgresql.conf
ssl = on
ssl_cert_file = '/etc/ssl/certs/postgresql.crt'
ssl_key_file = '/etc/ssl/private/postgresql.key'
ssl_ca_file = '/etc/ssl/certs/ca.crt' # для mutual TLS
ssl_min_protocol_version = 'TLSv1.2'
ssl_ciphers = 'HIGH:!aNULL:!MD5'
Принудительное SSL в pg_hba.conf:
# Только SSL подключения с определённой подсети
hostssl all all 10.0.0.0/8 scram-sha-256
# Запрет non-SSL
host all all 10.0.0.0/8 reject
Проверка:
SELECT ssl, client_addr, version, cipher FROM pg_stat_ssl
JOIN pg_stat_activity USING (pid)
WHERE datname = current_database();
Строки подключения с SSL
# psql
psql "host=db.company.internal sslmode=require sslcert=/etc/ssl/app.crt sslkey=/etc/ssl/app.key"
# DSN в приложении
DATABASE_URL=postgresql://user:[email protected]:5432/myapp?sslmode=require
Параметры sslmode:
-
disable— без SSL -
require— SSL обязателен, сертификат не проверяется -
verify-ca— SSL + проверка CA -
verify-full— SSL + проверка CA + hostname
MySQL SSL
# /etc/mysql/mysql.conf.d/mysqld.cnf
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
require_secure_transport=ON # принудительный SSL для всех
-- Требовать SSL для конкретного пользователя
ALTER USER 'app_user'@'%' REQUIRE SSL;
-- Или с конкретным сертификатом
ALTER USER 'app_user'@'%' REQUIRE X509;
Строка подключения:
mysql://user:pass@host/db?ssl-ca=/path/ca.pem&ssl-cert=/path/cert.pem&ssl-key=/path/key.pem
Клиентские библиотеки
Node.js (pg)
const { Pool } = require('pg')
const pool = new Pool({
host: 'db.company.internal',
ssl: {
rejectUnauthorized: true,
ca: fs.readFileSync('/etc/ssl/certs/ca.crt'),
cert: fs.readFileSync('/etc/ssl/certs/client.crt'),
key: fs.readFileSync('/etc/ssl/private/client.key'),
}
})
Python (psycopg2)
import psycopg2
conn = psycopg2.connect(
host='db.company.internal',
sslmode='verify-full',
sslcert='/etc/ssl/app.crt',
sslkey='/etc/ssl/app.key',
sslrootcert='/etc/ssl/ca.crt'
)
Ротация сертификатов без даунтайма
# 1. Добавить новый CA к старому (оба активны)
cat old-ca.crt new-ca.crt > combined-ca.crt
# 2. Обновить ssl_ca_file в postgresql.conf, перечитать конфиг
pg_ctl reload
# 3. Выпустить новые клиентские сертификаты
# 4. Обновить клиентов
# 5. Убрать старый CA из combined-ca.crt
Мониторинг срока действия сертификатов
# Проверить дату истечения
openssl x509 -in /etc/ssl/certs/postgresql.crt -noout -dates
# Автоматическая проверка (в cron)
EXPIRY=$(openssl x509 -in /etc/ssl/certs/postgresql.crt -noout -checkend 2592000)
if echo "$EXPIRY" | grep -q "will expire"; then
curl -X POST "$SLACK_WEBHOOK" -d '{"text": "DB SSL cert expires in < 30 days"}'
fi
Срок выполнения
Настройка SSL для PostgreSQL или MySQL с проверкой сертификата — 0,5–1 рабочий день.







