Совсем недавно по планете прокатились волны WannaCry и его клонов. А сама проблема шифровальщиков стоит перед системными администраторами уже более 10 лет. Рано или поздно – но все внедренные и реализованные меры по защите от шифровальщиков не помогают и все-таки находится пользователь, который открывает письмо, вложение и получает полный «букет». Также много «приятных и увлекательных» часов получает системный администратор.
И тут то все четко начинают понимать, что нужны резервные копии (много, разных, в разных местах). Т.е. правило 3-2-1, придуманное и описанное Peter-ом Krogh-ом, весьма желательно выполнять. Данная статья – пример, который помогает сделать реальным выполнение данного правила на «коленке» — без покупки дорогостоящего оборудования (в условиях жесткой экономии).
Итак – условия решаемой задачи:
• Есть небольшая среда виртуализации от Vmware (пара-тройка ESXi-серверов, vCenter, самый дешевый пакет лицензий – начальный Kit – в целом это не важно для данной статьи. Аналогично статья подойдет и для Hyper-V);
• Есть с десяток виртуальных машин, содержимое которых не хочется потерять в случае отработки автоматизированным Ransomware скриптом;
• Есть система резервного копирования от Veeam (бесплатная редакция, бекапы делаются с помощью PowerShell и Task Schedule).
Задачи:
• Делать резервные копии серверов 1 раз в день по ночам;
• Размножать копии (копировать на NAS-сервер с FreeBSD + ZFS). К слову, на ZFS тоже делаются снапшоты, которые автоматически удаляются по заданному расписанию (zfSnap + Cron);
• Иметь оффлайновую копию «бекапов» на съемном носителе.
Реализация:
Так как основной сервер, который делает резервные копии из работающих виртуальных машин, управляется операционной системой Windows Server (ввиду того, что Veeam Backup работает пока что только на базе этой ОС), было решено для реализации задач использовать PowerShell.
Решение задачи синхронизации бекапов между основным сервером (Windows) и NAS-сервером (FreeBSD):
Для решения задачи требовался скрипт, который бы запускался через Task Scheduler и синхронизировал каталог A с сетевым ресурсом B, доступным через протокол SMB. Вначале я попробовал использовать robocopy – но тесты показали весьма низкую скорость работы полученного скрипта. И я решил реализовать данный скрипт на другом инструменте.
Пятиминутный поиск и 10 минут тестов показали наличие весьма жизнеспособного и готового решения: powershell-synchronizing-a-folder
Скрипт оказался шикарным:
• Работает как с локальными дисками, так и с сетевыми ресурсами;
• Позволяет исключать определенные файлы из задачи;
• Позволяет синхронизировать файлы по заданному шаблону
• Работает на максимальной скорости (т.е. сколько железо и сеть могут выдать – с такой скоростью синхронизация и проходит, в отличие от robocopy).
В итоге на основном сервере появилась пачка заданий в Task Schedule вида:
powershell.exe "C:Scriptssyncfolder.ps1 -SourceFolder:G:BackupsWEBAPPS -TargetFolder:\192.168.0.232backups$WEBAPPS"
И задача синхронизации резервных копий после выполнения заданий Veeam Backup была решена (2 копия с дельтой по времени).
Решение задачи создания оффлайновых резервных копий:
Сама идея проста:
• Подключаем к серверу с Veeam Backup внешний USB 3.0 жесткий диск на 2 Тб
• Большую часть времени держим его Offline (и этим мы защищаемся от автоматизированных Ransomware);
• Когда скрипт отрабатывает, он переводит диск в Online, делает каталог с текущей датой, копирует в него текущие резервные копии, и по окончании выполнения снова переводит диск в Offline.
Реализация:
Отправной точкой служит команда: Get-Disk – нам нужно понять, какие диски у нас есть в системе и виден ли нам внешний USB-диск:
PS C:Windowssystem32> Get-Disk
Number Friendly Name OperationalStatus Total Size Partition Style
------ ------------- ----------------- ---------- ---------------
1 WDC WD30PURX-64P6ZY0 Online 2.73 TB GPT
0 WDC WD10EZEX-60M2NA0 Online 931.51 GB GPT
2 WD Elements 25A3 USB Device Offline 1.82 TB GPT
Теперь нам нужно поместить ссылку на USB-диск в переменную. Для его идентификации предлагается использовать атрибут «Friendly Name». Если Вы предпочитаете использовать другие атрибуты – выведите полный список (get-disk | select *). Либо посмотрите список доступных свойств и методов (get-disk | get-member).
Итого первая часть скрипта:
# Find USB disk by FriendlyName
$mybackupdisk = get-disk | where {$_.FriendlyName -like 'WD Elements 25A3 USB Device'}
Далее – нужно перевести диск из Offline в Online, а также убедиться, что диск в режиме Read-Write (иногда, по невыясненной причине, диск после перехода в Online становился Read-Only. Для выяснения номера диска используем свойство Number ($mybackupdisk.Number).
Получаем кусок:
# Make disk Online
Set-Disk -Number $mybackupdisk.Number -IsOffline $False
Start-Sleep -s 5
# Make disk Writeable (some times it ReadOnly after online - shit happens...)
Set-Disk –Number $mybackupdisk.Number -IsReadonly $False
Start-Sleep -s 5
Для идентификации буквы диска сделаем следующий финт – на USB диск повесим метку (имя): VMUSBBACKUPS (либо через Disk Manager, либо с помощью команды Set-Volume).
Далее – с помощью команды Get-Volume определяем букву подключенного USB-диска (после перевода его в Online):
# Find Disk Volume
$usbvolumename = Get-Volume | where {$_.FileSystemLabel -like 'VMUSBBACKUPS'}
И собственно само копирование нужных данных на диск:
Создаем каталог с текущей датой в имени:
$date = Get-Date
$newbackupfolder = $date.ToString("yyyy-MM-dd")
# Full Backup Fath
$createdirfullpath = $usbvolumename.DriveLetter + ":" + $newbackupfolder
# Create Backup Directory
New-Item -ItemType directory -Path $createdirfullpath -Force -Confirm:$false
Start-Sleep -s 2
Копируем резервные копии:
# Source Backup Dir (with backups)
$sourcebackup = "F:BackupsVCENTER"
# Copy to USB from Disk
Copy-Item $sourcebackup -Destination $createdirfullpath -Recurse
Start-Sleep -s 5
Другой вариант – когда нам нужно не создавать каждый раз новые каталоги и копии – а переписывать файлы новыми версиями – тогда используем уже ранее найденный скрипт для синхронизации каталога А с Б:
# Sync from HDD to USB:
C:Scriptssyncfolder.ps1 -SourceFolder:F:Backups -TargetFolder:$usbvolumename.DriveLetter:VMs
Start-Sleep -s 5
В любом случае – когда Вы закончите копировать либо синхронизировать, весьма желательно сбросить кэш операций (из ОЗУ на HDD/USB) командой:
# Write USB Disk Cache before offline
Write-VolumeCache $usbvolumename.DriveLetter
Start-Sleep -s 5
И не забыть снова перевести диск из Online в Offline:
# Place USB to Offline
Set-Disk -Number $mybackupdisk.Number -IsOffline $True
Результаты:
• Получили резервные копии в трех местах (Windows-сервер, FreeBSD-сервер, USB-диск);
• Два вида хранения (в шарах и на диске);
• Один носитель другого типа – отсуждаемый. Можно вообще иметь пару дисков – и просто 1 или 2 раза в месяц менять их местами (один в сейф). Так как USB-диск в режиме Offline 95% времени – его всегда можно безболезненно выдернуть из сервера.
Моя статистика:
• данная схема работает уже 6 месяцев без сбоев;
• объем синхронизируемых данных (сжатые и дедуплицированные бекапы – от 500 до 700 Гб);
• Время синхронизации на USB-диск – 1 час 20 минут в среднем (1 раз в неделю в выходные).
Полные скрипты можно скачать с Google Disk: BackupExamples
Автор: Dorlas