Настройка SSL/TLS для безопасных подключений к PostgreSQL: Полное руководство

Узнайте, как защитить подключения к PostgreSQL с помощью шифрования SSL/TLS. Это подробное руководство охватывает настройку на стороне сервера и клиента, включая генерацию сертификатов, изменение файлов `postgresql.conf` и `pg_hba.conf`, а также настройку клиентов для безопасного зашифрованного обмена данными. Защитите конфиденциальные данные при передаче и обеспечьте соответствие современным стандартам безопасности.

Настройка SSL/TLS для безопасных подключений к PostgreSQL: Полное руководство

Настройка SSL/TLS в PostgreSQL включает две отдельные задачи. Первая — шифрование, чтобы никто в сети не мог прочитать учетные данные или результаты запросов во время передачи. Вторая — идентификация, чтобы клиент был уверен, что общается с реальным сервером базы данных, а не с машиной, выдающей себя за него. Во многих настройках выполняют первую часть и случайно пропускают вторую.

Это различие имеет значение в реальных развертываниях. sslmode=require шифрует соединение, но сам по себе не полностью проверяет имя хоста сервера. sslmode=verify-full делает это. Если ваше приложение подключается через общедоступную сеть, общую корпоративную сеть, наложение Kubernetes, которое вы не полностью контролируете, или любую среду, где трафик может быть перехвачен, verify-full должен быть целью.

Понимание SSL/TLS в PostgreSQL

SSL/TLS (Secure Sockets Layer/Transport Layer Security) — это криптографический протокол, предназначенный для обеспечения безопасности связи через компьютерную сеть. При применении к PostgreSQL он шифрует данные, которыми обмениваются сервер базы данных и его клиенты. Это предотвращает перехват и чтение конфиденциальной информации, такой как учетные данные, финансовые данные или личные данные, неавторизованными сторонами.

Клиенты PostgreSQL поддерживают несколько режимов SSL:

  • sslmode=disable: Использовать только обычное незашифрованное соединение.
  • sslmode=prefer: Сначала попробовать TLS, затем вернуться к обычному TCP, если TLS недоступен. Это удобно, но может скрыть неправильную настройку.
  • sslmode=require: Требовать шифрование TLS, но не обязательно проверять имя хоста сервера.
  • sslmode=verify-ca: Требовать TLS и проверять, что сертификат привязан к доверенному ЦС.
  • sslmode=verify-full: Требовать TLS, проверять ЦС и проверять, что имя хоста соответствует сертификату.

На стороне сервера ssl = on означает только то, что PostgreSQL способен принимать TLS-соединения. Это не заставляет каждого клиента использовать TLS. Принуждение происходит в pg_hba.conf с помощью правил hostssl и избегания более широких правил host, которые позволяют тем же пользователям и сетям подключаться без TLS.

Предварительные требования для настройки SSL/TLS

Прежде чем приступить к настройке SSL/TLS для PostgreSQL, убедитесь, что у вас есть следующее:

  1. Установленный OpenSSL: Набор инструментов OpenSSL необходим для генерации и управления SSL-сертификатами. Обычно он предустановлен в системах Linux и macOS. Для Windows может потребоваться загрузить и установить его отдельно.
  2. Доступ к файлам конфигурации PostgreSQL: Вам понадобятся права администратора для изменения файлов postgresql.conf и pg_hba.conf.
  3. Понимание центров сертификации (ЦС): Хотя вы можете создать самоподписанные сертификаты для тестирования, в производственных средах желательно использовать сертификаты, подписанные доверенным центром сертификации (ЦС) или внутренним корпоративным ЦС.

Настройка SSL/TLS на стороне сервера

Настройка на стороне сервера включает включение SSL, указание местоположения SSL-сертификатов и ключей, а также настройку аутентификации клиентов.

1. Генерация или получение SSL-сертификатов и ключей

Есть два основных способа получить SSL-сертификаты для вашего сервера PostgreSQL:

  • Самоподписанные сертификаты (для тестирования/разработки): Они создаются с помощью OpenSSL и не доверяются по умолчанию внешними клиентами. Они полезны для начальной настройки и внутреннего тестирования.
  • Сертификаты от центра сертификации (ЦС) (для производства): Получите сертификаты от доверенного публичного ЦС (например, Let's Encrypt, DigiCert) или внутреннего корпоративного ЦС. Это гарантирует, что клиенты могут проверить личность сервера.

Создание самоподписанных сертификатов с помощью OpenSSL:

Это распространенный подход для сред разработки и внутреннего использования. Выполните следующие команды на вашем сервере PostgreSQL или на машине с OpenSSL:

  1. Создайте каталог для сертификатов: Рекомендуется хранить сертификаты организованно.

    sudo mkdir -p /etc/postgresql/ssl
    sudo chown postgres:postgres /etc/postgresql/ssl
    cd /etc/postgresql/ssl
    
  2. Сгенерируйте закрытый ключ сервера: Этот ключ должен храниться в секрете.

    sudo openssl genrsa -out server.key 2048
    
  3. Создайте запрос на подпись сертификата (CSR) сервера: Он содержит информацию о вашем сервере.

    sudo openssl req -new -key server.key -out server.csr
    

    Используйте имя хоста, к которому будут подключаться клиенты, например db01.internal.example.com. Современные клиенты обычно проверяют альтернативное имя субъекта (SAN), поэтому включайте DNS-имена в запрос сертификата, если ваш процесс ЦС это поддерживает.

  4. Подпишите сертификат вашим собственным ЦС (для внутреннего использования):

    • Создайте закрытый ключ и сертификат корневого ЦС (если у вас его нет):
      # Сгенерировать закрытый ключ ЦС
      sudo openssl genrsa -des3 -out root.key 2048
      # Создать сертификат ЦС (действителен на 3650 дней)
      sudo openssl req -new -x509 -days 3650 -key root.key -out root.crt
      
    • Подпишите CSR сервера с помощью ЦС: Это создает доверенный сертификат сервера.
      sudo openssl x509 -req -days 365 -in server.csr -CA root.crt -CAkey root.key -set_serial 01 -out server.crt
      
  5. Установите права доступа: Убедитесь, что пользователь PostgreSQL может читать эти файлы.

    sudo chown postgres:postgres server.key server.crt root.crt
    sudo chmod 600 server.key
    sudo chmod 644 server.crt root.crt
    

Использование сертификатов от публичного/корпоративного ЦС:

Если вы получаете сертификаты от ЦС, вы обычно получите:

  • server.crt: Публичный сертификат вашего сервера.
  • server.key: Закрытый ключ вашего сервера.
  • root.crt (или аналогичный): Корневой сертификат ЦС (и, возможно, промежуточные сертификаты).

Поместите эти файлы в защищенный каталог (например, /etc/postgresql/ssl/) и убедитесь, что пользователь PostgreSQL имеет права на чтение.

2. Настройка postgresql.conf

Отредактируйте файл postgresql.conf (обычно находится в каталоге данных PostgreSQL), чтобы включить SSL и указать файлы сертификатов.

#------------------------------------------------------------------------------
# SSL
#------------------------------------------------------------------------------

ssl = on

# Все файлы в формате PEM и игнорируются, если ключ/сертификат сервера не настроены.
# По умолчанию файлы ожидаются в каталоге данных сервера.
# Альтернативно, они могут быть указаны как полные пути.
ssl_cert_file = '/etc/postgresql/ssl/server.crt'     # (измените имя файла при необходимости)
ssl_key_file = '/etc/postgresql/ssl/server.key'      # (измените имя файла при необходимости)
ssl_ca_file = '/etc/postgresql/ssl/root.crt'         # (необязательно, для проверки сертификата клиента)

# Необязательно: укажите список шифров, если необходимо
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'

# Необязательно: включите проверку сертификата клиента
#ssl_ca_file должен быть установлен в файл, содержащий сертификат(ы) ЦС, которым доверять
#ssl_crl_file = ''
#ssl_crl_dir = ''
  • ssl = on: Включает поддержку SSL на сервере.
  • ssl_cert_file: Путь к публичному сертификату сервера.
  • ssl_key_file: Путь к закрытому ключу сервера.
  • ssl_ca_file: Путь к сертификатам ЦС, которым PostgreSQL должен доверять при проверке сертификатов клиентов. Клиенты используют свой собственный файл ЦС, например sslrootcert, для проверки сервера.

3. Настройка pg_hba.conf для принудительного использования SSL

Файл pg_hba.conf управляет аутентификацией клиентов. Вам нужно изменить записи, чтобы обеспечить принудительное использование SSL-соединений.

По умолчанию записи в pg_hba.conf выглядят так:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256

Чтобы принудительно использовать SSL, измените записи host на hostssl:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     peer
# IPv4 local connections:
hostssl all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
hostssl all             all             ::1/128                 scram-sha-256

# Пример для доступа к внешней сети - требуется SSL
hostssl all             app_user        10.20.0.0/16            scram-sha-256
hostssl all             app_user        2001:db8:20::/48        scram-sha-256
  • hostssl: Этот тип записи требует SSL-соединений. Любая попытка соединения без SSL будет отклонена.
  • hostnossl: Этот тип записи явно запрещает SSL-соединения.
  • host: Разрешает как SSL, так и не-SSL соединения. Если соответствующее правило host существует до или вместо вашего правила hostssl, клиенты все равно могут подключаться без TLS.

Избегайте публикации доступа 0.0.0.0/0, если нет веской причины и других средств контроля. Большинство производственных баз данных должны принимать соединения только из подсетей приложений, хост-машин, пулеров соединений или частных сетевых диапазонов.

4. Перезапуск сервера PostgreSQL

После изменения postgresql.conf и pg_hba.conf необходимо перезапустить службу PostgreSQL, чтобы изменения вступили в силу.

# Для систем, использующих systemd (большинство современных дистрибутивов Linux)
sudo systemctl restart postgresql

# Для систем, использующих init.d
sudo service postgresql restart

Настройка SSL/TLS на стороне клиента

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

1. Параметры строки подключения

При подключении через psql или любую клиентскую библиотеку PostgreSQL вы можете указать параметры SSL в строке подключения или как отдельные параметры.

Базовое SSL-соединение (только аутентификация сервера):

psql "sslmode=require host=your_server_hostname dbname=your_db user=your_user"
  • sslmode: Управляет поведением SSL клиента.
    • disable: Разрешать только не-SSL соединения.
    • allow: Разрешать не-SSL, но предпочитать SSL, если сервер его поддерживает.
    • prefer (по умолчанию): Предпочитать SSL, но разрешать не-SSL, если SSL не удается.
    • require: Разрешать только SSL-соединения. Если сервер не поддерживает SSL, соединение не удается.
    • verify-ca: Разрешать только SSL-соединения и проверять, что сертификат сервера подписан доверенным ЦС. Должен быть установлен параметр sslrootcert.
    • verify-full: Разрешать только SSL-соединения, проверять сертификат сервера относительно доверенного ЦС и проверять, что имя хоста сервера соответствует общему имени (CN) или альтернативному имени субъекта (SAN) сертификата.

Проверка сертификата сервера (verify-ca или verify-full):

Для повышения безопасности клиенты должны проверять личность сервера. Это требует, чтобы клиент доверял ЦС, подписавшему сертификат сервера.

  1. Получите сертификат ЦС: Получите файл root.crt (или соответствующий сертификат ЦС), который использовался для подписи сертификата сервера.
  2. Укажите sslrootcert: Сообщите клиенту, где найти этот сертификат ЦС.
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user sslrootcert=/path/to/your/root.crt"

Это строка подключения, которую вы должны протестировать с того же хоста или контейнера, где работает приложение. Частая ошибка: psql работает с ноутбука администратора, потому что файл ЦС существует там, а контейнер приложения терпит неудачу, потому что пакет ЦС никогда не был смонтирован.

2. Клиентские сертификаты (взаимная аутентификация)

Для еще более высокого уровня безопасности вы можете реализовать взаимную аутентификацию, когда сервер также проверяет личность клиента с помощью клиентских сертификатов.

Генерация клиентских сертификатов:

Как и для серверных сертификатов, вам понадобятся закрытый ключ клиента и клиентский сертификат, подписанный ЦС, которому доверяет сервер (часто тот же ЦС, что и для серверного сертификата).

  1. Сгенерируйте закрытый ключ клиента:

    openssl genrsa -des3 -out client.key 2048
    
  2. Создайте CSR клиента:

    openssl req -new -key client.key -out client.csr
    

    Укажите детали, убедившись, что общее имя уникально для клиента.

  3. Подпишите CSR клиента с помощью ЦС:

    sudo openssl x509 -req -days 365 -in client.csr -CA root.crt -CAkey root.key -set_serial <уникальный_серийный_номер> -out client.crt
    
  4. Установите права доступа:

    chmod 600 client.key
    chmod 644 client.crt
    

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

На сервере вам нужно настроить pg_hba.conf для принятия аутентификации по клиентскому сертификату. Часто для этого используется метод аутентификации cert.

# TYPE  DATABASE        USER            ADDRESS                 METHOD
# Требовать SSL и аутентификацию по клиентскому сертификату для конкретного пользователя/БД
hostssl all             your_user       your_client_ip/32       cert map=your_cert_map

Вам также может потребоваться определить файл карты сертификатов (опция cert_map), если вы хотите сопоставить определенные данные клиентского сертификата (например, Subject или SubjectAltName) с пользователями PostgreSQL. Обратитесь к документации PostgreSQL для получения подробной информации о настройке аутентификации cert и карты сертификатов.

Настройка клиента для использования сертификатов:

Обновите строку подключения клиента, включив пути к его сертификату и ключу:

psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user \
sslrootcert=/path/to/your/root.crt sslcert=/path/to/your/client.crt sslkey=/path/to/your/client.key"

Лучшие практики и советы

  • Используйте sslmode=verify-full: Стремитесь использовать verify-full на стороне клиента, чтобы снизить риск атаки "человек посередине".
  • Защищайте закрытые ключи: Убедитесь, что закрытые ключи (файлы .key) имеют строгие права доступа к файлам (например, chmod 600) и доступны для чтения только пользователю PostgreSQL на сервере и подключающемуся пользователю на клиенте.
  • Регулярно обновляйте сертификаты: Сертификаты имеют срок действия. Внедрите процесс их обновления до истечения срока действия, чтобы избежать сбоев подключения.
  • Централизованное управление сертификатами: Для более крупных развертываний рассмотрите возможность использования системы управления сертификатами или автоматизации выпуска и обновления сертификатов.
  • Мониторинг журналов: Проверяйте журналы PostgreSQL на наличие любых ошибок, связанных с SSL, во время запуска или попыток подключения.
  • Документация: Обратитесь к официальной документации PostgreSQL для получения самых актуальных параметров и расширенных параметров конфигурации, специфичных для вашей версии PostgreSQL.

Краткий контрольный список проверки

После перезапуска PostgreSQL проверьте, что сервер прослушивает с включенным TLS:

SHOW ssl;
SHOW ssl_cert_file;
SHOW ssl_key_file;

Затем протестируйте с клиентского хоста:

psql "host=your_server_hostname dbname=your_db user=your_user sslmode=verify-full sslrootcert=/path/to/root.crt"

Внутри сеанса подтвердите, что соединение зашифровано:

SELECT ssl, version, cipher
FROM pg_stat_ssl
WHERE pid = pg_backend_pid();

Если ssl имеет значение false, ваши правила pg_hba.conf не обеспечивают принуждение, как вы думаете. Если verify-full не работает, а require работает, вероятно, в сертификате отсутствует правильное имя хоста, клиент не доверяет ЦС или приложение подключается по IP-адресу, в то время как сертификат выдан для DNS-имени.

Хорошая настройка TLS в PostgreSQL — это не просто ssl = on. Это цепочка: сертификат с правильными именами, закрытые ключи со строгими правами доступа, правила hostssl, которые действительно обеспечивают принудительное использование TLS, и клиенты, которые проверяют сервер, а не просто шифруют сокет.