Защита сетевого трафика кластера MySQL Galera с помощью шифрования SSL

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

Кластер Galera поддерживает шифрование соединения с использованием протокола SSL. В статье мы рассмотрим, как зашифровать все соединения кластера с помощью SSL-шифрования.

Все настройки будут выполняться в реализации MySQL MariaDB. Если у вас уже есть настроенный кластер Galera с использованием MariaDB, читайте дальше. Если же вы только планируете развернуть кластер Galera, перейдите к нашему руководству для популярных дистрибутивов Linux — CentOS 7, Debian 9, Ubuntu 16.04 и 18.04.

Проверим текущую конфигурацию SSL:

$ mysql -uroot -e "SHOW VARIABLES LIKE 'have_ssl';"
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| have_ssl      | DISABLED |
+---------------+----------+

Как можно видеть, режим SSL сейчас отключен. Чтобы полностью защитить все соединения кластера необходимо шифровать:

  • SSL-трафик репликации кластера Galera;
  • трафик переноса снимков состояния;
  • трафик между серверами базы данных и клиентом.

С помощью OpenSSL сгенерируем сертификаты и ключи SSL. Создадим каталоги для ключей:

sudo mkdir -p /etc/mysql/ssl
cd /etc/mysql/ssl

Ключ и сертификат CA

openssl genrsa 2048 | sudo tee ca-key.pem

Сгенерируем сертификат CA:

sudo openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca-cert.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:Tomskaya
Locality Name (eg, city) []:Tomsk
Organization Name (eg, company) [Internet Widgits Pty Ltd]:NetPoint
Organizational Unit Name (eg, section) []:NOC
Common Name (e.g. server FQDN or YOUR name) []:CA
Email Address []:support@netpoint-dc.com

Ключ и сертификат сервера

Внимание: Атрибут Common Name для ключа сервера должен отличаться от Common Name для ключа CA:

sudo openssl req -newkey rsa:2048 -days 3600 \
         -nodes -keyout server-key.pem -out server-req.pem
Generating a 2048 bit RSA private key
.....+++
................+++
writing new private key to 'server-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:Tomskaya
Locality Name (eg, city) []:Tomsk
Organization Name (eg, company) [Internet Widgits Pty Ltd]:NetPoint
Organizational Unit Name (eg, section) []:NOC
Common Name (e.g. server FQDN or YOUR name) []:Server
Email Address []:support@netpoint-dc.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Удалим из него парольную фразу:

sudo openssl rsa -in server-key.pem -out server-key.pem

Создадим сертификат сервера:

sudo openssl x509 -req -in server-req.pem -days 3600 \
         -CA ca-cert.pem -CAkey ca-key.pem \
         -set_serial 01 -out server-cert.pem

Ключ и сертификат клиента

Внимание: Атрибут Common Name для ключа клиента должен отличаться от Common Name для ключа сервера и ключа CA:

sudo openssl req -newkey rsa:2048 -days 3600 \
          -nodes -keyout client-key.pem -out client-req.pem
Generating a 2048 bit RSA private key
............................................................................................................................................................................................................+++
...............+++
writing new private key to 'client-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:Tomskaya
Locality Name (eg, city) []:Tomsk
Organization Name (eg, company) [Internet Widgits Pty Ltd]:NetPoint
Organizational Unit Name (eg, section) []:NOC
Common Name (e.g. server FQDN or YOUR name) []:Client
Email Address []:support@netpoint-dc.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Удалим пароль из ключа клиента:

sudo openssl rsa -in client-key.pem -out client-key.pem

Создадим SSL-сертификат клиента:

sudo openssl x509 -req -in client-req.pem -days 3600 \
          -CA ca-cert.pem -CAkey ca-key.pem \
          -set_serial 01 -out client-cert.pem

Выполним проверку корректности сертификатов:

openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem

server-cert.pem: OK
client-cert.pem: OK

Если проверка прошла успешно, необходимо скопировать сертификаты на оставшиеся узлы в кластере и установить корректные права доступа на каталоги:

sudo chown -R mysql:mysql /etc/mysql/ssl

Настройка защиты трафика базы данных и клиентских соединений

Добавим следующие строки в конфигурационный файл my.cnf или другой .cnf в каталоге /etc/mysql/conf.d, если вы предпочитаете модульную конфигурацию.

# Сервер MySQL 
[mysqld]
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
# Клиент MySQL
[client]
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/client-cert.pem
ssl-key=/etc/mysql/ssl/client-key.pem
 

Защита трафика репликации

Определите пути к ключу, сертификату и файлам центра сертификации. Кластер Galera будет использовать эти файлы для шифрования и дешифрования трафика репликации.

wsrep_provider_options="socket.ssl_key=/etc/mysql/ssl/server-key.pem;socket.ssl_cert=/etc/mysql/ssl/server-cert.pem;socket.ssl_ca=/etc/mysql/ssl/ca-cert.pem"

Активация SSL для переноса состояния (SST) с помощью MySQLDump

Создайте пользователя, который требует SSL для подключения.

MariaDB [(none)]> CREATE USER 'sstssl'@'localhost' IDENTIFIED BY 'secret';
Query OK, 0 rows affected (0.03 sec)

MariaDB [(none)]> GRANT PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'sstssl'@'localhost' REQUIRE ssl;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Мы будем использовать этого пользователя для репликации. Измените wsrep_sst_auth в файле конфигурации my.cnf.

wsrep_sst_auth="sstssl:secret"

Теперь необходимо остановить и заново запустить весь кластер. Если перезапустить только один узел во время работы других, он не сможет присоединиться к существующему кластеру. Вы увидите ошибки, подобные приведенным ниже, в журнале ошибок MySQL.

171017  3:20:29 [ERROR] WSREP: handshake with remote endpoint ssl://192.168.56.22:4567 failed: asio.ssl:336031996: 'unknown protocol' ( 336031996: 'error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol')
171017  3:20:29 [ERROR] WSREP: handshake with remote endpoint ssl://192.168.56.23:4567 failed: asio.ssl:336031996: 'unknown protocol' ( 336031996: 'error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol')

Активация SSL для переноса состояния (SST) с помощью Rsync

Используйте специальный обработчик secure_rsync. Сам обработчик и инструкцию по его применению можно найти в GitHub-репозитории проекта.

По сути, в настройках изменится только метод осуществления SST:

wsrep_sst_method=secure_rsync

Активация SSL для переноса состояния (SST) с помощью Percona Xtrabackup

Если вы используете Xtrabackup, то данная утилита уже имеет настройки для SSL. В конфигурационный файл my.cnf добавьте:

[sst]
encrypt=4
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem

Проверка кластера

Выключим кластер и запустим его снова. Проверим применились ли внесенные изменения, проверим, что кластер функционирует корректно:

mysql -uroot -e "SHOW VARIABLES LIKE 'have_ssl';";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_ssl      | YES   |
+---------------+-------+

mysql -uroot -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster%';";
+--------------------------+--------------------------------------+
| Variable_name            | Value                                |
+--------------------------+--------------------------------------+
| wsrep_cluster_conf_id    | 3                                    |
| wsrep_cluster_size       | 3                                    |
| wsrep_cluster_state_uuid | 15a6ec3c-648e-11e9-ae72-0715b07d89d9 |
| wsrep_cluster_status     | Primary                              |
| wsrep_cluster_weight     | 3                                    |
+--------------------------+--------------------------------------+

Клиентские подключения

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

[client]
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/client-cert.pem
ssl-key=/etc/mysql/ssl/client-key.pem

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