Mikrotik backup using SSH and SCP

    If we look back into the past when there was no Ansible or other linux remote administration systems, we used only our improvised scripts and allowed them to connect to systems via ssh using keys. I think to this day many people use their scripts instead of centralized management systems.

    I decided to share my experience.
    It was necessary to write a script that can go to a given number of hosts and backup some configuration files.

    The logic of work lined up immediately. Go to the host via ssh, execute some commands to prepare backups and pick up the finished files using scp.

    The first step is to create a user who will have access to the necessary data with the necessary rights. Then I think everyone will be able to figure out which group to identify the user. The main thing to remember:
    1. The username for login without password must be the same on all hosts, or you will have to specify a username for each host, which is not convenient;
    2. The user must have access to the host without a password (ssh-keygen to help);
    3. The user must have access to the files that need to be taken.

    here you can go in several ways 1) execute a command in a remote shell to collect the necessary data to be backed up and then pick it up 2) configure cron on the host and execute the data collection command, and only then, someday, go to the host and pick up the ready-made backup patties . Of course, we will go the first way.

    We have this configuration -
    10 hosts (Mikrotik) from which you need to get two types of backups - binary (for recovery from scratch) and a configuration without passwords and certificates for uploading to a working config. We also have at our disposal a machine with debian 8 on board, let's call its server (and it doesn’t matter that it is a container, it is important that it is Debian) and of course, where would it be without it - zabbix-server.

    • IP Mikrotik - 10.10.0.1, 10.10.1.1, 10.10.2.1, 10.10.3.1, 10.10.4.1, 10.10.5.1, 10.10.6.1, 10.10.7.1, 10.10.8.1, 10.10.9.1;
    • IP Zabbix-server - 10.10.10.10;


    To simplify the task, zabbix-hostname will be in mik format (third octet in decimal format) .host thus we get -
    • Zabbix hostnames - mik0.host, mik1.host, mik2.host, mik3.host, mik4.host, mik5.host, mik6.host, mik7.host, mik8.host, mik9.host


    If someone does not remember - we specify the zabbix hostname in the settings file zabbix-agent (the agent is not needed here, but still) and on the zabbix server in web-ui.


    First of all, we create the RSA key on our server. Why RSA - but actually out of habit, by the way, old versions of RB only support DSA, and all that is fresh 6.35 already works with RSA and DSA, so look at the situation, you can upgrade as I did :) if you already have ready key - skip this step.

    ssh-keygen -t RSA

    We transfer the contents of the file $ HOME / .ssh / id_rsa.pub from the server to our hosts. I am lazy and used winbox for Mikrotik.

    For Linux, you can make it easier to create a sh script and run it as a user, by which we will go to the host for backups ( on hosts, the user should already be) of such content -
    If you have a DSA key, then change id_rsa.pub to id_dsa.pub
    #!/usr/bin/env bash
    
    hosts=(10.10.0.1 10.10.1.1 10.10.2.1 10.10.3.1 10.10.4.1 10.10.5.1 10.10.6.1 10.10.7.1 10.10.8.1 10.10.9.1)
    username='user'for host in${hosts[*]}do
                    cat $HOME/.ssh/id_rsa.pub | ssh -o "StrictHostKeyChecking no"${user}@${host}'cat >> ~/.ssh/authorized_keys'done

    We launch it and enter the passwords for all 10 servers in turn.

    There is a catch in the script - I didn’t specifically add verification, otherwise I’ll completely forget how to press the keys -) if you read everything, the catch will not work.

    Soooo, what's next, but, for sure, we already know how to go without a password to all hosts under the user, let's say user.
    We want to get Mikrotik configs. Actually proceed.

    We create such a script on the server -
    #!/usr/bin/env bash
    
    hosts=(10.10.0.1_mik0.host_22 \
           10.10.1.1_mik1.host_22 \
           10.10.2.1_mik2.host_22 \
           10.10.3.1_mik3.host_22 \
           10.10.4.1_mik4.host_22 \
           10.10.5.1_mik5.host_22 \
           10.10.6.1_mik6.host_22 \
           10.10.7.1_mik7.host_22 \
           10.10.8.1_mik8.host_22 \
           10.10.9.1_mik9.host_22 )
    # bash array of values. All values are arrays too, after remove splitter "_".# Sub array content IP_ZABBIX-HOSTNAME_SSH-DAEMON-PORT
    cdate=`date +%d-%m-%Y` # System date =) Hi Max
    dir="/mik_backup/"# Storage for backups
    cmd="/system backup save name=backup; export file=backup.rsc hide-sensitive"# command that do the preparation of backup
    username="user"# SSH user
    zabbix_hp=(10.10.10.10 10051) # IP then PORT
    age="30"# remove all backups older then 30 days
    itemname="backup"# zabbix item
    error_value="1"# error value for trigger
    value="0"# good value =)for host in${hosts[*]}# Get values from main listdo
    hostname=($(echo${host} | tr "_"" ")) # Get values from sub list
    ssh ${username}@${hostname[0]} -o "StrictHostKeyChecking no" -p${hostname[2]}"${cmd}"
    new_dir="${HOME}${dir}${hostname[1]}/${cdate}"
    mkdir -p ${new_dir}
    scp -P${hostname[2]}${username}@${hostname[0]}:backup.backup  ${new_dir}
    scp -P${hostname[2]}${username}@${hostname[0]}:backup.rsc ${new_dir}
    check=`find ${new_dir} -type f -name backup.*`
    if [ "${check}" == "" ]
    then
    zabbix_sender -z ${zabbix_hp[0]} -p ${zabbix_hp[1]} -s ${hostname[1]} -k ${itemname} -o ${error_value}else
    zabbix_sender -z ${zabbix_hp[0]} -p ${zabbix_hp[1]} -s ${hostname[1]} -k ${itemname} -o ${value}fidone
    find ${HOME}${dir} -mindepth 2 -mtime ${age} -type d -exec rm -rf {} \; #clear dirs


    I tried to comment as much as possible on everything that happens in the script. Let's see what is being done here.

    Here we say which interpreter we will execute the code
    #!/usr/bin/env bash
    

    Here we create an array with the data we need to connect to the hosts and send data to zabbix
    hosts=(10.10.0.1_mik0.host_22 \
           10.10.1.1_mik1.host_22 \
           10.10.2.1_mik2.host_22 \
           10.10.3.1_mik3.host_22 \
           10.10.4.1_mik4.host_22 \
           10.10.5.1_mik5.host_22 \
           10.10.6.1_mik6.host_22 \
           10.10.7.1_mik7.host_22 \
           10.10.8.1_mik8.host_22 \
           10.10.9.1_mik9.host_22 )
    

    Here I think only one variable needs an explanation - $ cmd. These are two commands that are executed sequentially on Mikrotik. The first one creates a binary backup, the
    second one creates a script with settings without uploading passwords and encryption keys.

    cdate=`date +%d-%m-%Y` # System date =) Hi Max
    dir="/mik_backup/"# Storage for backups
    cmd="/system backup save name=backup; export file=backup.rsc hide-sensitive"# command to do the preparation of backup
    username="user"# SSH user
    zabbix_hp=(10.10.10.10 10051) # IP then PORT
    age="30"# remove all backups older then 30 days
    itemname="backup"# zabbix item
    error_value="1"# error value for trigger
    value="0"# good value =)

    The main body of the program. At the entrance to the loop, we have an array contained in the $ hosts variable. The loop works like this - take the first element of the array, with us it is 10.10.0.1_mik0.host_22 and start working with it. The first step is to add the array created from the first element of the $ hosts array to the $ hostname variable. We do this with the tr command, essentially as in python we emit the action of the .split () line method. It turns out quite tolerably. We get 3 elements in the $ hostname array. The first element is the host ip. The second element is zabbix-hostname. The third element is ssh-port.
    Next, we access these elements using an index, again python.
    Next, we create a directory tree for storing files and tell scp which files to take. Please do not kick - if someone tells me how to use scp in such a design to access files by mask + in karma.
    After we received the files, we send a success message to zabbix.
    Checking the creation of the config is done by simply searching for the file in the destination directory. It was possible to make a comparison of md5 on Mikrotik and in the destination directory, but that's another story, although I did.

    for host in${hosts[*]}# Get values from main listdo
    hostname=($(echo${host} | tr "_"" ")) # Get values from sub list
    ssh ${username}@${hostname[0]} -o "StrictHostKeyChecking no" -p${hostname[2]}"${cmd}"
    new_dir="${HOME}${dir}${hostname[1]}/${cdate}"
    mkdir -p ${new_dir}
    scp -P${hostname[2]}${username}@${hostname[0]}:backup.backup  ${new_dir}
    scp -P${hostname[2]}${username}@${hostname[0]}:backup.rsc ${new_dir}
    check=`find ${new_dir} -type f -name backup.*`
    if [ "${check}" == "" ]
    then
    zabbix_sender -z ${zabbix_hp[0]} -p ${zabbix_hp[1]} -s ${hostname[1]} -k ${itemname} -o ${error_value}else
    zabbix_sender -z ${zabbix_hp[0]} -p ${zabbix_hp[1]} -s ${hostname[1]} -k ${itemname} -o ${value}fidone

    Here we clean the place. The $ age variable will help us keep backups as much as we need.
    find ${HOME}${dir} -mindepth 2 -mtime ${age} -type d -exec rm -rf {} \; #clear dirs


    Now the most trivial.
    We create a template on the zabbix server or just a data item of the zabbix_trapper type on our nodes, which we added in advance for monitoring in zabbix.
    I will not lay out a template from one data element and one trigger. I think everyone can do it. The main thing to remember, if hosts are monitored through zabbix-proxy, you must send data to zabbix-proxy. Otherwise, we send everything to zabbix-server.
    No matter what IP these zabbix web ui hosts will have. It is important that the hostname matches the data in the script.

    PS. All scripts need to be thrown chmod + x so they can be launched without invoking the interpreter.
    PSS To transfer the scp list of files for backup to linux, you can make another array and put it in a for loop. You can do everything in the form of the resulting parameters. Well, in general, you can have fun.

    Also popular now: