Zwykle dbamy o to, co cenimy, czy jest to drogi smartfon, czy firmowe serwery. Dane to jeden z najważniejszych atutów organizacji i chociaż tego nie widzimy, to trzeba je starannie chronić. Wdrażamy szyfrowanie danych w spoczynku w celu szyfrowania plików baz danych lub całych woluminów zawierających nasze dane. Wdrażamy dane w szyfrowaniu tranzytu za pomocą SSL, aby nikt nie mógł podsłuchiwać i zbierać danych przesyłanych przez sieci. Kopie zapasowe nie różnią się. Bez względu na to, czy jest to pełna kopia zapasowa, czy przyrostowa, przechowa przynajmniej część Twoich danych. W związku z tym kopie zapasowe również muszą być szyfrowane. W tym poście na blogu przyjrzymy się niektórym dostępnym opcjom szyfrowania kopii zapasowych. Najpierw jednak spójrzmy, jak możesz zaszyfrować swoje kopie zapasowe i jakie mogą być przypadki użycia tych metod.
Jak zaszyfrować kopię zapasową?
Zaszyfruj plik lokalny
Przede wszystkim możesz łatwo zaszyfrować istniejące pliki. Wyobraźmy sobie, że masz proces tworzenia kopii zapasowych, który przechowuje wszystkie kopie zapasowe na serwerze kopii zapasowych. W pewnym momencie zdecydowałeś, że nadszedł czas, aby wdrożyć przechowywanie kopii zapasowych poza siedzibą firmy w celu odzyskiwania po awarii. Możesz do tego użyć S3 lub podobnej infrastruktury od innych dostawców chmury. Oczywiście nie chcesz przesyłać niezaszyfrowanych kopii zapasowych w dowolne miejsce poza zaufaną siecią, dlatego bardzo ważne jest, aby wdrożyć szyfrowanie kopii zapasowych w taki czy inny sposób. Bardzo prostą metodą, nie wymagającą żadnych zmian w istniejących skryptach kopii zapasowych, jest utworzenie skryptu, który pobierze plik kopii zapasowej, zaszyfruje go i prześle do S3. Jedną z metod szyfrowania danych jest użycie openssl:
openssl enc -aes-256-cbc -salt -in backup_file.tar.gz -out backup_file.tar.gz.enc -k yoursecretpassword
Spowoduje to utworzenie nowego, zaszyfrowanego pliku „backup_file.tar.gz.enc” w bieżącym katalogu. Zawsze możesz go odszyfrować później, uruchamiając:
openssl aes-256-cbc -d -in backup_file.tar.gz.enc -out backup_file.tar.gz -k yoursecretpassword
Ta metoda jest bardzo prosta, ale ma pewne wady. Największym z nich są wymagania dotyczące miejsca na dysku. Podczas szyfrowania, jak opisano powyżej, musisz zachować zarówno niezaszyfrowany, jak i zaszyfrowany plik, w wyniku czego potrzebujesz miejsca na dysku dwa razy większego niż plik kopii zapasowej. Oczywiście, w zależności od Twoich wymagań, może to być coś, czego chcesz – przechowywanie niezaszyfrowanych plików lokalnie poprawi szybkość odzyskiwania – w końcu odszyfrowanie danych również zajmie trochę czasu.
Zaszyfruj kopię zapasową w locie
Aby uniknąć konieczności przechowywania zarówno zaszyfrowanych, jak i niezaszyfrowanych danych, warto wdrożyć szyfrowanie na wcześniejszym etapie procesu tworzenia kopii zapasowej. Możemy to zrobić za pomocą rur. Potoki to w skrócie sposób przesyłania danych z jednego polecenia do drugiego. Umożliwia to stworzenie łańcucha poleceń przetwarzających dane. Możesz wygenerować dane, a następnie skompresować je i zaszyfrować. Przykładem takiego łańcucha może być:
mysqldump --all-databases --single-transaction --triggers --routines | gzip | openssl enc -aes-256-cbc -k mypass > backup.xb.enc
Możesz również użyć tej metody z xtrabackup lub mariabackup. W rzeczywistości jest to przykład z dokumentacji MariaDB:
mariabackup --user=root --backup --stream=xbstream | openssl enc -aes-256-cbc -k mypass > backup.xb.enc
Jeśli chcesz, możesz nawet spróbować przesłać dane w ramach procesu:
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
W rezultacie zobaczysz lokalny plik „mysqldump.gz.enc”, a kopia danych zostanie przesłana do programu, który coś z tym zrobi. Użyliśmy „nc”, który przesyłał dane do innego hosta, na którym wykonano następujące czynności:
nc -l 9991 > backup.gz.enc
W tym przykładzie użyliśmy mysqldump i nc, ale możesz użyć xtrabackup lub mariabackup i jakiegoś narzędzia, które prześle strumień do Amazon S3, Google Cloud Storage lub innego dostawcy chmury. Zamiast „nc” można użyć dowolnego programu lub skryptu, który akceptuje dane na stdin.
Użyj wbudowanego szyfrowania
W niektórych przypadkach narzędzie do tworzenia kopii zapasowych ma wbudowaną obsługę szyfrowania. Przykładem jest tutaj xtrabackup, który może wewnętrznie zaszyfrować plik. Niestety mariabackup, mimo że jest rozwidleniem xtrabackup, nie obsługuje tej funkcji.
Zanim będziemy mogli z niego skorzystać, musimy stworzyć klucz, który posłuży do szyfrowania danych. Można to zrobić, uruchamiając następujące polecenie:
[email protected]:~# openssl rand -base64 24
HnliYiaRo7NUvc1dbtBMvt4rt1Fhunjb
Xtrabackup może zaakceptować klucz w formacie zwykłego tekstu (przy użyciu opcji --encrypt-key) lub odczytać go z pliku (przy użyciu opcji --encrypt-key-file). Ta ostatnia jest bezpieczniejsza, ponieważ przekazywanie do poleceń haseł i kluczy w postaci zwykłego tekstu powoduje ich przechowywanie w historii basha. Możesz to również wyraźnie zobaczyć na liście uruchomionych procesów, co jest dość złe:
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: [email protected]
root 25363 0.0 0.8 92796 6700 ? Ss 08:54 0:00 \_ sshd: vagrant [priv]
vagrant 25393 0.0 0.6 93072 4936 ? S 08:54 0:01 | \_ sshd: [email protected]/1
vagrant 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/
W idealnym przypadku użyjesz klucza przechowywanego w pliku, ale jest też mały problem, o którym musisz wiedzieć.
[email protected]:~# openssl rand -base64 24 > encrypt.key
[email protected]:~# 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.
Możesz się zastanawiać, na czym polega problem. Stanie się jasne, gdy otworzymy plik encrypt.key w edytorze szesnastkowym, takim jak 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.
Możesz teraz zauważyć ostatni znak zakodowany za pomocą „0A”. Jest to zasadniczo znak nowego wiersza, ale jest on brany pod uwagę podczas oceny klucza szyfrowania. Gdy go usuniemy, możemy wreszcie uruchomić kopię zapasową.
[email protected]:~# 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 10:11: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 10:11: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 10:11:25 version_check Connected to MySQL server
181116 10:11:25 version_check Executing a version check against the server...
181116 10:11:25 version_check Done.
181116 10:11: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 10:11: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 10:11:25 [01] Encrypting ./ibdata1 to /backup/2018-11-16_10-11-25/ibdata1.xbcrypt
181116 10:11:26 >> log scanned up to (2597648)
181116 10:11:27 >> log scanned up to (2597648)
181116 10:11:28 [01] ...done
181116 10:11:28 [01] Encrypting ./mysql/server_cost.ibd to /backup/2018-11-16_10-11-25/mysql/server_cost.ibd.xbcrypt
181116 10:11:28 [01] ...done
181116 10:11:28 [01] Encrypting ./mysql/help_category.ibd to /backup/2018-11-16_10-11-25/mysql/help_category.ibd.xbcrypt
181116 10:11:28 [01] ...done
181116 10:11:28 [01] Encrypting ./mysql/slave_master_info.ibd to /backup/2018-11-16_10-11-25/mysql/slave_master_info.ibd.xbcrypt
181116 10:11:28 [01] ...done
W rezultacie otrzymamy katalog kopii zapasowej pełen zaszyfrowanych plików:
[email protected]:~# ls -alh /backup/2018-11-16_10-11-25/
total 101M
drwxr-x--- 5 root root 4.0K Nov 16 10:11 .
drwxr-xr-x 16 root root 4.0K Nov 16 10:11 ..
-rw-r----- 1 root root 580 Nov 16 10:11 backup-my.cnf.xbcrypt
-rw-r----- 1 root root 515 Nov 16 10:11 ib_buffer_pool.xbcrypt
-rw-r----- 1 root root 101M Nov 16 10:11 ibdata1.xbcrypt
drwxr-x--- 2 root root 4.0K Nov 16 10:11 mysql
drwxr-x--- 2 root root 12K Nov 16 10:11 performance_schema
drwxr-x--- 2 root root 12K Nov 16 10:11 sys
-rw-r----- 1 root root 113 Nov 16 10:11 xtrabackup_checkpoints
-rw-r----- 1 root root 525 Nov 16 10:11 xtrabackup_info.xbcrypt
-rw-r----- 1 root root 2.7K Nov 16 10:11 xtrabackup_logfile.xbcrypt
Xtrabackup ma kilka innych zmiennych, których można użyć do dostrojenia wydajności szyfrowania:
- --encrypt-threads umożliwia zrównoleglenie procesu szyfrowania
- --encrypt-chunk-size definiuje bufor roboczy dla procesu szyfrowania.
Jeśli potrzebujesz odszyfrować pliki, możesz użyć innobackupex z opcją --decrypt:
[email protected]:~# innobackupex --decrypt=AES256 --encrypt-key-file=/root/encrypt.key /backup/2018-11-16_10-11-25/
Ponieważ xtrabackup nie czyści zaszyfrowanych plików, możesz chcieć je usunąć za pomocą następującego jednowierszowego:
for i in `find /backup/2018-11-16_10-11-25/ -iname "*\.xbcrypt"`; do rm $i ; done
Szyfrowanie kopii zapasowej w ClusterControl
Dzięki ClusterControl zaszyfrowane kopie zapasowe to tylko jedno kliknięcie. Wszystkie metody tworzenia kopii zapasowych (mysqldump, xtrabackup lub mariabackup) obsługują szyfrowanie. Możesz zarówno utworzyć kopię zapasową ad hoc, jak i przygotować harmonogram kopii zapasowych.
W naszym przykładzie wybraliśmy pełną kopię zapasową xtrabackup, będziemy ją przechowywać w instancji kontrolera.
Na następnej stronie włączyliśmy szyfrowanie. Jak już wspomniano, ClusterControl automatycznie utworzy dla nas klucz szyfrowania. To wszystko, po kliknięciu przycisku „Utwórz kopię zapasową” rozpocznie się proces.
Nowa kopia zapasowa jest widoczna na liście kopii zapasowych. Jest oznaczony jako zaszyfrowany (ikona kłódki).
Mamy nadzieję, że ten wpis na blogu da Ci pewne informacje o tym, jak upewnić się, że Twoje kopie zapasowe są prawidłowo zaszyfrowane.