Copias de seguridad

Copias de seguridad

Con rsnapshot podremos hacer copias de seguridad automáticas y periódicas, optimizando al máximo el espacio ocupado mediante el uso de enlaces simbólicos:

apt-get install rsnapshot

Para configurar las copias editamos /etc/rsnapshot.conf para indicar donde se guardaran los scripts:

snapshot_root /var/cache/rsnapshot/

Además, en este mismo fichero vamos a establecer nuestra política de backups: Se almacenaran las últimas 6 horas, los últimos 7 días, las últimas 4 semanas y los últimos 6 meses. Por otra parte, también indicaremos que directorios queremos copiar y que scripts ejecutar:

...
#rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded --stats --timeout=10
...

#########################################
# BACKUP INTERVALS #
# Must be unique and in ascending order #
# i.e. hourly, daily, weekly, etc. #
#########################################

## Tendremos backup de las últimas 6 horas, los últimos 7 días, las últimas 4 semanas y los últimos 6 meses:
interval hourly 6
interval daily 7
interval weekly 4
interval monthly 6

...
# Excluimos algunos ficheros para hacer más pequeños los backups
exclude access.log
exclude access.log.*
exclude access_log
exclude error.log
exclude error.log.*
exclude .bash_history
...

###############################
### BACKUP POINTS / SCRIPTS ###
###############################

# LOCALHOST
backup /etc/ localhost/
backup /home/ localhost
backup /var/www/ localhost
backup /usr/local/ localhost
backup /var/lib/awstats/ localhost
backup /var/lib/bandwidthd/ localhost
backup /var/lib/cacti/ localhost
backup /var/cache/nagios2/ localhost
backup /var/lib/nagios2/ localho
backup_script /usr/local/bin/backup_dpkg.sh localhost/dpkg/
backup_script /usr/local/bin/backup_mysql.sh localhost/mysql/
backup_script /usr/local/bin/backup_info.sh localhost/info/

backup rsnapshot@webserver:/etc/ webserver/ ssh_args=-p 22
backup rsnapshot@webserver:/usr/local/ webserver/ ssh_args=-p 22
backup rsnapshot@webserver:/var/www/ webserver/ ssh_args=-p 22
backup_script /usr/bin/ssh -i /root/.ssh/id_rsa rsnapshot@webserver /home/rsnapshot/.ssh/backup_mysql_all.sh > db.sql webserver/mysql/all/

En este ejemplo estamos haciendo backup tanto de directorios locales (p.ej. /etc) como remotos del servidor ‘webserver’.

Es importante que los parámetros de este fichero de configuración se encuentren separados por tabulaciones y no por espacios, de lo contrario rsnapshot no podrá procesarlo correctamente. Comprobamos que el archivo de configuración sea correcto:

# rsnapshot configtest
Syntax OK

Simula la creación de un snapshot:

# rsnapshot -t hourly

El snapshot más reciente siempre se encontrará en el número más bajo, en el caso de los snapshots realizados cada hora: /var/cache/rsnapshot/hourly.0/

Es recomendable evitar que slocate indexe el backup, editamos /etc/updatedb.conf:

FINDOPTIONS='-ignore_readdir_race'
export FINDOPTIONS
PRUNEFS="NFS nfs nfs4 afs binfmt_misc proc smbfs autofs iso9660 ncpfs coda devpts ftpfs devfs mfs shfs sysfs cifs lustre_lite tmpfs usbfs udf"
export PRUNEFS
PRUNEPATHS="/tmp /usr/tmp /var/tmp /var/spool /media /var/cache/rsnapshot /var/cache/rsnapshot-tar"
export PRUNEPATHS
NETPATHS=""
export NETPATHS
LOCALUSER="nobody"
export LOCALUSER
NICE=10
export NICE
IONICE_CLASS=2
export IONICE_CLASS
IONICE_PRIORITY=7
export IONICE_PRIORITY

Utilidades rsnapshot

A la hora de hacer backup, además de especificar directorios concretos podemos hacer que se ejecuten scripts (p.ej. que realicen volcados de las BBDD) para que también se efectue una copia de su resultado (en el fichero de configuración de ejemplo anterior, se puede observar como hay varios scripts especificados).
Información de estado

A modo de ejemplo, podemos crear un script a medida /usr/local/bin/backup_info.sh que genere varios ficheros con el estado de la máquina en el momento de realizar la copia:

#!/bin/bash
# Date
/bin/date -R > date.out
# Host name and kernel
/bin/uname -a > uname.out
# Interfaces
/sbin/ifconfig -a > ifconfig.out
# Disk space
/bin/df -h > df.out
# Processes
/bin/ps aux > ps.out
# Open ports & conections
/bin/netstat -atunp > netstat.out
/usr/bin/lsof -i > lsof-i.out
# Processes with lots of files open
/usr/bin/lsof +c 15 | awk '{printf("%15s (%s)n", $1, $2)}' | sort | uniq -c | sort -rn | head > losf-processes-with-lots-of-open-files.out
# Mounted filesystems
/bin/mount > mount.out
# Connected users
/usr/bin/who > who.out
# Firewall rules
/sbin/iptables -L > iptables.out
# Daemons & init scripts
/usr/sbin/sysv-rc-conf --list > sysv-rc-conf.out
# Files with special permissions
#/usr/bin/find / -path /proc -prune -o -perm -2 ! -type l -ls > find-world-writable.out
#/usr/bin/find / -path /proc -prune -o -nouser -o -nogroup > find-files-without-owner.out
#/usr/bin/find / -path /proc -prune -o -type f -perm +6000 -ls > find-suid-guid.out

dpkg y mysql

Scripts que copian el listado de paquetes instalados en Ubuntu y un volcado de la MySQL:

cp /usr/share/doc/rsnapshot/examples/utils/backup_dpkg.sh /usr/local/bin/
cp /usr/share/doc/rsnapshot/examples/utils/backup_mysql.sh /usr/local/bin/

Editamos ‘/root/.my.cnf’ para establecer el password de root y así poder realizar volcados sin necesidad de interaccionar con la máquina:

[client]
user = root
password = secret
host = localhost

Ejecutamos:

chmod 600 /root/.my.cnf

En el fichero de configuración especificaremos los scripts a ejecutar y el destino de su resultado:

backup_script /usr/local/bin/backup_dpkg.sh localhost/dpkg/
backup_script /usr/local/bin/backup_mysql.sh localhost/mysql/

Backups remotos

Si queremos hacer backup de directorios remotos o incluso ejecutar scripts remotos (p.ej. volcado mysql), en el servidor donde tenemos rsnapshot debemos generar una clave SSH con ssh-keygen (ver sección correspondiente) para el usuario root (/root/.ssh/).

En la máquina a la que queremos conectarnos para hacer las copias, crearemos un usuario bloqueado:

useradd -d /home/rsnapshot -m -K PASS_MAX_DAYS=-1,PASS_MIN_DAYS=0,PASS_WARN_AGE=0,UMASK=0022 -s /bin/bash rsnapshot
passwd -l rsnapshot
mkdir -p /home/rsnapshot/.ssh

Además, permitiremos que el usuario ejecute ‘rsync’ como root mediante ’sudo’ sin necesidad de contraseña. Para ello ejecutamos ‘visudo’ y añadimos al final:

rsnapshot ALL=NOPASSWD: /usr/bin/rsync

Para que rsnapshot funcione se conecte remotamente sin intervención, necesitamos copiar la clave pública a ‘/home/rsnapshot/.ssh/authorized_keys’ y conviene establecer todas las limitaciones posibles (ver sección SSH):

from="71.21.5.19",command="/home/rsnapshot/.ssh/validate-ssh.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAUTQEbt7GOcR4jZ2bTgzxpgABIwAAAQEAwAQKRBv+ABDyOgvHfAxSVcWOEzhieC7rwrBjquLJw0W+U9vD7QgmffmuKDZksI7bAAB3NzaC1yc2EAAAdbHBOGg/zgXcrCNsuJ5IJoDw== root@server.com

En este ejemplo, el usuario solo podrá ser utilizado desde una IP concreta, siempre que tenga la clave privada y únicamente podrá ejecutar el script ‘/home/rsnapshot/.ssh/validate-ssh.sh’:

#!/bin/sh

case "$SSH_ORIGINAL_COMMAND" in
*&*)
echo "Rejected"
;;
*(*)
echo "Rejected"
;;
*{*)
echo "Rejected"
;;
*;*)
echo "Rejected"
;;
*< *)
echo "Rejected"
;;
*`*)
echo "Rejected"
;;
rsync --server*)
# the calling user HAST TO BE in the sudoers list for executing rsync!
sudo $SSH_ORIGINAL_COMMAND
;;
mysqldump *)
$SSH_ORIGINAL_COMMAND
;;
/home/rsnapshot/.ssh/backup_mysql_all.sh)
/home/rsnapshot/.ssh/backup_mysql_all.sh
;;
*)
echo "Rejected $SSH_ORIGINAL_COMMAND"
;;
esac

Este script permitirá al usuario ejecutar únicamente 'rsync' (con permisos de root mediante 'sudo'), 'mysqldump' y el script '/home/rsnapshot/.ssh/backup_mysql_all.sh':

#!/bin/bash
/usr/bin/mysqldump --all-databases --add-drop-table --password=secret -u miusuario

El script anterior realiza un volcado de todas las BBDD de MySQL utilizando un usuario/password determinado. Dado que contiene información sensible, el script debe tener permisos restrictivos:

chown -R rsnapshot:rsnapshot /home/rshapshot
chmod 700 /home/rshapshot/.ssh/*.sh

Con esto ya tenemos preparado todo el montaje. Rsnapshot podrá conectarse al servidor (ver fichero de configuración de ejemplo anterior, donde se definían copias del servidor ‘webserver’) sin contraseña y hacer backups de directorios y MySQL. Adicionalmente, hemos establecido controles adicionales para minimizar la posibilidad de que un atacante pueda intentar aprovecharse de la configuración (cifrado SSH, autenticación por clave asimétrica limitada a una IP y a unos comandos concretos).
Tars semanales

De forma semanal, haremos que se cree un tar con la última copia para poder enviarlo cómodamente a otro ordenador:

cp /usr/share/doc/rsnapshot/examples/utils/rsnaptar /usr/local/bin/
mkdir /var/cache/rsnapshot-tar/

Editamos /usr/local/bin/rsnaptar para especificar el lugar donde guardaremos los tar, comentamos GPG y añadimos info al mail que se genera automaticamente.

# DIRECTORIES
TAR_DIR="/var/cache/rsnapshot-tar"
SNAPSHOT_DIR="/var/cache/rsnapshot/daily.0/"
...
#GPG="/usr/bin/gpg"
...
${CAT} << EOF | ${SENDMAIL}
To: ${TO_EMAIL}
Subject: [rsnapshot] Tar backup job complete - ${HOSTNAME}

Now is the time to backup the latest files from rsnapshot on ${HOSTNAME}

Tar files created on ${TAR_DIR}/${DATE}/
EOF

Editamos ‘/etc/cron.d/rsnapshot’ para que se ejecute cada semana:

# Weekly
# At 5:00 every monday
0 5 * * 1 root /usr/local/bin/rsnaptar marble@localhost

Reportes

Si queremos recibir un reporte del backup cada cierto tiempo como medida para saber que se están efectuando:

cp /usr/share/doc/rsnapshot/examples/utils/rsnapreport.pl.gz /usr/local/bin/
gzip -d /usr/local/bin/rsnapreport.pl.gz
chmod 755 /usr/local/bin/rsnapreport.pl

Establecemos en /etc/rsnapshot.conf el nivel de verbose a 3 y añadimos –stats al comando rsync_long_args:

# Verbose level, 1 through 5.
# 1 Quiet Print fatal errors only
# 2 Default Print errors and warnings only
# 3 Verbose Show equivalent shell commands being executed
# 4 Extra Verbose Show extra verbose information
# 5 Debug mode Everything
#
verbose 3

...

# Default rsync args. All rsync commands have at least these options set.
#
#rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded --stats --timeout=10

# this script prints a pretty report from rsnapshot output
# in the rsnapshot.conf you must set
# verbose >= 3
# and add --stats to rsync_long_args
# then setup crontab 'rsnapshot daily 2>&1 | rsnapreport.pl | mail -s"SUBJECT" backupadm@adm.com
# don't forget the 2>&1 or your errors will be lost to stderr

Editamos /etc/cron.d/rsnapshot para hacer que el reporte se genere una vez a la semana:

# 4 times per day
0 */4 * * * root /usr/bin/rsnapshot hourly > /dev/null
# At 3:30 every day
30 3 * * * root /usr/bin/rsnapshot daily > /dev/null
# At 3:00 every monday
0 3 * * 1 root /usr/bin/rsnapshot weekly > /dev/null
# At 2:30 every 1st of month
30 2 1 * * root /usr/bin/rsnapshot monthly > /dev/null

# Run rsnapshot once a week as it were hourly but with rsnapreport (send report by mail)

# I use it only to validate that backups are being done.
# When we execute rsnapshot daily/weekly/... rsync is not called, only a move is done and rsnapreport can not generate a report with that info.
# At 1:00 every monday
0 1 * * 1 root /usr/bin/rsnapshot hourly 2>&1 | /usr/local/bin/rsnapreport.pl | mail -s"[rsnapshot] Weekly report" marble@localhost

Comentarios