18 julio, 2017

Automatizar copias de seguridad FTPS con WinSCP y Taskschd

Hace tiempo que quería comentar el tema de como hago mis copias de seguridad de la información personal. Intentaré explicar de forma detallada y clara todo el proceso.

Es recomendable y tendría que ser una práctica rutinaria realizar backups de la información importante. Sobretodo para no echarnos las manos a la cabeza llegado el momento de recuperar cierta información que por cualquier situación hubiésemos perdido.

Se pueden realizar copias de seguridad de una manera u otra. Ya sea copiando directamente la información algún medio extraíble, subiéndola algún servicio de almacenamiento cloud, copias redundantes en ambos medios, etc. A su vez, cuantas más medidas de seguridad se tomen para cada una de estas técnicas, más segura estará la información, pero también más "pasos" habrá que desencadenar para llegar a ella.

En este caso expondré la forma en la que personalmente realizo mis copias de seguridad. Intento no utilizar, siempre que sea posible, aplicaciones locales o almacenamientos cloud de terceros bien conocidos como pueden ser: GoogleDrive, OneDrive, Dropbox, etc. Ya que actualmente son los servicios más extendidos y usados, por lo que tienen un véctor de ataque continuo pero a su vez son servicios que están constantemente actualizándose, lo que los hacen ser "insuficientemente seguros".
En el caso de usar un servicio de terceros de almacenamiento cloud habría que intentar contratarlo en una empresa no tan extendida pero de confianza.

En mi caso tengo una carpeta con toda la información a respaldar, esta carpeta está ubicada en un disco duro extraible protegido con un cifrado BitLocker To Go. Es decir, que cuando conectamos el disco duro extraible a un puerto USB del equipo tenemos que introducir una password para desbloquearlo y así poder acceder a la información.  

Primera medida de seguridad es el disco duro extraible por lo que nunca tengo la información en el disco local del sistema ni en un segundo disco conectado directamente a ningún puerto SATA de la placa base. 

Segunda medida de seguridad es el cifrado por BitLocker To Go. De este modo puedo llevarme el disco duro extraíble a cualquier parte y conectarlo a cualquier equipo con un sistema operativo MS Windows que admita BitLocker, sin recurrir a ningún software de terceros para el cifrado del disco, por que como ya dije, prefiero utilizar mecanismos propios de los sistemas operativos y así garantizar la disponibilidad de la información en un entorno Windows de forma nativa. No es el caso que voy a comentar pero también estaría la posibilidad de cifrar una unidad de almacenamiento externo USB con VeraCrypt. Otra buena alternativa a BitLocker To Go.

Tercer paso sería garantizar esta información en caso de pérdida, tener una redundancia.
¿Que pasaría si en un futuro perdiese físicamente el disco duro extraible o no pudiese acceder a el porque hubiese sido dañado?.
Pues esta redundancia la tendríamos en un sitio de ubicado geográficamente distinto, un sitio de terceros. Actualmente tengo contratado un servicio de almacenamiento cloud en una empresa de Hosting, la cual es de mi confianza.
Este servicio me ofrece un espacio FTP con un certificado SSL/TLS, por lo que puedo usar el canal de control y el de data para transferir información de forma segura mediante FTPS "FTP over SSL" (no confundir con SFTP "SSH-FTP").

Cuarto paso sería automatizar esta tarea. Generar un script que pudiese realizar por ejemplo, una copia semanalmente de toda esta carpeta y la transfiera de forma síncrona a este espacio de almacenamiento vía FTPS. En Windows existe la característica de habilitar el cliente FTP por línea de comandos, pero no podemos usar certificados sobre este cliente. Por lo que obté en usar la herramienta WinSCP, esta incorpora una utilidad en línea de comandos (winscp.com) la cual podemos generar un script en batch en integrarla perfectamente.

Si no somos usuarios administradores en el equipo local por seguridad, si no que usamos un usuario raso para el uso habitual de nuestro equipo, lo que sería más adecuado, para no tener problemas con los privilegios en el momento de ejecutar el script y las acciones que este realice, en este caso trabajaré sobre el direcctorio por defecto de instalación de WinSCP: "C:\Program Files (x86)\WinSCP". Estableceremos los permisos de modificar o control total para el usuario local sobre el directorio.

Figura 1: Establecer permisos sobre el directorio donde se ejecutará el script batch.

Generamos un fichero por lotes .bat con el siguiente código:
@echo off

set ano=%date:~6,4%
set mes=%date:~3,2%
set dia=%date:~0,2%
set backup=backup_%dia%-%mes%-%ano%.log

if exist "backup*.log" (
      del backup*.log
      echo > %backup%
   ) else (
      echo > %backup%
   )
winscp.com /log="%backup%" /loglevel=2 /command "open ftp://USER:PASSWROD@IP_O_DNS_SERVER -explicit" "synchronize remote -delete -mirror -transfer=binary {PATH_LOCAL_ORIGEN} {PATH_REMOTO_DESTINO}" "close" "exit"
Figura 2: Script batch usando winscp.com para conexiones FTPS con sincronización de local a remoto.

Se establecen las variables con las que se obtendrán la fecha/hora actuales y otra (%backup%) para almacenar el nombre que tendrá el fichero con la estructura "backup_DD-MM-AAAA.log". Con un condicinal se comprueba que el fichero "backup*.log" exista. Si ya existiese de una copia pasada lo eliminaría y lo volvería a crear vacío con la estructura de nombre del fichero se le indicara en la variable, si no existiese lo crearía por primera vez de igual modo que el anterior. Esta comprobación sería opcional para aquellos que quieran incluír un fichero de log. En caso de incluírlo aconsejo esta comprobación inicial, este fichero al paso del tiempo suele alcanzar un tamaño considerable, en más de una ocasión antes de haber incluído esta condición en el script llegó a ocupar tamaños superiores a 500MB, y un volumen importante de registros por lo que se hacía finalmente ilegible.

Iniciamos la utilidad winscp.com con el argumento /log para obtener un registro de la actividad realizada incidándole la variable "%backup%" correspondiente al nombre establecido que en ese momento se le asigne al fichero con fecha/hora actuales. Podemos indicar el nivel de depuración del log con el parámetro /loglevel esto nos dará más detalles de log.

La ventaja de utilizar el parámetro /log con winscp.com es que la password utilizada para la autenticación de conexión con el servidor FTP no se muestra en texto plano en el fichero de log, sino que aparace con tres asteríscos "***" sea cual sea la longitud de la contraseña. A diferencia de si se utilizara winscp.exe donde le pasaríamos el script en un fichero de texto a parte pero le indicaríamos igualmente el parámetro /log por ejemplo: winscp.exe /console /script="script_backup.txt" /log="myscript.log" (ver la figura 11 de este artículo). En este caso la contraseña en el fichero de log si se mostraría en texto plano siendo claramente visible. 

A continuación indicaremos los parámetros realmente importantes, al usar winscp.com en un script batch tendremos que indicarle el modificador /command para que sepa que los próximos modificadores serán realizados en una sola instrucción. Podríamos crear un fichero a parte con los mismos modificadores del comando necesarios, en mi caso solamente realizo una única transferencia por lo que he obtado por unificarlo en un mismo fichero .bat.

Abrimos la conexión al servidor FTP (open) y la invocamos de forma explícita (-explicit). De esta forma el cliente solicita de forma explícita la seguridad acordada para empezar la comunicación con el servidor FTP de modo que tanto el canal de control como el de data sean cifrados.
synchronize remote: Los cambios del directorio local se actualizan con los remotos.
-delete: Elimina archivos obsoletos.
-mirror: Modo espejo (sincroniza también archivos antiguos).
-transfer=binary: Modo de transferencia binario, necesario por ejemplo para transferir ficheros de tipo imagen, vídeo, pdf, etc.
J:\ADRIAN: Directorio local.
/Backup: Directorio remoto.
Finalmente cerramos la conexión (close) y salimos de la sesión (exit).

Más información sobre WinSCP en command line:
https://winscp.net/eng/docs/ftps
https://winscp.net/eng/docs/scriptcommand_open
https://winscp.net/eng/docs/scriptcommand_synchronize

Con esto conseguiremos que cada vez que se ejecute el script este solo hará un repaso a todos los ficheros tanto locales como remotos haciendo un espejo y adaptando solamente los cambios, con lo que conseguiremos una reducción de tiempo en futuras transferencias.

Una vez que tenemos generado el script, tendremos que ejecutarlo manualmente y eso no sería práctico, llegados a este punto lo mejor será automatizar este script para que por ejemplo se ejecute un día y hora en concreto de la semana.
Para no recurrir a herramientas de terceros usaremos el "Programador de tareas" de Windows (taskschd.msc).

Creamos una nueva tarea. Como descadenador será según una progamción, semanalmente los Domingos a las 22:00. En mi caso lo tengo así programado ya que se que ese día de la semana y a esa hora suelo tener equipo encendido.

Figura 3: Estableciendo el desencadenador de la tarea programada.

Las acción será iniciar un programa o script, indicamos el path de la ruta donde se encuentra el script. En mi caso no quería crear una variable de entorno de Windows por lo que tengo que indicarle al sistema donde se encuentra la utilidad winscp.com, por lo que le indico donde se debería iniciar el path en "Iniciar en".

Figura 4: Estableciendo la acción para ejecutar el script.

La configuración de la tarea programada la establecí del siguiente modo. Si la tarea no se ejecuta, reiniciarla cada 1 minuto durante un número de intentos de 5 veces y si sobrepasa las 12 horas de ejecución detener la tarea.

Figura 5: Configuración de la tarea programada.

Finalmente en la pestaña general designamos un nombre a la tarea programada. Una vez llegados a este punto tendremos dos opciones:

- Ejecutar solo cuando usuario haya iniciado sesión: En este caso veremos la vetana de la consola de Windows ejecutando todo el proceso.

- Ejecutar tanto si el usuario inició sesión como si no: En este caso la tarea se ejecutará de forma subyacente al usuario. Aconsejo esta opción ya que nos garantiza la ejecutación de la tarea tan solo con tener encendido el equipo. Por lo que pude comprobar al intentar ejecutar esta tarea de forma manual a través del programador de tareas puede que falle. Sin embargo, al ejecutarse automáticamente según la programación establecida se ejecutará sin problemas.

Si escogemos la primera opción no tendremos problemas. Pero si escogemos la segunda opción ya que puede darse el caso de que no estemos con la sesión iniciada en el equipo pero el equipo esté encendido (y con el BitLocker desbloqueado en este caso). Al intentar establecer la tarea nos dirá que "la cuenta de usuario especificada tenga derechos para iniciar sesión como trabajo por lotes". Esto ocurre por que en mi caso el usuario que habitualmente uso en el sistema por seguridad no está dentro del grupo Administradores, sino dentro del grupo Usuarios y por lo tanto no tiene los suficientes permisos como para llevar a cabo esta acción.

Figura 6: Ejecutar tarea programada tanto si el usuario inicia sesión como si no.

Para ello solamente tendremos que agregar la cuenta de usuario en el editor de directivas seguridad local (a través de la consola de Microsoft "gpedit.msc" o directamente "secpol.msc") buscamos "Iniciar sesión como proceso por lotes" y agregamos el usuario.

Figura 7: secpol.msc - Iniciar sesión como proceso por lotes para una tarea programada.

De este modo ya podremos autenticar con las credenciales del usuario local, independientemente de si se marca el checkbox de "No almacenar contraseña" como si no.
Más información: https://technet.microsoft.com/en-us/library/cc722152(v=ws.11).aspx

Figura 8: Autenticación de credenciales del usuario local para tarea programada.

Para poder hacer un seguimiendo de la ejecución de la tarea programada habilitamos el historial. Esta opción afectará a todas las tareas programadas que tengamos en la biblioteca.

Figura 9: Habilitar el historial de las tareas programadas.

Una vez se ejecute y concluya la tarea, en la pestaña de historial veremos la auditoria de información de tiempos. Para hacerse una idea, en mi caso, según mi conexión de DSL y el ancho de banda contratado con el Hosting que me proporciona el server FTP. En menos de 25 minutos se hicieron transferencias de un total aproximado de 40GB.

Figura 10: Historial de la tarea programada.

Si consultamos el fichero .log que creamos para el registro de actividad de conexiones y transferencias hacia el servidor FTPS. Vemos como la conexión se realiza de forma expícita solicitando el certificado al servidor FTP y finalmente se establece la conexión TLS.

Figura 11: Fichero de log de las transferencias realizadas al servidor FTPS.


Enviar el log por correo electrónico con un Script automatizado en PowerShell

Mencionar la posibilidad de poder auto-enviarse este log generado anteriormente a través de un correo electrónico y así tener un registro más clasificado por fechas.

Se me ocurrió crear un fichero .ps1 (PowerShell) que será el script que enviará el mensaje de correo electrónico con el fichero log como adjunto. E incluir una llamada a al fichero .ps1 al final del script batch que hace la copia de seguridad con WinSCP. De ese modo se garantiza que el fichero log esté finalizado. Con este método no se tendrá que modificar la tarea programada.

Para poder ejecutar scripts en PowerShell sin problemas, se tendrá que cambiar la política de ejecución (ExecutionPolicy). En un principio no están definidas y por seguridad vienen deshabilitados todos los tipos de ejecuciones para los scopes.

Existen varios modos de políticas de ejecución para definir en PowerShell:
Restricted: Bloquea todos los scripts en PowerShell y hace que todas las tareas deban ejecutarse de forma interactiva, nada automático.
AllSigned: Solo pueden ejecutarse paquetes y scripts firmados digitalmente.
RemoteSigned: Los paquetes descargados deben firmarse de forma remota antes de poder instalarlos, los locales no.
Unrestricted: Puede ejecutarse cualquier script, sin restricciones.

Para esta situación puede servir tanto el modo de ejecución RemoteSigned como Unrestricted.

Listamos el tipo de políticas de ejecución y esteblecemos el tipo de política para el scope LocalMachine como Unrestricted.
Get-ExecutionPolicy -List
Set-ExecutionPolicy Unrestricted -scope LocalMachine
Figura 12: Estableciendo el modo de política de ejecución (ExecutionPolicy) para PowerShell

Una vez se puedan ejecutar scripts en PowerShell, se crea un documento de texto en el mismo directorio y se renombra con una extensión .ps1 (extensión usada por PowerShell) por ejemplo "envio_log_correo.ps1". Se inserta el siguiente código:
$fecha = Get-Date -uformat "%d/%m/%Y - %H:%M:%S"
$passwd = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force
$credenciales = New-Object System.Management.Automation.PSCredential ("USUARIO@gmail.com", $passwd)
Send-MailMessage -From USUARIO@gmail.com -To USUARIO@gmail.com -Subject "Backup personal - $fecha" -Body "Backup personal - $fecha" -Attachments "backup*.log" -SmtpServer smtp.gmail.com -UseSsl -Credential $credenciales
exit
Este script en Powershell auto-enviará un mensaje de correo a una misma cuenta de correo electrónico u otra si lo establecemos.

La variable "$fecha" alamacena la función "Get-Date" usando el parámetro "-uformat" seguido de la estructura fecha y hora "DD/MM/AAAA - HH:MM:SS" esto se añadirá en el asunto y cuerpo del mensaje, después del nombre del fichero de log, reflejará el momento actual en el que ha sido enviado este adjunto. Se almacena también la contraseña en la variable "$passwd" en una función "ConvertTo-SecureString" que se pasará en una cadena de texto segura. La ventaja de inclurla la hora es que se puede calcular el tiempo transcurrido en el proceso de backup desde el momento en el que se ejecutó la tarea programada hasta el momento en el que se recibe el mensaje de correo electrónico. Esta información también se podría ver en el historial del programador de tareas como se puede observar en la figura 10 de este artículo. 

USUARIO: Se cambiará por el nombre de usuario de la dirección de correo electrónico correspondiente.
PASSWORD: Password del usuario (dirección del correo electrónico) necesaria para autenticarnos en el servidor de correo.
Backup personal: Texto del asunto (-Subject) y el cuerpo (-Body) del mensaje.
backup*.log: Nombre que se estableciese al fichero de log adjunto a enviar en el mensaje.

En mi caso usaré Gmail como servidor SMTP. En un principio no va poder autenticarse aunque se le pasen correctamente las credenciales de usuario. Esto es debido a la protección de seguridad que implementa Gmail para evitar el inicio de sesión de aplicaciones de terceros menos seguras.

Para poder autenticarse con PowerShell en una cuenta Gmail tan solo se tendría que activar el acceso a "Aplicaciones menos seguras". En el siguiente enlace podemos acceder a esta sección: https://myaccount.google.com/lesssecureapps.

En el caso de tener activado un segundo factor de autenticación (2FA) con Google Authenticator, esta característica estaría deshabilitada y no se podría realizar este proceso.

Figura 13: Activar el acceso a aplicaciones menos seguras en una cuenta Gmail

En el script batch inicial donde se realiza el backup con WinSCP se añade al final la siguiente línea de código indicándole el que le ejecute con powershell, el argumento -file hará la llamada al script .ps1 desde un script .bat. De este modo no se tendrá que modificar la tarea programada.
powershell.exe -file "{PATH_FICHERO.ps1}"
Figura 14: Llamada a un fichero script .ps1 desde un script.bat.

Se puede ver el mensaje de correo electrónico que fue auto-enviado a uno mismo con un fichero adjunto "backup_DD-MM-AAAA.log" donde se muestra la fecha y hora de envío en el cuerpo del mensaje en formato "DD/MM/AAAA - HH:MM:SS".

Figura 15: Correo enviado con Powershell y recibido en Gmail con fecha y hora del log.

El procedimiento de enviarse el log por correo electrónico a través de PowerShell simplemente lo menciono por si es de interés para alguien. Personalmente en mis cuentas de correos Gmail, Hotmail, Yahoo. Tengo habilitado un segundo factor de autenticación, considero que es lo más seguro y que todo el mundo que quiera tener sus cuentas más seguras use, en la medida de lo posible, más de un factor de autenticación.

Si también es el caso de algún/a otro/a las autenticaciones 2FA. Aconsejo crear una cuenta de correo exclusivamente para esta finalidad y configurar las opciones de reenvío de mensajes de esa cuenta para otra cuenta más personal en la que si se tenga habilitada la autenticación 2FA.

Espero que algo de esto le resulte de utilidad o le sirva de ejemplo inspiracional para aquell@s que quieran realizar sus propios métodos para las copias de seguridad.

Saludos!

4 comentarios:

  1. Muchas gracias por el artículo.

    Me da un error al listar los archivos del directorio.

    . 2017-08-10 10:21:45.388 Local file 'C:\Users\FisioViapol\Desktop\copias\..' [2017-08-10T07:49:27.337Z] [0] excluded from synchronization
    . 2017-08-10 10:21:45.388 Recibiendo listado de Directorio...
    > 2017-08-10 10:21:45.388 CWD /home/s20ec263/public_html/diamagnetoterapia.es/
    < 2017-08-10 10:21:45.410 550 Can't change directory to /home/s20ec263/public_html/diamagnetoterapia.es/: No such file or directory
    . 2017-08-10 10:21:45.410 No se pudo obtener el listado del directorio
    . 2017-08-10 10:21:45.411 Asking user:
    . 2017-08-10 10:21:45.411 Error al intentar listar al directorio «/home/s20ec263/public_html/diamagnetoterapia.es». ("No se pudo obtener el listado del directorio","Can't change directory to /home/s20ec263/public_html/diamagnetoterapia.es/: No such file or directory")
    < 2017-08-10 10:21:45.411 Script: Error al intentar listar al directorio «/home/s20ec263/public_html/diamagnetoterapia.es».
    < 2017-08-10 10:21:45.411 Script: No se pudo obtener el listado del directorio

    < 2017-08-10 10:21:45.411 Can't change directory to /home/s20ec263/public_html/diamagnetoterapia.es/: No such file or directory
    . 2017-08-10 10:21:45.412 Script: Failed
    . 2017-08-10 10:21:45.412 Script: Exit code: 1
    . 2017-08-10 10:21:45.415 Desconectado del servidor

    Agradecido si pudieran ayudarme. Un saludo.

    ResponderEliminar
  2. Hola @Fernando, puedes mostrarme la línea de comandos completa?.
    En principio el path destino no existe y no lo reconoce.

    ResponderEliminar
  3. Muy bien explicado :)

    Otra posibilidad que también se podría añadir es que tras finalizar la copia de seguridad enviara un correo con el fichero log y así podrías tener en el correo un control de las copias que se han realizado y cómo se han realizado éstas.


    Un saludo,

    ResponderEliminar
    Respuestas
    1. Hola @Pixu.

      Lo había pensado, pero tengo todas mis cuentas configuradas para autenticarme con F2A. Igualmente se podría tener una cuenta a parte tipo gmail en la que se permita el inicio de sesión de aplicaciones menos seguras y hacer un script automatizado con PowerShell para el envio adjunto del fichero de log.

      Actualizo la entrada con esta información que comentas, por que me parece interesante para aquellos que quieran realizarlo. Tengo que decir que me dio algunos problemas en los primeros scripts que cree para el envío de correos en PowerShell. Finalmente cree un script totalmente funcional. Indico todos los pasos para llevar a cabo este último punto que comentas.

      Gracias,
      Saludos!

      Eliminar

Entradas Relacionadas