Instalando libvirt en ArchLinux

Introducción

Libvirt es un API de código abierto y una herramienta de administración para diferentes sistemas de virtualización entre los que se encuentran Xen, OpenVZ, Virtualbox, VMWare, Microsoft Hyper-V y por supuesto KVM/Qemu instalado en el servidor de desarrollo previamente.

Este software es ideal para la gestión de las máquinas virtuales y su administración remota a través de conexiones seguras con SSH.  Además incluye una librería en C para el desarrollo de aplicaciones e incluye además interfaces para diversos lenguajes como Python, Perl, Ruby, Java y PHP.

Instalación del software

Instalar los paquetes del repositorio oficial.

# pacman -S libvirt urlgrabber dnsmasq bridge-utils

Inicio automático del demonio

Configurar el demonio de libvirtd para que se inicie automáticamente junto con el sistema operativo.

# vi /etc/rc.conf

DAEMONS = (… libvirtd …)

Debe tenerse en cuenta que el demonio libvirtd requiere ser invocado después de dbus y avahi-daemon.

Autorizar la administración a usuarios sin privilegios

Si se desea que usuarios sin privilegios (diferentes de root) administren las máquinas virtuales, estos deberán ser explícitamente autorizados de la siguiente manera.

# vi /etc/polkit-1/localauthority/50-local.d/org.libvirt.unix.manage.pkla

[Allow a user to manage virtual machines]
Identity=unix-user:jimezam
Action=org.libvirt.unix.manage
ResultAny=yes
ResultInactive=yes
ResultActive=yes

Si en lugar de administración se desea conceder la autorización para monitorear las máquinas se deberá especificar la siguiente acción.

org.libvirt.unix.monitor

Permitir el acceso a través de SSH

Para permitir el acceso a las máquinas virtuales a través de herramientas como virsh o virt-viewer a través del protocolo SSH (qemu+ssh) es necesario contar con paquete netcat de OpenBSD instalado de la siguiente manera.

$ sudo pacman -S openbsd-netcat

Si se cuenta adicionalmente con el paquete netcat convencional instalado es posible que este se haya apoderado del enlace /usr/bin/nc y libvirt intente utilizarlo erróneamente generando el siguiente mensaje de error.

error: server closed connection: nc: invalid option — ‘U’
Try `nc –help’ for more information.
error: failed to connect to the hypervisor

En ese caso es necesario indicarle a libvirt cual es la versión de netcat que debe utilizar.  Esto se puede realizar desde los parámetros extra del URI en cada invocación de acceso de la siguiente manera.

$ virsh -d 0 –connect qemu+ssh://usuario@servidor/system?netcat=/usr/bin/nc.openbsd

O de manera permanente modificando en el servidor el enlace /usr/bin/nc de la siguiente manera.

$ sudo mv /usr/bin/nc /usr/bin/nc.orig

$ sudo ln -s /usr/bin/nc.openbsd /usr/bin/nc

Enlaces

Acceder a un servicio RDP de Windows a través de un túnel SSH

Introducción.

Esta semana fue necesario acceder remotamente a unos servidores para desplegar en ellos un proyecto.  El servidor web es visible a través de Internet y utiliza GNU/Linux, este expone además del http el servicio ssh al exterior utilizando el puerto 45729.  En la red interna (por obvias razones) se encuentra un segundo servidor con Windows XP SP3 sobre el cual se ejecuta la base de datos MSSQL.

Estructura general de la red
Estructura general de la red

Trivialmente el acceso al servidor web es muy sencillo gracias al SSH.  La transmisión de archivos al servidor Windows también puede ser fácilmente implementada gracias al cliente de Samba que permite una interacción transparente con el protocolo SMB de este sistema operativo.  Pero qué pasa si es necesario acceder a la consola grafica de Windows ?  Desafortunadamente en esta etapa de despliegue es necsario hacer verificaciones y algunos cambios en la base de datos MSSQL y no fue posible encontrar herramientas de administración remotas o web que fueran realmente efectivas.  La única opción sería acceder al escritorio a través de Internet.

Para hacer esto, el primer paso es activar el servicio de escritorio remoto (Remote Desktop Protocol) en Windows XP y autorizar su acceso desde la red LAN.

El segundo paso consiste en garantizar el acceso remoto a través de Internet.  Para esto se deberá aprovechar el protocolo SSH del servidor GNU/Linux.

Una primera aproximación es utilizar el ForwardX11 del servicio SSH a través del cual es posible unrrutar el protocolo de la interfaz gráfica de usuario (X11) hacia el cliente a través de la conexión segura.  Después de establecida la conexión se utiliza la aplicación rdesktop, local al servidor web, y su presentación es redirigida hacia el cliente gracias al protocolo SSH.

Esta aproximación fue exitosa, sin embargo los tiempos de respuesta aunque tolerables, fueron muy largos.

Una segunda aproximación consiste en la creación de un túnel SSH entre el servicio de RDP del servidor con Windows XP y el servidor GNU/Linux que pueda ser accedido desde Internet a través de conexiones seguras.  Esta aproximación, que se describe a continuación, nos dió unos mejores tiempos de respuesta a través de una implementación simple pero mas elegante que la anterior.

Procedimiento.

Como se mencionó anteriormente, el primer paso es la activación del servicio de escritorio remoto en la máquina Windows XP SP3 que se encuentra en la red privada, esto se debe realizar localmente.

El siguiente paso consiste en establecer el túnel entre el cliente y el servidor web (GNU/Linux) a través de Internet involucrando al servidor de bases de datos (Windows XP) asociándolo a un puerto específico del primero.  Para hacer esto se debe ejecutar el siguiente comando desde el cliente.

$ ssh -L 33389:192.168.3.1:3389 -l usuario mi.servidor.com -p 45729 -Nf

mi.servidor.com es el nombre FQDN con el que se accede al servidor GNU/Linux que expone a Internet el servicio de SSH a través del cual se ingresa a la red remota.  El puerto que utiliza en este caso el servicio SSH es el 45729.  De manera similar, la dirección del servidor Windows XP es la 192.168.3.1 y el puerto (por defecto) que utiliza el servicio de RPD es el 3389 con el cual se establece un túnel con el puerto local 33389.

El proceso después de autenticado se envía automáticamente a background retornando el control del shell gracias al parámetro -N especificado, sin embargo es posible verificar el establecimiento del túnel de la siguiente manera.

$ ps -fea | grep ssh

jimezam  25009     1  0 14:46 ?        00:00:00 ssh -L 33389:192.168.3.1:3389 -l usuario mi.servidor.com -p 45729 -Nf

Esquema general del túnel SSH
Esquema general del túnel SSH

En términos generales, el túnel SSH le permite al cliente acceder al servicio RDP remoto (192.168.3.1:3389) desde localhost:33389 de manera transparente a través del servicio SSH de mi.servidor.com.

Finalmente en el cliente se accede al escritorio remoto utilizando una aplicación como rdesktop de la siguiente manera.

$ rdesktop -z localhost:33389

La ejecución de este comando mostrará localmente la consola gráfica de la máquina Windows XP.

Escritorio remoto del servidor Windows XP
Escritorio remoto del servidor Windows XP

Una nota acerca de clientes en Windows.

Este procedimiento puede adaptarse para el uso de clientes Windows utilizando herramientas adicionales como el caso de Putty para el establecimiento del túnel SSH y la aplicación para conexión a escritorios remotos de Windows.

El primero de ellos es software libre y puede obtenerse en la página web de Putty mientras que el segundo hace parte de las herramientas incluídas en Windows XP y se accede a través de los siguientes menúes.

Inicio > Accesorios > Conexión a escritorio remoto.

Conexión al escritorio remoto de Windows XP
Conexión al escritorio remoto de Windows XP

Enlaces.

Acceder al escritorio remoto de GNU/Linux Ubuntu 10.04 utilizando FreeNX

Introducción.

Después de experimentar el acceso al escritorio remoto de GNU/Linux a través de XDMCP (con Xephyr y como una terminal) encontré que los resultados fueron satisfactorios pero con algunas desventajas: la seguridad y la velocidad.  En pocas palabras no es prudente utilizar XDMCP en un ambiente diferente a LAN ya que su tráfico no está encriptado y el puerto abierto puede convertirse en un problema de seguridad.

Por esta razón decidí probar un software muy conocido pero que nunca utilizado.  FreeNX es la versión libre del NXServer de NoMachine, el cual es descrito de la siguiente manera en su sitio de Launchpad.

NX technology is a computer program that handles remote X Window System connections, and attempts to greatly improve on the performance of the native X11 protocol to the point that it can be usable over a slow link such as a dial-up modem … The open source alternative to NoMachines’s commercial NX Server.

En términos generales me gustaron mucho los resultados, es rápido y aparentemente seguro (su tráfico se envía a través de SSH). El servidor inclusive puede servir de proxy para acceder a servidores RDP (Windows), VNC o de impresoras mediante los paquetes freenx-rdp, freenx-vnc y freenx-smb respectivamente.

En la instalación, a pesar de no ser compleja, encontré un par de bugs para Ubuntu 10.04 que fueron resueltos.  Este procedimiento se describe a continuación.

Instalar el servidor.

Instalar los paquetes.

$ sudo aptitude install python-software-properties

$ sudo add-apt-repository ppa:freenx-team

$ sudo aptitude update

$ sudo aptitude install freenx-server

Crear las llaves de acceso (opcional).

Como mencioné inicialmente, FreeNX utiliza el protocolo SSH para su transporte, por este motivo puede aprovechar la riqueza de opciones de autenticación que provee este servicio.  Por defecto el servidor instala una pareja de llaves por defecto, utilizarlas constituye un riesgo de seguridad.  Por este motivo se sugiere que se creen y popularicen las llaves propias.  Si la seguridad no es una preocupación, puede obviar este paso y continuar con la instalación del cliente.

Si recibe un mensaje de error al ejecutar nxsetup indicándole que el comando no fue encontrado, realice primero los pasos descritos en la sección de solución de problemas.

$ sudo sudo /usr/lib/nx/nxsetup –install

——> It is recommended that you use the NoMachine key for
easier setup. If you answer “y”, FreeNX creates a custom
KeyPair and expects you to setup your clients manually.
“N” is default and uses the NoMachine key for installation.

Do you want to use your own custom KeyPair? [y/N] y
Setting up /etc/nxserver …done
Generating public/private dsa key pair.
Your identification has been saved in /etc/nxserver/users.id_dsa.
Your public key has been saved in /etc/nxserver/users.id_dsa.pub.
The key fingerprint is:
90:d2:6b:93:58:35:09:7b:e4:cd:43:db:83:9b:e2:bf root@jimezam-notebook
The key’s randomart image is:
+–[ DSA 1024]—-+
|      ..+..      |
|     . *.= +     |
|    . * o * o    |
|     + =   + .   |
|    . = S o      |
|     . o .       |
|        .        |
|         .       |
|          E.     |
+—————–+
Setting up /var/lib/nxserver/db …done
Setting up /var/log/nxserver.log …done
Adding user “nx” to group “utmp” …done
Setting up known_hosts and authorized_keys2 …Unique key generated; your users must install

/var/lib/nxserver/home/.ssh/client.id_dsa.key

on their computers.
done
Setting up permissions …done
Setting up cups nxipp backend …
cp: `/usr/lib/cups/backend/ipp’ and `/usr/lib/cups/backend/ipp’ are the same file

Copie la llave a los equipos cliente, la cual posteriormente podrá ser importada desde el cliente de NX.

$ sudo scp /var/lib/nxserver/home/.ssh/client.id_dsa.key usuario@mi-cliente:~/client.id_dsa.key

Después de importada la llave en el cliente de NX de mi-cliente, se recomienda que remueva el archivo ~/client.id_dsa.key.

Crear nuevas llaves (Servidor)

Es posible que por motivos de seguridad posteriormente desee crear nuevas llaves para reemplazar las existentes después de una cierta cantidad de tiempo.  Para hacer esto ejecute el siguiente comando.

$ sudo dpkg-reconfigure freenx-server

Seleccione el tipo de llaves a utilizarse, utilice la opción Create new custom keys para crear un nuevo par.

Selección del tipo de llaves
Selección del tipo de llaves

Seleccione el tipo de autenticación a utilizarse, en este caso se utilizará el servicio SSH.

Selección del tipo de autenticación
Selección del tipo de autenticación

Finalmente transmita la nueva llave a los clientes para permitirles acceder nuevamente al servidor.

Instalar el cliente.

Instalar el paquete.

Descargue el paquete correspondiente a su sistema operativo de la siguiente dirección.

http://www.nomachine.com/select-package-client.php

Para este caso, Ubuntu 10.04 de 64 bits, se descargo el paquete NX Client DEB for Linux – x86_64.  A continuación se instala el paquete recién descargado.

$ sudo dpkg -i nxclient_3.4.0-7_x86_64.deb

CUPS Printing Backend

The NX Client set-up procedure detected that your “IPP CUPS” printing
backend doesn’t allow printing from the NX session. In order to have
printing support in your NX system, you need to set proper permissions
on the IPP backend. Please execute:

chmod 755 /usr/lib/cups/backend/ipp

$ sudo chmod 755 /usr/lib/cups/backend/ipp

Ejecutar el cliente.

$ /usr/NX/bin/nxclient &

Crear una nueva cuenta de conexión con el asistente (cliente).

Presione el botón Next para iniciar el asistente de creación de cuentas.

Iniciar el asistente de creación de cuentas
Iniciar el asistente de creación de cuentas

Especifique la siguiente información relacionada con la conexión al servidor.

  • Session: nombre de la sesión (a gusto del usuario).
  • Host: dirección IP o nombre del servidor FreeNX.
  • Port: puerto donde se está ejecutando el servicio SSH.
  • Connection Type: tipo de acceso a la red, en este caso es una red LAN.
Información de conexión al sevidor
Información de conexión al sevidor

Especifique la siguiente información relacionada con el administrador de ventanas a ejecutarse en el servidor.

  • Tipo: en este caso será una conexión nativa (Unix) y se ejecutará GNOME.
  • Size: se permite utilizar el máximo tamaño disponible.
Información del escritorio
Información del escritorio

Presione el botón Finish para terminar el asistente.

Finalizar la instalación
Finalizar la instalación

Realizar una conexión con el servidor.

Registro de usuarios
Registro de usuarios

Seleccione el tipo de sesión (Session) que se creó anteriormente a través del asistente y especifique su información de autenticación (Login y Password) para acceder al servidor.  Presione el botón Login para iniciar la sesión.

Si el servidor cuenta con sus propias llaves personalizadas (ver proceso de instalación) será necesario importarlas en el cliente para poder registrarse exitosamente (ver siguiente apartado).

Importar las llaves del servidor en el cliente.

Si el servidor cuenta con sus propias llaves personalizadas (que es lo mas conveniente) es necesario importarlas en el cliente para que se realice exitosamente la conexión al mismo.  Para esto es necesario transferir la llave (client.id_dsa.key) de manera segura desde el servidor hasta el cliente (ver comando scp en la instalación del servidor).

Para importar el archivo de llave seleccione editar la configuración de la sesión presionando el botón Configure del diálogo de registro (ver anterior).

Configuración de sesión
Configuración de sesión

Presione el botón Key… e importe o pegue la llave proveniente del archivo client.id_dsa.key traído desde el servidor.  Después de importado se recomienda que remueva de manera segura este archivo.

Importar llave
Importar llave

Solución de problemas.

No existe la aplicación nxsetup.

Si obtiene el siguiente mensaje de error, el paquete de freenx-server no incluyó erróneamente la aplicación nxsetup la cual es necesaria para realizar su instalación completa.

nxsetup: command not found

Para corregir este problema realice los pasos descritos a continuación.

$ cd /usr/lib/nx

$ sudo wget “https://help.ubuntu.com/community/FreeNX?action=AttachFile&do=get&target=nxsetup.tar.gz”

$ sudo mv “FreeNX?action=AttachFile&do=get&target=nxsetup.tar.gz” nxsetup.tar.gz

$ sudo tar zxvf nxsetup.tar.gz

$ sudo rm nxsetup.tar.gz

Enlaces.

Realizar un tar local y almacenarlo remotamente a través de SSH

Introducción.

Esta es la versión mas simple y menos elaborada que se me ocurre para hacer copias de seguridad esporádicas de archivos locales y almacenarlos en un servidor de archivos remoto.  No permite la facilidad de autenticación con llaves de propósito único como en los artículos anteriores (1 y 2), pero es posible utilizarlo con la autenticación basada en llaves (de propósito general) y la autenticación basada en contraseñas.

En funcionalmente es un tar y scp resumidos en una única ejecución de comandos.

Procedimiento.

Se desea realizar la copia de seguridad de los archivos locales almacenados bajo el directorio /archivos/importantes y almacenarlos en el servidor mis.backups.com bajo la ubicación /u/backups.  El procedimiento es tan sencillo como la única línea que se muestra a continuación.

$ tar zcvf – /archivos/importantes | ssh usuario@mis.backups.com “cat > /u/backups/miArchivoBackup.tgz”

Realizar copias de seguridad remotas con llaves SSH de propósito único (2 – el camino inverso)

Introducción.

Después de encontrar una forma muy interesante de hacer las copias de seguridad mediante el uso de llaves de propósito único mi mente inquieta se ha quedado pensando acerca de la factibilidad de hacer lo mismo pero en sentido contrario y de la posible utilidad para el mismo problema: el método mas simple, seguro y fácil de implementar para hacer las copias de seguridad.

En el artículo anterior se configuró al servidor para que confiara en el cliente que portara el par de llaves adecuado, esta confianza le permitiría al servidor ejecutar un único comando y retornar la información resultante al cliente el cual podría tomar el flujo binario de bytes y crear con él un archivo.  En este caso, cualquiera que tuviera posesión de los archivos de la llave y la passphrase (si las llaves se crearon con ella) podrían ejecutar el comando único, en otras palabras, obtener la copia de seguridad del servidor.  En términos generales esto no debe suceder, no debe ser un riesgo ya que supuestamente las llaves se encuentran bien resguardadas, sin embargo estamos analizando el peor escenario.

Ahora, cómo sería el caso contrario en el que el antes cliente (quien almacena las copias de seguridad) confiara en el servidor (a quien se le va a hacer la copia de seguridad) y recibiera todos los archivos que este le envía y los almacenara en el sistema de archivos.  Es posible implementarlo ?  En caso de comprometerse la pareja de llaves, cuál sería el peor escenario ?

Como lo veo hasta el momento, el atacante estaría posibilitado a subir todos los archivos que quisiera llenando la partición del sistema de archivos (ataque por denegación de servicio – DOS) e interfiriendo con el uso normal del sistema.  Podría además sobreescribir (dependiendo de como se cree el script local) los archivos sobre los cuales cuenta con suficientes permisos.  Estos efectos se minimizarían con el uso de un usuario específico para las copias de seguridad, la asignación de una cuota de disco, la implementación de un buen script en el cliente y un contínuo seguimiento al éxito de las copias de seguridad.  En términos generales es aún mas promisorio que la primera versión (directa).  Vale la pena explorar esta aproximación.

Desde el punto de vista funcional hay una diferencia que debe tenerse en cuenta, la primera aproximación es útil inclusive para realizar las copias de seguridad desde equipos que no siempre están activos o en línea, ya que puede realizarse por demanda; mientras que la segunda aproximación analizada a continuación, requiere que ambos equipos estén en línea al mismo tiempo ya que el procedimiento probablemente se inicie por un proceso cron en el servidor.

Crear la llave de propósito único.

Para la creación de la llave de propósito único se siguen los mismos pasos realizados durante la experimentación con la versión directa, con la diferencia que ahora el servidor es el equipo donde se almacenan las copias de seguridad y el cliente es el equipo que contiene la información a la cual se le desea hacer copia de seguridad.  De esta manera, las llaves (demokey y demokey.pub en el ejemplo) se crearían en el servidor web (por ejemplo) y se crearía el archivo ~/.ssh/authorized_keys2 con el contenido apropiado en el servidor de copias de seguridad.

Crear el script para recibir las copias de seguridad.

Del lado del servidor de copias de seguridad (donde se almacenarán) se crea a manera de ejemplo la siguiente configuración.

Una ruta donde se almacenarán las copias de seguridad.

$ mkdir -p /u/backups/datos

$ chown -R bkpuser /u/backups

$ chmod -R 700 /u/backups

Se crea un script para recibir los archivos con las copias de seguridad y almacenarlos en la ubicación creada anteriormente.

$ vi /u/backups/recibir.sh

# Fecha de creación de la copia de seguridad.
FECHA=`date +%Y%m%d`
# Hora de creación de la copia de seguridad.
HORA=`date +%H%M%S`
# Ubicación donde se almacenan las copias de seguridad.
DIRECTORIO=/u/backups/datos
# Nombre del archivo donde se almacenará la copia de seguridad.
ARCHIVO=”backup-${DATE}-${TIME}.data”

# Almacenar la información de la copia de seguridad.
cat > $DIRECTORIO/$ARCHIVO

# Reportar al cliente el nombre del archivo utilizado.
echo $ARCHIVO

$ chmod +x /u/backups/recibir.sh

Finalmente se configura la llave (authorized_keys2) para que invoque a recibir.sh como su propósito único.

$ vi ~/.ssh/authorized_keys2

(modificar la llave específica)
from=”*.jorgeivanmeza.com,10.20.*” command=”/u/backups/recibir.sh“,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-dss AAAAB3Nza…(mas caracteres)… jimezam@mi-cliente

El modificador from permite limitar desde cuales ubicaciones es posible utilizar la llave privada para acceder a la funcionalidad de las copias de seguridad.  En este caso sólo es posible acceder a través de SSH utilizando esta llave de propósito único desde cualquier equipo del dominio jorgeivanmeza.com o desde cualquier equipo de la subred 10.20.xxx.xxx.

Realizar una copia de seguridad.

Para iniciar una copia de seguridad desde el servidor de aplicaciones (servidor web por ejemplo) sólo es necesario ejecutar el siguiente comando.

$ tar zcvf – /ruta/a/resguardar 2> /dev/null | ssh bkpuser@mi-servidor


backup-20100927-205847.data

En el ejemplo anterior se realizó la copia de seguridad de los directorios bajo /ruta/a/resguardar y se guardó en mi-servidor en un archivo llamado backup-20100927-205847.data.  Esta última información puede resultar útil para guardar el registro de los archivos de copias de seguridad generados.  Otra alternativa mas elegante sería utilizar llaves de propósito único para cada servidor al cual se le va a hacer copia de seguridad de forma que se pueda especificar claramente que archivo corresponde a que servidor.

Realizar copias de seguridad remotas con llaves SSH de propósito único

Introducción.

Es muy común que se deban desarrollar actividades en los servidores así como el subir y descargar archivos necesarios para o producto de estas actividades.  Un caso muy especial de este tipo de necesidades es la realización de copias de seguridad.

Del lado del servidor se acostumbra (si no se opta por una solución mas elaborada) crear scripts (1 y 2) que crean las copias empaquetadas de los archivos los cuales deben ser resguardados.  Generalmente la ejecución de esta tarea se realiza periódica y automáticamente a través de un proceso cron del sistema operativo.  Queda pendiente el problema de transferir esta información desde el servidor hasta el equipo local de manera segura y en lo posible automatizada.

La mejor opción para el transporte de los archivos es utilizar un método seguro basado en SSH, sin embargo el uso de contraseñas entorpece el desarrollo ya que estas dificultan la implementación y se constituyen como un riesgo ya que estas deben estar disponibles de manera legible en el cliente para ejecutar la utilidad de transferencia de archivos (como scp).

Gracias a la flexibilidad del protocolo SSH, es posible obviar la autenticación por contraseñas y utilizar un método basado en llaves, a través del cual se autoriza en el servidor el acceso directo a los usuarios que tengan su llave registrada en él.  De esta forma el usuario puede acceder a los datos de la cuenta y transmitirlos si es necesario.  La llave privada envuelta en esta configuración se cifra con una passphrase para mayor seguridad.  Esto hace que sea necesario introducirla, al menos una vez por sesión, antes de poder realizar satisfactoriamente la autenticación basada en llaves.

Esta situación va en contra de los requerimientos de la automatización ya que sería necesaria la intervención humana para realizar las copias de seguridad, al menos al inicio de esta.  Por suerte es posible eliminar la necesidad de esta passphrase de la llave privada, sin embargo se incurre en un significativo riesgo de seguridad (especialmente en servidores compartidos) ya que quien se apodere de los archivos de la llave, tendrá acceso total a la cuenta del usuario en el servidor remoto.

La solución final a este dilema es la utilización del esquema basado en llaves que he mencionado anteriormente pero utilizando llaves que tengan un fin único y específico, es decir, las llaves no permitirán el acceso total a la cuenta en el servidor sino que permitirán solamente la ejecución de una instrucción específica y previamente determinada, de esta manera no será tan crítica la eliminación de la passphrase.

Crear la llave de propósito único.

Generar la pareja de llaves.

$ ssh-keygen -t dsa -f ~/.ssh/demokey

Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase):      [ENTER]   [1]
Enter same passphrase again:                     [ENTER]
[1]
Your identification has been saved in /home/jimezam/.ssh/demokey.
Your public key has been saved in /home/jimezam/.ssh/demokey.pub.
The key fingerprint is:
77:71:75:7e:d2:7a:f3:af:3f:77:cf:2d:77:6a:79:f3 jimezam@jimezam-ultra
The key’s randomart image is:
+–[ DSA 1024]—-+
|                o|
|               +.|
|            . o +|
|             o o.|
|        S . . …|
|         . .   .o|
|               ..|
|              ++O|
|             .oBE|
+—————–+

Especifique una passphrase vacía cuando se le solicite [1] para evitar que se le solicite nuevamente cada vez que vaya a ser utilizada la llave.  Tenga en cuenta el impacto de seguridad que esto pueda traer a su sistema.

Verifique la existencia de los archivos generados los cuales deberán ser similares a los siguientes.

$ ls -l ~/.ssh/

-rw——- 1 jimezam jimezam  668 2010-09-23 00:56 demokey
-rw-r–r– 1 jimezam jimezam  611 2010-09-23 00:56 demokey.pub

Especificar el propósito único de la llave.

Cree una copia de la llave pública recién generada.

$ cp ~/.ssh/demokey.pub tempkey

Esta tendrá un contenido similar al siguiente.

$ cat tempkey

ssh-dss AAAAB3Nza…(mas caracteres)… jimezam@mi-cliente

Modifíquelo de la siguiente manera.

$ vi tempkey

command=echo I’m `/usr/bin/whoami` on `/bin/hostname`,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-dss AAAAB3Nza…(mas caracteres)… jimezam@mi-cliente

Transmitir la llave de propósito único al servidor.

$ cat tempkey | ssh jimezam@mi-servidor ‘sh -c “cat – >>~/.ssh/authorized_keys2″‘

Por seguridad remueva la copia de la llave de propósito único después de haberla transmitido al servidor.

$ rm tempkey

Verificar el funcionamiento de la llave de propósito único.

La prueba se realiza intentando acceder al servidor utilizando SSH y la cuenta del usuario que posee la llave de propósito único.

$ ssh jimezam@mi-servidor

I’m jimezam on mi-servidor
Connection to mi-servidor closed.

Modificar el propósito único de la llave.

Siendo la precondición del artículo la necesidad de realizar copias de seguridad del servidor remoto, se va a modificar el propósito de la llave a crear un tar que contenga los archivos importantes y que será posteriormente transmitido al cliente a través de SSH.  La complejidad de este comando depende de los requerimientos que se tengan, sin embargo el ejemplo a continuación servirá como lineamientos básicos para su elaboración.

Como fácilmente se podrá concluír el comando es referenciado por la sección command al comienzo de la línea de la llave de propósito único.  Este comando puede ser especificado desde el cliente en el contenido de la llave si no se ha transmitido aún al servidor o podrá ser manipulado desde el servidor en el archivo ~/.ssh/authorized_keys2.

$ vi ~/.ssh/authorized_keys2

(modificar la llave específica)
from=”*.jorgeivanmeza.com,10.20.*command=”tar zcf – ~/tmp 2> /dev/null“,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-dss AAAAB3Nza…(mas caracteres)… jimezam@mi-cliente

El modificador from permite limitar desde cuales ubicaciones es posible utilizar la llave privada para acceder a la funcionalidad de las copias de seguridad.  En este caso sólo es posible acceder a través de SSH utilizando esta llave de propósito único desde cualquier equipo del dominio jorgeivanmeza.com o desde cualquier equipo de la subred 10.20.xxx.xxx.

En este caso particular, la llave de propósito único crea un tar de un directorio específico (~/tmp) y envía su flujo de bytes a través de la conexión SSH.

Obtener el archivo de la copia de seguridad.

Del lado del cliente el proceso inverso consiste en abrir una conexión SSH con el servidor utilizando la cuenta a la cual pertenece la llave de propósito único y obtener el archivo enviado a través de un flujo binario.

$ ssh -T -i ~/.ssh/demokey jimezam@mi-servidor | cat > miCopiaDeSeguridad.tgz

El parámetro -i es opcional y permite especificar el archivo con la identidad (llave privada) que se va a utilizar, mientras que el parámetro -T es necesario para transmitir un flujo binario de información.

Finalmente después de la ejecución anterior, en el cliente local se encuentra el archivo miCopiaDeSeguridad.tgz con la copia de seguridad del directorio ~/tmp del servidor.

Agradecimientos.

Gracias a Paul Keck por ayudarme a encontrar la dirección correcta para solucionar el problema del flujo binario de información (-T).

Enlaces.

Establecer una conexión web segura con un sitio web sin HTTPS a través de un tunel SSH con GNU/Linux

Introducción.

A pesar de que el hosting donde se almacena mi blog no cuenta con certificados SSL para poder implementar HTTPS siempre me había preguntado si era posible realizar conexiones seguras con ese servidor específico para realizar ciertas transacciones, es decir, me importaba especialmente mi acceso de administrador cuando debía ingresar mi nombre de usuario y contraseña para autenticarme ya que mediante el HTTP estas viajan planas (sin cifrado).

Ya que por estos días he vuelto a escribir acerca del protocolo SSH, me doy por fin la tarea de detallar este procedimiento, que a través de un túnel SSH con el servidor permite establecer conexiones seguras y temporales con el mismo.

Precondiciones.

  • El servidor cuenta, además del servicio HTTP, con el servicio de SSH.
  • El usuario cuenta con una cuenta de usuario y contraseña válidas para acceder al servidor a través de SSH.
  • La conexión se considera segura hasta el servidor que se contacta (el hosting del blog en mi caso), si se acceden sitios mas allá de él la transmisión será insergura.
  • El cliente cuenta con un navegador web que permita configurar su proxy.  Se recomienda utilizar Firefox.

Procedimiento.

Establecer el túnel seguro.

En esta etapa inicial se crea un túnel SSH entre el equipo cliente y el servidor (que almacena el blog).

$ ssh -fND 4711 usuario@mi.blog.com

El túnel se conecta del lado del cliente mediante el puerto 4711 (definido por el usuario).  La instrucción ssh es enviada automáticamente a background después de realizarse la autenticación (normalmente basada en nombre de usuario y contraseña).  Si desea evitar este comportamiento, remueva el parámetro -f de la instrucción.

Configurar a Firefox para utilizar el túnel.

Es necesario indicarle a Firefox que enrrute el tráfico de información a través del túnel recién creado.  Para hacer esto es necesario acceder a las preferencias de red mediante los menúes Edit > Preferences y allí activar la sección Advanced (parte superior) y presionar el botón Settings en la pestaña Network (parte media).

Configuración de conexión de Firefox

En el diálogo de configuración de conexiones seleccione la opción Manual proxy configuration y especifique la dirección 127.0.0.1 como SOCKS Host y 4711 como Port.  Este último valor deberá coincidir con el utilizado durante el establecimiento del túnel.

Una alternativa mas flexible a esta es el uso de FoxyProxy, un plugin para Firefox que permite manipular sus proxies de una forma mas eficiente.  Presione CTRL+F2 para acceder a la configuración de este plugin, presione el botón Add New Proxy e ingrese la información del túnel.

FoxyProxy plugin, Proxy Settings

Configurar a Firefox para incluír las peticiones de DNS a través del túnel (opcional).

Hasta este punto la comunicación entre el cliente y el servidor, a pesar de que se realiza utilizando el protocolo HTTP, se realiza de manera cifrada ya que se hace utilizando el túnel SSH.  Por fuera de esta comunicación quedan las solicitudes para resolver nombres a través del servicio DNS que hace el cliente antes de transmitir la información a través del túnel.  Esto probablemente no sea un riesgo significativo de seguridad pero enrrutarlas a través del túnel confiere un poco mas de privacidad, al menos a nivel de la LAN ya que no será posible identificar localmente esta información mediante el uso de un sniffer.

Por suerte Firefox permite configurarse para incluír las peticiones al DNS a través de un proxy SOCKS, el cual en este caso es el túnel SSH.  Para hacer esto es necesario acceder al siguiente URL en el navegador: about:config.

Opciones de configuración de Firefox relacionadas con proxies.

Finalmente ubique la variable network.proxy.socks_remote_dns y modifique su valor a true.

Si utiliza FoxyProxy puede realizar esta configuración por proxy ingresando a la configuración del proxy elegido (Proxy Settings) y seleccionando la casilla de verificación Perform remote DNS lookups on hostnames loading through this proxy en la pestaña General.

Finalizar el túnel.

Para terminar la existencia del túnel simplemente finalice la aplicación de ssh, ya sea terminando la aplicación con CTRL+C (si no estaba en background) o matando su proceso mediante el comando kill.

Recuerde ajustar nuevamente el proxy activo en Firefox para continuar utilizando el tipo de conexión habitual en su equipo.

Autenticación basada en llaves para SSH

Introducción.

A diario utilizamos el protocolo SSH para establecer conexiones seguras entre servidores y acceder a shells remotos, montar sistemas de archivos remotos y crear túneles entre muchas otras facilidades.  Habitualmente nos autenticamos ante el servidor remoto utilizando contraseñas, es decir, para indicarle quienes somos le enviamos nuestro nombre de usuario y para garantizarle al servidor que efectivamente somos quienes decirmos ser, el enviamos nuestra contraseña, la cual es secreta y sólo el servidor y nosotros la conocemos.

Este es el método de autenticación mas utilizado y viene por defecto con la instalación del servicio SSH, sin embargo no es muy práctico cuando es necesario interactuar en múltiples ocasiones con múltiples servidores ya que será necesario ingresar la contraseña para autenticarnos múltiples veces.  Una solución a este problema es el uso de llaves (privada y pública) para autenticarnos con el servidor remoto.

El procedimiento es simple, el cliente crea su propio par de llaves y le envía al servidor remoto su llave pública.  En el servidor se agrega esta llave recibida a la lista de llaves autorizadas para su conexión.

La próxima vez que el usuario (que cuenta con sus llaves) intenta acceder al servidor a su cuenta (que cuenta con su llave pública autorizada), este último utilizará el método basado en llaves para autenticarlo con el cual no será necesario que ingrese su contraseña nuevamente.

En este punto es necesario hacer una aclaración, la idea fundamental es la de evitar la necesidad de especificar la contraseña del usuario frecuentemente, sin embargo la llave privada del usuario viene por defecto encriptada con una passphrase, la cual debe especificarse cada vez que el usuario la va a utilizar.

La diferencia de uso entre la contraseña y la passphrase es que esta última puede ser recordada mediante agentes SSH los cuales almacenan las passphrases la primera vez que se utilizan y la proveen automáticamente en las veces subsecuentes, es decir, en una sesión de trabajo sólo será necesario escribir una única vez la passphrase específica de una llave para la autenticación basada en estas.

Existen distintos agentes SSH como ssh-agent (incluído con OpenSSH), GNUPG Agent que tiene emulación para OpenSSH, keychain y GNOME Keyring entre otros.  En mi caso utilizo GNOME así que utilizo el Keyring que viene con él por defecto.

Configuración.

Crear las llaves en el cliente.

En el cliente se inicia creando la pareja de llaves, pública y privada.

$ ssh-keygen -b 1024 -t dsa

Generating public/private dsa key pair.
Enter file in which to save the key (/home/jimezam/.ssh/id_dsa):   [1]
Enter passphrase (empty for no passphrase):                        [2]
Enter same passphrase again:                                       [3]
Your identification has been saved in /home/jimezam/.ssh/id_dsa.
Your public key has been saved in /home/jimezam/.ssh/id_dsa.pub.
The key fingerprint is:
55:32:22:01:1f:b3:5c:f1:44:28:49:55:93:55:f9:1f jimezam@micliente
The key’s randomart image is:
+–[ DSA 1024]—-+
|        ..*=*=+++|
|         o.Ooo.=.|
|          =  .=  |
|         .     . |
|        S       .|
|                E|
|                .|
|                 |
|                 |
+—————–+

Se recomienda utilizar la ubicación sugerida por defecto [1] para el almacenamiento de las llaves.  En este punto [2] debe especificarse el passphrase (concepto que se introdujo en la sección anterior) para cifrar la llave privada, es necesario que recuerde muy bien la cadena de texto que utilizó ya que debe ser utilizada durante su confirmación [3] y una vez por sesión cada vez que vaya a realizar la autenticación basada en llaves con otro servidor.

Terminado este procedimiento se deberá tener dos archivos nuevos con las llaves recién generadas: id_dsa.pub es la llave pública y id_dsa es la llave privada.

$ file ~/.ssh/id_dsa.pub

id_dsa.pub: OpenSSH DSA public key

$ file ~/.ssh/id_dsa

id_dsa: PEM DSA private key

Transmitir la llave pública al servidor.

El siguiente paso es el de transmitir la llave pública del usuario en el cliente al servidor.

$ scp ~/.ssh/id_dsa.pub jimezam@miservidor:

Autorizar en el servidor la llave pública enviada desde el cliente.

Se autoriza la llave pública enviada desde el cliente para que el servidor confíe en ella la próxima vez que el primero intente autenticarse.  Para esto se realiza una conexión remotoa con el servidor.

$ ssh jimezam@miservidor

Ya en el servidor se ejecutan los siguientes comandos.

$ mkdir ~/.ssh

$ chmod go-w ~/.ssh

$ cat ~/id_dsa.pub >> ~/.ssh/authorized_keys

$ rm ~/id_dsa.pub

$ chmod 600 ~/.ssh/authorized_keys

Utilización.

La próxima vez que el usuario (con las llaves) intenta acceder a través de SSH al servidor (que confía en la llave pública) el agente SSH que esté utilizando (en mi caso GNOME) le solicitará una única vez el passphrase de la llave privada [2] y de allí en adelante autenticará de manera transparente las demás sesiones que abra el usuario.

$ ssh jimezam@miservidor

GNOME Keyring solicitando una passphrase

Enlaces.

para que confíe en ella la próxima vez que el primero intente autenticarse.

Agilizar las conexiones con SSH

Introducción.

Revisando información acerca del protocolo SSH encontré en el Wiki de ArchLinux unos tips muy interesantes para agilizar las conexiones con los servidores remotos.  A continuación incluyo una reseña de estas sugerencias.

Limitar los algoritmos de cifrado.

No estoy muy seguro cuan buena opción en términos de seguridad sea hacer esto sin embargo es una opción.  La idea es limitar los algoritmos que usa el protocolo para utilizar sólo aquellos que demandan menos recursos de CPU y por ende son mas rápidos.  En este caso se sugiere utilizar ArcFour y Blowfish-CBC.

Para hacer esto en la conexión actual únicamente se debe realizar la conexión de la siguiente manera.

$ ssh -c arcfour,blowfish-cbc usuario@servidor

Si se desea realizar este cambio permanentemente es necesario modificar la configuración del cliente SSH.

$ sudo vi /etc/ssh/ssh_config

Ciphers arcfour,blowfish-cbc

Activar la compresión.

Para hacer esto en la conexión actual únicamente se debe realizar la conexión de la siguiente manera.

$ ssh -C usuario@servidor

Si se desea realizar este cambio permanentemente es necesario modificar la configuración del cliente SSH.

$ sudo vi /etc/ssh/ssh_config

Compression yes

Desactivar la comprobación de IPV6.

Para hacer esto en la conexión actual únicamente se debe realizar la conexión de la siguiente manera.

$ ssh -4 usuario@servidor

Si se desea realizar este cambio permanentemente es necesario modificar la configuración del cliente SSH.

$ sudo vi /etc/ssh/ssh_config

AddressFamily inet

Mantener viva la conexión.

Cuando se trabaja con varias sesiones remotas es frecuente que estas se desactiven por falta de uso (timeout) lo cual es bastante molesto ya que es necesario volver a conectar para continuar con el trabajo.  Esto sucede por razones de seguridad ya que intenta bloquear las conexiones que han sido abiertas y probablemente han sido abandonadas y así impedir que personas no autorizadas puedan acceder al shell, así como optimizar los recursos utilizados por parte de los usuarios.

La idea en este caso es configurar las conexiones de forma que se adecúen a los tiempos de espera que se presentan en el uso del administrador.  En mi caso utilizo los siguientes valores.

$ sudo vi /etc/ssh/ssh_config

ServerAliveInterval 60
ServerAliveCountMax 10

El primer valor  (ServerAliveInterval) le indica al cliente que envíe cada cierto tiempo (magnitud en segundos) paquetes al servidor para indicarle que la conexión continúa con vida.  El segundo valor (ServerAliveCountMax) indica el número de mensajes de vida que pueden ser enviados por el cliente sin recibir respuesta del servidor antes de abortar la comunicación automáticamente.

Crear alias para los servidores.

Esta opción es muy practica cuando se deben realizar conexiones con múltiples servidores y cada una de ellas con características muy específicas, permite establecer parámetros de conexión determinados y nombrarlos bajo un alias para permitir realizar conexiones rápidas con ellos.

La información de los alias de las conexiones es independiente para cada uno de los usuarios del sistema.  Es posible utilizar las opciones válidas del archivo /etc/ssh/ssh_config para establecer los parámetros de configuración de cada una de las conexiones.

$ vi ~/.ssh/config

Host servidor1
HostName 123.123.123.123
Port 12345
User jimezam
Host servidorweb
HostName mi.servidorweb.com
User jimezam
CheckHostIP no
Cipher blowfish

Una vez que se han establecido los alias es posible realizar las conexiones SSH referenciándolos.

$ ssh servidorweb

Crear las sesiones SSH a través de una única conexión.

Esta es la sugerencia que mas me pareció interesante ya que hasta el momento no la conocía.  Permite indicarle al cliente de SSH que envíe las sesiones a través de una única conexión, es decir, la primera vez que se realiza una sesión con un servidor y un usuario específicos el procedimiento de conexión se realiza normalmente, sin embargo las sesiones siguientes en iguales condiciones reutilizan la conexión vigente así que ya no es necesario realizar la autenticación de nuevo.

La configuración de esta opción puede realizarse en el archivo /etc/ssh/ssh_config si se desea que aplique a todos los usuarios del sistema o en ~/.ssh/config si se desea que sólo aplique a un usuario específico.

ControlMaster auto
ControlPath ~/.ssh/socket-%r@%h:%p

Enlaces.

Ejecutar aplicaciones X remotas a través de SSH en GNU/Linux

Introducción.

Otra característica muy práctica que es permite el protocolo SSH (OpenSSL) es la ejecución remota de aplicaciones X.  Esto es, la facilidad de ejecutar aplicaciones gráficas (X) en servidores remotos y recibir su contexto gráfico (ventana) en el escritorio remoto de la misma manera como se ejecutan las aplicaciones locales.  Sobra decir que la comunicación cliente/servidor a través de la cual viajan las peticiones y respuestas de la aplicación se realiza a través de una conexión encriptada así que es posible hacerlo sobre un medio inseguro como Internet.

Hace un par de años había explicado como hacerlo bajo Windows, esta vez voy a documentar como hacerlo bajo GNU/Linux Ubuntu 10.04 (aunque en términos generales aplica para cualquier distribución) donde es aún mas natural.

Requerimientos.

  • Tanto el cliente como el servidor deberán estar ejecutando servidores de ventanas X.
  • El servidor cuenta con el servicio de SSH.
  • El cliente cuenta con un cliente para SSH.
  • El usuario en el cliente tiene una cuenta de usuario con acceso de SSH en el servidor.

Configuración.

En el servidor.

Las siguientes opciones son necesarias en la configuración del servicio SSH en el servidor.

$ sudo vi /etc/ssh/sshd_config

AllowAgentForwarding yes
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes

Después de realizadas las modificaciones en la configuración del servicio es necesario reiniciarlo para que estas sean tenidas en cuenta.

$ sudo /etc/init.d/sshd restart

En el cliente.

No es necesaria ninguna modificación.

Implementación.

Desde el cliente inicie una sesión SSH con el servidor remoto.

$ ssh -X jimezam@mi.servidor.com

jimezam@mi.servidor.com’s password: ******

Nótese el uso del parámetro -X (en mayúscula!) el cual permite la transmisión del protocolo X a través de la conexión segura.

-X      Enables X11 forwarding.  This can also be specified on a per-host
basis in a configuration file.

X11 forwarding should be enabled with caution .  Users with the
ability to bypass file permissions on the remote host (for the
user’s X authorization database) can access the local X11 display
through the forwarded connection.  An attacker may then be able
to perform activities such as keystroke monitoring.

For this reason, X11 forwarding is subjected to X11 SECURITY
extension restrictions by default.  Please refer to the ssh -Y
option and the ForwardX11Trusted directive in ssh_config(5) for
more information.

En el shell de la sesión simplemente invoque las aplicaciones (remotas) que desee ejecutar, estas aparecerán en el escritorio local con su mismo look-and-feel.

Ejecución de aplicaciones remotas a través de SSH

En el ejemplo anterior, el servidor remoto (parte izquierda) sirve remotamente las aplicaciones ejecutadas que se muestran como ventanas locales (parte derecha).  En este caso se ejecutaron xclock, xeyes y xterm.

El servidor se utiliza XFCE como manejador de ventanas (azules) mientras que el cliente utiliza GNOME (negras), nótese como las aplicaciones remotas, enunciadas en el párrafo anterior, aparecen en ventanas negras adaptándose al manejador de ventanas local.

Enlaces.