ИТ Блог. Администрирование серверов на основе Linux (Ubuntu, Debian, CentOS, openSUSE)

Как зашифровать ваши резервные копии MySQL и MariaDB

Мы обычно заботимся о том, что мы ценим, будь то дорогостоящий смартфон или серверы компании. Данные являются одним из важнейших активов организации, и, хотя мы этого не видим, его необходимо тщательно защищать. Мы используем шифрование данных для шифрования файлов базы данных или целых томов, содержащих наши данные. Внедряем данные в транзитном шифровании с использованием SSL, чтобы никто не мог разнюхать и собирать данные, отправленные по сетям. Резервные копии ничем не отличаются. Независимо от того, будет ли это полная резервная копия или инкрементная, она сохранит хотя бы часть ваших данных. Таким образом, резервные копии также должны быть зашифрованы. В этом посте мы рассмотрим некоторые параметры, которые могут возникнуть при шифровании резервных копий. Во-первых, давайте посмотрим, как вы можете зашифровать свои резервные копии и какие могут быть варианты использования этих методов.

 

Как зашифровать вашу резервную копию?

Шифрование локального файла

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

openssl enc -aes-256-cbc -salt -in backup_file.tar.gz -out backup_file.tar.gz.enc -k yoursecretpassword

 

Это создаст новый, зашифрованный файл «backup_file.tar.gz.enc» в текущем каталоге. Вы всегда можете расшифровать его позже, выполнив:

openssl aes-256-cbc -d -in backup_file.tar.gz.enc -out backup_file.tar.gz -k yoursecretpassword

 

Этот метод очень прост, но он имеет некоторые недостатки. Самый большой из них – требования к дисковому пространству. При шифровании, как описано выше, вы должны хранить как незашифрованный, так и зашифрованный файл, и в результате вам потребуется дисковое пространство в два раза больше размера файла резервной копии. Конечно, в зависимости от ваших требований, это может быть что-то, что вы хотите – сохранение нешифрованных файлов локально улучшит скорость восстановления – после того, как дешифрование данных также займет некоторое время.

 

Шифрование резервной копии на лету

Чтобы избежать необходимости хранить как зашифрованные, так и незашифрованные данные, вы можете реализовать шифрование на более раннем этапе процесса резервного копирования. Мы можем это сделать через дампы. Короче говоря, дамп – это способ отправки данных от одной команды к другой. Это позволяет создать цепочку команд, обрабатывающих данные. Вы можете сгенерировать данные, затем сжать и зашифровать. Примером такой цепи может быть:

mysqldump --all-databases --single-transaction --triggers --routines | gzip | openssl enc -aes-256-cbc -k mypass> backup.xb.enc

 

Вы также можете использовать этот метод с помощью xtrabackup или mariabackup. Фактически, это пример из документации MariaDB:

mariabackup --user = root --backup --stream = xbstream | openssl enc -aes-256-cbc -k mypass> backup.xb.enc

 

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

mysqldump --all-databases --single-transaction --triggers --routines | gzip | openssl  enc -aes-256-cbc -k mysecretpassword | tee -a mysqldump.gz.enc | nc 10.0.0.102 9991

 

В результате вы увидите локальный файл «mysqldump.gz.enc», и копия данных будет передана в программу, которая будет что-то делать с ней. Мы использовали «nc», который передавал данные другому хосту, на котором выполнялось следующее:

nc -l 9991 > backup.gz.enc

 

В этом примере мы использовали mysqldump и nc, но вы можете использовать xtrabackup или mariabackup и некоторый инструмент, который будет загружать поток в Amazon S3, Google Cloud Storage или какой-либо другой облачный провайдер. Любая программа или скрипт, который принимает данные на stdin, может использоваться вместо nc.

 

Использовать встроенное шифрование

В некоторых случаях инструмент резервного копирования имеет встроенную поддержку шифрования. Примером здесь является xtrabackup, который может внутренне зашифровать файл. К сожалению, mariabackup, даже если он является xtrabackup, не поддерживает эту функцию.

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

root@andreyex:~# openssl rand -base64 24
HnliYiaRo7NUvc1dbtBMvt4rt1Fhunjb

 

Xtrabackup может принимать ключ в текстовом формате (с использованием опции –encrypt-key) или он может читать его из файла (используя параметр –encrypt-key-file). Последнее более безопасно, поскольку передача паролей и ключей в виде простого текста в командах приводит к их сохранению в истории bash. Вы также можете увидеть это в списке запущенных процессов, что довольно плохо:

root       1130  0.0  0.6  65508  4988 ?        Ss   00:46   0:00 /usr/sbin/sshd -D
root      13826  0.0  0.8  93100  6648 ?        Ss   01:26   0:00  \_ sshd: root@notty
root      25363  0.0  0.8  92796  6700 ?        Ss   08:54   0:00  \_ sshd: andreyex [priv]
andreyex  25393  0.0  0.6  93072  4936 ?        S    08:54   0:01  |   \_ sshd: andreyex@pts/1
andreyex  25394  0.0  0.4  21196  3488 pts/1    Ss   08:54   0:00  |       \_ -bash
root      25402  0.0  0.4  52700  3568 pts/1    S    08:54   0:00  |           \_ sudo su -
root      25403  0.0  0.4  52284  3264 pts/1    S    08:54   0:00  |               \_ su -
root      25404  0.0  0.4  21196  3536 pts/1    S    08:54   0:00  |                   \_ -su
root      26686  6.0  4.0 570008 30980 pts/1    Sl+  09:48   0:00  |                       \_ innobackupex --encrypt=AES256 --encrypt-key=TzIZ7g+WzLt0PXWf8WDPf/sjIt7UzCKw /backup/

 

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

root@andreyex:~# openssl rand -base64 24 > encrypt.key
root@andreyex:~# innobackupex --encrypt=AES256 --encrypt-key-file=/root/encrypt.key /backup/
.
.
.
xtrabackup: using O_DIRECT
InnoDB: Number of pools: 1
encryption: unable to set libgcrypt cipher key - User defined source 1 : Invalid key length
encrypt: failed to create worker threads.
Error: failed to initialize datasink.

 

Вы можете задаться вопросом, в чем проблема. Будет ясно, когда мы откроем файл encrypt.key в шестнадцатеричном редакторе, таком как hexedit:

00000000   6D 6B 2B 4B  66 69 55 4E  5A 49 48 77  39 42 36 72  68 70 39 79  6A 56 44 72  47 61 79 45  6F 75 6D 70  0A                                     mk+KfiUNZIHw9B6rhp9yjVDrGayEoump.

 

Теперь вы можете заметить последний символ, закодированный с использованием «0A». Это в основном символ линии, но он рассматривается во время оценки ключа шифрования. Как только мы удалим его, мы можем, наконец, запустить резервную копию.

root@andreyex:~# innobackupex --encrypt=AES256 --encrypt-key-file=/root/encrypt.key /backup/


xtrabackup: recognized server arguments: --datadir=/var/lib/mysql --innodb_buffer_pool_size=185M --innodb_flush_log_at_trx_commit=2 --innodb_file_per_table=1 --innodb_data_file_path=ibdata1:100M:autoextend --innodb_read_io_threads=4 --innodb_write_io_threads=4 --innodb_doublewrite=1 --innodb_log_file_size=64M --innodb_log_buffer_size=16M --innodb_log_files_in_group=2 --innodb_flush_method=O_DIRECT --server-id=1


xtrabackup: recognized client arguments: --datadir=/var/lib/mysql --innodb_buffer_pool_size=185M --innodb_flush_log_at_trx_commit=2 --innodb_file_per_table=1 --innodb_data_file_path=ibdata1:100M:autoextend --innodb_read_io_threads=4 --innodb_write_io_threads=4 --innodb_doublewrite=1 --innodb_log_file_size=64M --innodb_log_buffer_size=16M --innodb_log_files_in_group=2 --innodb_flush_method=O_DIRECT --server-id=1 --databases-exclude=lost+found --ssl-mode=DISABLED

encryption: using gcrypt 1.6.5

181116 13.04:25 innobackupex: Starting the backup operation

IMPORTANT: Please check that the backup run completes successfully.

At the end of a successful backup run innobackupex

prints "completed OK!".

181116 13.04:25  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;mysql_socket=/var/lib/mysql/mysql.sock' as 'backupuser'  (using password: YES).

181116 13.04:25  version_check Connected to MySQL server

181116 13.04:25  version_check Executing a version check against the server...

181116 13.04:25  version_check Done.

181116 13.04:25 Connecting to MySQL server host: localhost, user: backupuser, password: set, port: not set, socket: /var/lib/mysql/mysql.sock

Using server version 5.7.23-23-57

innobackupex version 2.4.12 based on MySQL server 5.7.19 Linux (x86_64) (revision id: 170eb8c)

xtrabackup: uses posix_fadvise().

xtrabackup: cd to /var/lib/mysql

xtrabackup: open files limit requested 0, set to 1024

xtrabackup: using the following InnoDB configuration:

xtrabackup:   innodb_data_home_dir = .

xtrabackup:   innodb_data_file_path = ibdata1:100M:autoextend

xtrabackup:   innodb_log_group_home_dir = ./

xtrabackup:   innodb_log_files_in_group = 2

xtrabackup:   innodb_log_file_size = 67108864

xtrabackup: using O_DIRECT

InnoDB: Number of pools: 1

181116 13.04:25 >> log scanned up to (2597648)

xtrabackup: Generating a list of tablespaces

InnoDB: Allocated tablespace ID 19 for mysql/server_cost, old maximum was 0

181116 13.04:25 [01] Encrypting ./ibdata1 to /backup/2018-11-27_13-05-34/ibdata1.xbcrypt

181116 13.04:26 >> log scanned up to (2597648)

181116 13.04:27 >> log scanned up to (2597648)

181116 13.04:28 [01]        ...done

181116 13.04:28 [01] Encrypting ./mysql/server_cost.ibd to /backup/2018-11-27_13-05-34/mysql/server_cost.ibd.xbcrypt

181116 13.04:28 [01]        ...done

181116 13.04:28 [01] Encrypting ./mysql/help_category.ibd to /backup/2018-11-27_13-05-34/mysql/help_category.ibd.xbcrypt

181116 13.04:28 [01]        ...done

181116 13.04:28 [01] Encrypting ./mysql/slave_master_info.ibd to /backup/2018-11-27_13-05-34/mysql/slave_master_info.ibd.xbcrypt
181116 13.04:28 [01]        ...done

 

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

root@andreyex:~# ls -alh /backup/2018-11-27_13-05-34/

total 101M

drwxr-x---  5 root root 4.0K Nov 27 13.04 .

drwxr-xr-x 16 root root 4.0K Nov 27 13.04 ..

-rw-r-----  1 root root  580 Nov 27 13.04 backup-my.cnf.xbcrypt

-rw-r-----  1 root root  515 Nov 27 13.04 ib_buffer_pool.xbcrypt

-rw-r-----  1 root root 101M Nov 27 13.04 ibdata1.xbcrypt

drwxr-x---  2 root root 4.0K Nov 27 13.04 mysql

drwxr-x---  2 root root  12K Nov 27 13.04 performance_schema

drwxr-x---  2 root root  12K Nov 27 13.04 sys

-rw-r-----  1 root root  113 Nov 27 13.04 xtrabackup_checkpoints

-rw-r-----  1 root root  525 Nov 27 13.04 xtrabackup_info.xbcrypt
-rw-r-----  1 root root 2.7K Nov 27 13.04 xtrabackup_logfile.xbcrypt

 

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

Если вам нужно расшифровать файлы, вы можете использовать innobackupex с опцией -decrypt для этого:

root@andreyex:~# innobackupex --decrypt=AES256 --encrypt-key-file=/root/encrypt.key /backup/2018-11-27_13-05-34/

 

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

for i in `find /backup/2018-11-27_13-05-34/ -iname "*\.xbcrypt"`; do rm $i ; done

 

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

Exit mobile version