Мы обычно заботимся о том, что мы ценим, будь то дорогостоящий смартфон или серверы компании. Данные являются одним из важнейших активов организации, и, хотя мы этого не видим, его необходимо тщательно защищать. Мы используем шифрование данных для шифрования файлов базы данных или целых томов, содержащих наши данные. Внедряем данные в транзитном шифровании с использованием 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
Мы надеемся, что в этом блоге вы узнали, как правильно зашифровать ваши резервные копии.