Шифрование трафика Redis с помощью stunnel в Ubuntu 16.04

Redis – открытое in-memory хранилище типа «ключ-значение». Redis поддерживает транзакции, шаблон проектирования pub-sub, автоматический обход сбоев и многое другое. Для Redis разработано множество клиентов в различных языках программирования.

Примечание: Список рекомендованных клиентов можно найти здесь.

Однако Redis не имеет никаких функций шифрования данных. Хранилище нужно развёртывать в изолированной частной сети, доступ к которой есть только у заведомо безопасных клиентов, либо же настроить шифрование трафика самостоятельно.

Данное руководство поможет настроить шифрование трафика Redis с помощью программы stunnel. Трафик между клиентами и серверами Redis будет направляться через специальный шифрованный SSL-туннель.

Требования

В руководстве настройка продемонстрирована на примере двух серверов Ubuntu 16.04. На серверах должны быть:

  • Пользователь с доступом к sudo.
  • Базовый брандмауэр.

Все необходимые инструкции можно найти в руководстве по начальной настройке.

Что такое stunnel?

Утилита stunnel обеспечивает шифрованный обмен данными между двумя машинами. Клиент подключается к локальному порту, и stunnel шифрует данные перед передачей на удаленный сервер. На стороне сервера stunnel прослушивает заданный порт и расшифровывает трафик перед отправкой его на локальный порт, который прослушивает сервер Redis.

Преимущества stunnel:

  • Пакеты stunnel можно найти в стандартном репозитории Ubuntu.
  • Утилита проста в установке и настройке.
  • Ubuntu предоставляет сценарий инициализации для автозапуска сервиса.
  • Для каждой цели используется отдельный туннель. В некоторых ситуациях это может стать недостатком, но благодаря этому вы получаете полный контроль над доступом.

Недостатки stunnel:

  • Клиенты подключаются к удаленной машине с помощью нестандартного локального порта.
  • Объединяя два сервера Redis для репликации или кластеризации, вы должны настроить два туннеля на каждой машине (один для исходящего и один для входящего трафика).

Установка сервера и клиента Redis

На один сервер Ubuntu 16.04 нужно установить пакеты сервера Redis, на второй – пакеты клиента Redis. Если вы сделали это заранее, пропустите раздел.

Примечание: Сервер Redis устанавливает тестовый ключ, который в дальнейшем будет использоваться для проверки соединения. Если вы уже установили сервер Redis, вы можете продолжить и установить такой ключ (вы можете выбрать любое ключевое слово).

Установка сервера Redis

Чтобы установить последнюю доступную версию Redis, используйте этот PPA.

Примечание: Всегда проверяйте пакеты, загруженные из сторонних репозиториев.

Добавьте PPA и установите Redis.

sudo apt-add-repository ppa:chris-lea/redis-server
sudo apt-get update
sudo apt-get install redis-server

Чтобы ответить на запросы инсталлятора, нажмите Enter.

После завершения установки убедитесь, что вы можете подключиться к сервису Redis локально:

redis-cli ping

Если программа успешно установлена и запущена, на экране появится:

PONG

Теперь добавьте ключ для дальнейшего использования:

redis-cli set test 'success'

Это присвоит ключу test значение success. Это ключевое слово нужно использовать в дальнейшем для проверки соединения с stunnel.

Установка клиента Redis

Второй сервер Ubuntu 16.04 будет использоваться в качестве клиента. Все необходимые пакеты можно загрузить из стандартного реопзитория:

sudo apt-get update
sudo apt-get install redis-tools

Установка stunnel

Примечание: Данный раздел нужно выполнить на каждом сервере и клиенте Redis.

В репозиториях Ubuntu можно найти пакет stunnel4. Установите этот пакет. Если вы пропустили предыдущий раздел, не забудьте обновить индекс пакетов перед установкой:

sudo apt-get update
sudo apt-get install stunnel4

Сервис stunnel в Ubuntu использует для запуска старый сценарий SysVinit. Система system может управлять этим сценарием. Чтобы использовать его вместо встроенных функций system, отредактируйте файл /etc/default/stunnel4:

sudo nano /etc/default/stunnel4

Чтобы сервис запускался вместе с сервером, найдите ENABLED и задайте значение 1:

. . .
ENABLED=1
. . .

Сохраните и закройте файл.

Теперь нужно создать самоподписанный SSL-сертификат и ключ для шифрования трафика.

Создание самоподписанного SSL-сертификата на сервере Redis

Сертификат нужно создать на сервере Redis в каталоге /etc/stunnel. С его помощью stunnel сможет зашифровать обмен данными между сервером и клиентом. Файлы сертификата и ключа называются redis-server (при желании вы можете выбрать другое имя).

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/stunnel/redis-server.key -out /etc/stunnel/redis-server.crt

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

. . .
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company
Organizational Unit Name (eg, section) []:Community
Common Name (e.g. server FQDN or YOUR name) []:redis-server
Email Address []:admin@example.com
Ограничьте доступ к ключу:
sudo chmod 600 /etc/stunnel/redis-server.key

Создание конфигурационного файла stunnel на сервере Redis

На сервере Redis в каталоге /etc/stunnel откройте файл с расширением .conf.

sudo nano /etc/stunnel/redis.conf

Укажите в нём PID-файл. Для хранения таких файлов предназначен каталог /run.

pid = /run/stunnel-redis.pid

Теперь нужно настроить доступ к сервису Redis. Для этого создайте новый раздел (в данном руководстве он называется redis-server). Этот раздел сможет отделить параметры туннелей сервера Redis от других туннелей, которые вы добавите в файл.

Укажите путь к сертификату и ключу, для этого используйте cert и key.

Также здесь можно определить туннель для входящих данных. Для этого предназначена директива accept. Укажите порт Redis (6379) и внешний IP-адрес сервера Redis. Трафик должен передаваться на стандартный порт Redis и локальный интерфейс (эти данные укажите в директиве connect).

pid = /run/stunnel-redis.pid
[redis-server] cert = /etc/stunnel/redis-server.crt
key = /etc/stunnel/redis-server.key
accept = redis_servers_public_IP:6379
connect = 127.0.0.1:6379

Сохраните и закройте файл.

Перезапуск stunnel и настройка брандмауэра

Примечание: Данный раздел нужно выполнить на сервере Redis.

Перезапустите сервис stunnel:

sudo systemctl restart stunnel4.service

Проверьте сервисы, которые прослушивают соединения на сервере Redis; вы должны увидеть сервис stunnel, использующий порт 6379 на открытом интерфейсе. На локальном интерфейсе Redis слушает тот же порт.

sudo netstat -plunt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 public_IP:6379          0.0.0.0:*               LISTEN      4292/stunnel4
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      2679/redis-server 1
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1720/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      1720/sshd

Сервис stunnel прослушивает открытый интерфейс, однако брандмауэр, скорее всего, блокирует этот трафик.

Чтобы разблокировать порт 6379, введите:

sudo ufw allow 6379

Перемещение сертификата на клиент

Каждый клиент Redis должен иметь копию сертификата сервера Redis. Проще всего передать файл .crt следующим образом: отобразить содержимое файла, а затем скопировать его и поместить в соответствующий файл на клиенте.

Запросите содержимое сертификата на сервере Redis:

cat /etc/stunnel/redis-server.crt
-----BEGIN CERTIFICATE-----
MIIEGTCCAwGgAwIBAgIJALUdz8P8q8UPMA0GCSqGSIb3DQEBCwUAMIGiMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxFjAUBgNVBAcMDU5ldyBZb3JrIENp
. . .
Tq7WJk77tk4nPI8iGv1WuK8xTAm5aOncxP16VoMpsDMV+GB1p3nBkMQ/GKF8pPXU
fn6BnDWKmeZqAlBM+MGYAfkbZWdBslrWasCJzs+tehTqL0LLJ6d3Gi9biBPb
-----END CERTIFICATE-----

Примечание: Строки BEGIN CERTIFICATE и END CERTIFICATE также нужно скопировать.

Перейдите на клиентскую машину и откройте одноименный файл в каталоге  /etc/stunnel.

sudo nano /etc/stunnel/redis-server.crt

Вставьте в него скопированный сертификат сервера. Сохраните и закройте файл.

Создание конфигурационного файла stunnel на клиенте Redis

Теперь нужно настроить сервис stunnel на клиентской стороне.

Перейдите на клиент. Откройте файл с расширением .conf в каталоге /etc/stunnel:

sudo nano /etc/stunnel/redis.conf

В нём укажите PID-файл.

pid = /run/stunnel-redis.pid

Теперь добавьте раздел для обработки исходящего трафика (в руководстве такой раздел называется redis-client).

С помощью директивы client нужно указать, что эти настройки относятся к клиентской машине. Директива accept должна прослушивать любой свободный порт локального интерфейса (например, 8000). В директиве connect укажите внешний IP сервера Redis и открытый порт.

С помощью CAfile укажите копию сертификата сервера Redis. В директиве verify укажите значение 4 (в этом режиме stunnel проверяет самоподписанные сертификаты).

pid = /run/stunnel-redis.pid
[redis-client] client = yes
accept = 127.0.0.1:8000
connect = remote_server_IP_address:6379
CAfile = /etc/stunnel/redis-server.crt
verify = 4

Сохраните и закройте файл.

Перезапуск клиента и тестирование соединения

Перезапустите stunnel на клиенте, чтобы обновить настройки.

sudo systemctl restart stunnel4.service

Убедитесь, что туннель установлен правильно:

sudo netstat -plunt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      3809/stunnel4
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1714/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      1714/sshd

Сервис stunnel прослушивает порт 8000.

Теперь вы можете подключиться к удалённому серверу Redis:

redis-cli -p 8000 ping
PONG

Запросите ключевое слово, установленное в начале:

redis-cli -p 8000 get test
"success"

Это значит, что у клиента есть доступ к удалённой базе данных.

Теперь нужно убедиться, что вы не можете подключиться к серверу без туннеля. Подключитесь напрямую к порту удалённого сервера:

redis-cli -h redis_server_public_IP -p 6379 ping
Error: Connection reset by peer

Как видите, трафик поступает только по туннелю.

Расширение настроек

Выше мы рассмотрели пример простой настройки шифрования для одного клиента и одного сервера Redis. Эту настройку вы можете применить и для большой инфраструктуры.

Чтобы настроить несколько клиентов, нужно просто повторить все вышеописанные действия:

  • Установить ПО клиента и утилиту stunnel.
  • Включить автозапуск сервиса stunnel.
  • Скопировать сертификат сервера Redis в /etc/stunnel.
  • Перезапустить stunnel.

Чтобы использовать эту настройку для репликации или кластеризации, нужно создать два параллельных туннеля:

  • Установите ПО сервера Redis и утилиту stunnel.
  • Включите автозапуск сервиса stunnel.
  • Сгенерируйте новый сертификат и ключ шифрования (имя файла должно быть уникальным).
  • Скопируйте сертификат с одного сервера на другой в каталог /etc/stunnel.
  • Отредактируйте или создайте конфигурационный файл stunnel. Такой файл должен содержать раздел настроек сервера (связывать внешний порт с локальным портом Redis) и настройки клиента (связывать локальный порт с удалённым портом).
  • Откройте внешний порт в брандмауэре сервера Redis.
  • Настройте каждый экземпляр Redis для подключения к локальному порту. Это позволит получить доступ к удаленному серверу с помощью файла конфигурации Redis (набор директив зависит от отношений между серверами; см. документацию Redis для получения более подробной информации).

Конфигурационные файлы будут выглядеть примерно так:

pid = /run/stunnel-redis.pid
[redis-server] cert = /etc/stunnel/this_servers_certificate.crt
key = /etc/stunnel/this_servers_key.key
accept = this_servers_public_IP:6379
connect = 127.0.0.1:6379
[redis-client] client = yes
accept = 127.0.0.1:arbitrary_local_port
connect = remote_servers_public_IP:6379
CAfile = /etc/stunnel/remote_servers_certificate.crt
verify = 4

При необходимости можно создать несколько разделов client на каждой машине для соединения локального и удалённого порта. В таком случае не забудьте выбрать другой свободный локальный порт и указать его в директиве accept.

Заключение

Redis – производительный и гибкий инструмент для хранения данных. Однако обмен данными Redis не защищен, что позволяет злоумышленникам похитить информацию. Поэтому очень важно зашифровать трафик между удалёнными серверами Redis.

Читайте также:

Шифрование трафика Redis с помощью spiped в Ubuntu 16.04

Шифрование трафика Redis с помощью PeerVPN в Ubuntu 16.04

Tags: , , ,

Добавить комментарий