Всем привет, в моей первой публикации на хабре хочу поделиться готовым решением для бэкапов устройств Mikrotik.
Для микротика предусмотрены два вида бэкапов конфигурации, это бинарный бэкап и экспорт конфигурации. Бинарный бэкап имеет свои преимущества и недостатки. Преимуществом является то, что после восстановления бинарного бэкапа у вас сохраняется вся конфигурация( с пользователями, паролями, импортированными для пользователей ssh-ключами); недостатком же является то, что такой бэкап нельзя восстановить на другого типа устройство.
В целом и общем это полноценный бэкап, его восстановление занимает мало времени и восстанавливает всю конфигурацию. Экспорт конфигурации как способ бэкапа в свою очередь отчасти сглаживает эти недостатки, являясь скриптом для ребилда микротика. Суть тут в том, что выводятся все настройки, которые могут быть экспортированы. Преимуществом является то, что можно посмотреть и пощупать, что же там экспортируется, а к недостаткам можно опять же отнести то, что это тоже упирается в модель. но чуть меньше. Иногда дело в количестве интерфейсов, иногда ещё в чём-то. Так же не все настройки могут быть экспортированы в текст(пользователи, файлы на усройстве, ssh-ключи).
В целом и общем, как я вынес для себя, совершенно необходимо иметь для себя оба варианта и желательно регулярно и обязательно автоматически. Идею я взял из вики микротика: раз и два.
Предложенный вариант бэкапов по почте или ftp мне не нравится тем, что тут всё либо по почте, либо по ftp, всё plaintext. Так же не нравится то, что надо держать какой-то ящик или ftp и микротики сами будут слать. Мне удобнее всё делать с сервера бэкапов.
По сути для бэкапа по ssh руками достаточно просто зайти на микротик, выполнить бэкап и забрать его. Соответственно это можно автоматизировать.
Как вы уже поняли, реализовалось это всё с помощью обычного bash-скрипта, далее он немного оброс мусором и тихо работает. Поэтому я решил его описать здесь чтобы получить какой-то фидбэк от тех, кому это может быть интересно.
Итак, переходим непосредственно к скрипту.
Файлы скрипта
Для работы скрипта используется исполняемый файл и параметром к нему указывается файл конфигурации.
/usr/local/bin/mbkp /etc/mikrotik_backup/xxx-core01.cfg
Соответственно размещается бэкапный скрипт в директории /usr/local/bin/ для простоты поиска оного в PATH, а файлы конфигурации хранятся в /etc/mikrotik_backup/ в соответствии с FHS. Размещение файлов дело сугубо личное, мне просто так удобнее.
Исполняемый скрипт
Самая первая секция содержит shebang, проверки конфигурационного файла, не указав который, скрипт не выполнится. Далее идут дефолтные переменные, достаточно лаконичные, часть из которых вы можете переопределить в файле конфигурации конкретного устройства.
#!/bin/bash
# mikrotik-backup script
# author Tenhi
# Initial checks
# Config file should be provided and should be readable
[[ -z "$1" ]] && echo "ERR: no config file provided" && exit 1
! [[ -r "$1" ]] && echo "ERR: cannot read $1" && exit 1
# Default variables ( may be overrided in custom config )
#### Connection ####################################
TGT_PORT="22" # default ssh-port
TGT_USER="bkpuser" # Default backup user
IDL="5s" # Default idle time
#### Backup variables ##############################
BKP_BINPWD="NvLB37zchdor9Y4E8KSpxibWHATfjstnw" # Default password for binary backup 33cr
BKP_EXPPWD="hGAEJKptcCznB2v8RaHkoxiSTYNFZ3suW" # Default password for export 33cr
ST_RTN="30" # Default retention time
#### Storage variables #############################
ST_ROOT="/mnt/bkp_share/mikrotik" # Default storage root
Далее идёт строка, которая делает source конфигурационного файла:
#######################################################################################################################
# Importing target config where you can override options
source $1
#######################################################################################################################
После идёт секция с некоторыми переменными, которые лучше задавать после того, как импортируется конфигурационный файл и системные утилиты, которые я для пущей надёжности ищу через which:
#### Utils #############################################################################################
CMD_FIND=$(which find)
CMD_MV=$(which mv)
CMD_GZ=$(which gzip)
CMD_CHO=$(which chown)
CMD_CHM=$(which chmod)
CMD_MKD=$(which mkdir)" -p "
CMD_RM=$(which rm)
CMD_DATE=$(date +%Y%m%d_%H%M) # date in format YYYYMMDD_HHmm
CMD_SSL=$(which openssl)
CMD_SSH=$(which ssh)
CMD_SCP=$(which scp)
########################################################################################################
ST_FULL=$ST_ROOT/$ST_HOSTNAME"/" # full path to .backup (/root_storage/hostname/)
ST_ARCH=$ST_FULL"archive/" # full path to archive (/root_storage/hostname/archive)
TGT_BKPNAME_BIN=$ST_HOSTNAME"_"$CMD_DATE".backup"
TGT_BKPNAME_EXP=$ST_HOSTNAME"_"$CMD_DATE".export"
SSH_OPT=" -o ConnectionAttempts=5 -o ConnectTimeout=5s
-o PasswordAuthentication=no -o PreferredAuthentications=publickey
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
-o GlobalKnownHostsFile=/dev/null -o CheckHostIP=no "
SSH_STR="$CMD_SSH -2 -4 -p $TGT_PORT -l $TGT_USER $TGT_IP $SSH_OPT"
SCP_STR="$CMD_SCP -2 -4 -B $SSH_OPT -P $TGT_PORT $TGT_USER@$TGT_IP:/$TGT_BKPNAME_BIN $ST_FULL"
После идёт определение функций скрипта, описание я дам ниже:
#### Defining functions ################################################################################
function fn_check_log {
# Function for checking need of creating logfile
LOG=$ST_ROOT/"LOG.txt" # log-file location
if [[ -r $LOG ]]
then
return 0
else
echo "
################################################
# Logfile for mikrotik backups
# The format is:
# DATE;STATE;FILENAME
# author: Tenhi(adm@tenhi.ru)
################################################
" > $LOG
fi
}
function fn_check_readme {
# Function for checking need of creating readme
README=$ST_ROOT"/README.txt" # README File
if [[ -r $README ]]
then
return 0
else
echo "
# ===
# Here you can find backups for all Mikrotiks
# Files located in:
# hostname/...
# Archived backups are in:
# hostname/archive/...
# You can get backup info for all jobs in LOG.txt
# ===
" > $README
fi
}
function fn_check_directory {
# Function for checking||creating full-path dirs
if [[ -d $ST_FULL"archive" && -r $ST_FULL"archive" ]]
then
return 0
else
$CMD_MKD $ST_FULL"archive"
$CMD_CHO root:root $ST_FULL
$CMD_CHM 755 $ST_FULL
fi
}
function fn_mikrotik_cleanup {
# Function for cleaning up target mikrotik
$SSH_STR "ip dns cache flush"
$SSH_STR "console clear-history"
}
function fn_mikrotik_fixtime {
# Function for setting ntp client
$SSH_STR "ip cloud set update-time=no; system ntp client set primary-ntp=0.0.0.0 secondary-ntp=0.0.0.0 enabled=yes server-dns-names=pool.ntp.org"
}
function fn_backup_binary {
# Function for saving binary backup
# Changed 20170901
T_BKPSTR="system backup save name=$TGT_BKPNAME_BIN dont-encrypt=no password=$BKP_BINPWD"
T_BKPCLN="file remove [find name=$TGT_BKPNAME_BIN]"
$SSH_STR $T_BKPSTR # Initializing backup
sleep $IDL && $SCP_STR # Copy file to storage
sleep $IDL && $SSH_STR $T_BKPCLN # Remove created file on mikrotik
}
function fn_backup_export {
# Function for saving exported config
# NOTE: decrypt the file
# openssl des3 -d -salt -in encryptedfile.txt -out normalfile.txt
EXP_TMP_FILE="/tmp/"$RANDOM".export"
sleep $IDL && $SSH_STR export > $EXP_TMP_FILE
$CMD_SSL des3 -salt -k $BKP_EXPPWD -in $EXP_TMP_FILE -out $ST_FULL$TGT_BKPNAME_EXP".des3"
$CMD_RM $EXP_TMP_FILE
}
function fn_backup_retention {
# Function for rotating old backups
$CMD_FIND $ST_FULL -mtime +$ST_RTN -type f -exec $CMD_MV {} $ST_ARCH ;
$CMD_FIND $ST_ARCH -type f -exec $CMD_GZ {} ;
}
function fn_log {
# Function for recording results to logfile
if [[ -r $ST_FULL$TGT_BKPNAME_BIN ]]
then
echo $CMD_DATE";okay;"$TGT_BKPNAME_BIN >> $LOG
else
echo $CMD_DATE";fail;"$TGT_BKPNAME_BIN >> $LOG
fi
if [[ -r $ST_FULL$TGT_BKPNAME_EXP".des3" ]]
then
echo $CMD_DATE";okay;"$TGT_BKPNAME_EXP".des3" >> $LOG
else
echo $CMD_DATE";fail;"$TGT_BKPNAME_EXP".des3" >> $LOG
fi
}
Все функции подписаны, но я немного поясню. Функции fn_check_log fn_check_readme проверяют и создают первичное наполнение файлов LOG.TXT и README.TXT
fn_check_directory проверяет создана ли директория для устройства, которое вы описываете в директиве ST_HOSTNAME="" в конфиг-файле
fn_mikrotik_cleanup выполняет очистку кэша DNS и истории команд в консоли, чтобы не тянуть это в бэкап и в секурных целях.
fn_mikrotik_fixtime вещь опциональная, которая принудительно устанавливает ntp-сервер для обновления времени. В этой функции можно написать всё, что угодно, если вы хотите постоянно это выполнять. Можно так же не пользоваться этой функцией если нет нужды.
fn_backup_binary и fn_backup_export делают бинарный и экспорт-бэкапы соответственно. При чём стоит заметить, что вместо plaintext, создаётся зашифрованный экспорт-файл используя openssl. (Соответственно нужно иметь openssl в системе)
fn_backup_retention упаковывает бэкапы старше чем ST_RTN дней, которую вы задаёте в конфиг файле, если не используете стандарт(30 дней). Функция кладёт их в папку archive
fn_log в самом конце скрипта создаёт запись в файле LOG.TXT о статусе бэкапа
Конфигурационный файл устройства
Касательно файла конфигурации минимальная конфигурация это:
# Target device address (ip or DNS)
TGT_IP="nmr01.loc.lan"
# Also will be used to form backupname like $ST_HOSTNAME_YYYYMMDD-HHmm.backup|export
ST_HOSTNAME="loc-nmr01"
Остальные директивы конфиг файлы подробно описаны и являются опциональными, то есть имеют дефолтное значение:
# Example config for mikrotik-backup script
# author Tenhi (adm@tenhi.ru)
# Required parameters are uncommented. Optional are commented
# You can easly uncomment some of them to override defaults
#### Connection ####################################
# Target device address (ip or DNS)
TGT_IP=""
# Target device ssh port
# TGT_PORT="22"
# Target ssh user
# TGT_USER="backupser"
# Idle for avoiding ban (or something else)
# IDL="1s"
#### Backup variables ##############################
# Password for binary backup ( default is in main script and there are no chance to do it without password :) )
# BKP_BINPWD=""
# Password for export ( default is in main script )
# BKP_EXPPWD=""
#### Storage variables #############################
# root backup location
# ST_ROOT="/mnt/backup"
# will be used to create dir $ST_ROOT/$ST_HOSTNAME
# Also will be used to form backupname like $ST_HOSTNAME_YYYYMMDD-HHmm.backup|export
ST_HOSTNAME=""
# backup retention to archive files older $ST_RTN days to $ST_ROOT/$ST_HOSTNAME/archive/
# ST_RTN="30"
#### Logging #######################################
# LOG default location
# LOG=$ST_ROOT/$ST_HOSTNAME/"LOG.txt"
Cron
Если вы хотите зашедулить выполнение, можно использовать пример cron задачи:
# Mikrotik backup script mbkp
# Config:
MCFG="/etc/mikrotik_backup"
MBKP="/usr/local/bin/mbkp"
MLOG="/var/log/mikrotik_backup/log"
# Tasks:
00 03 * * * $MBKP $MCFG"/xxx-core01.cfg" >>$MLOG 2>>$MLOG # XXX DC New core router node1
Итак, сразу об использовании в планировщике cron можете копировать и пользоваться моим решеним, но я немного поясню. Естественно все пути должны существовать и файлы должны быть доступны на чтение, а скприт на выполнение. Использование переменных в кроне не возбраняется и немного улучшает читабельность, когда кроновских задач у вас больше 50.
Автор: Станислав