Publicar la llave pública SSH

Los principales repositorios (Gitlab y Github) exponen las llaves públicas SSH de sus usuarios de forma que están accesibles para descarga:

https://(gitlab|github).com/<usuario>.keys

Es la URL de donde se obtienen, y aquí las mías:

La ventaja es tener un sitio disponible donde está nuestra clave (y la de nuestros colegas) para usar en automatismos como esta task de Ansible:

- name: Enable pilasguru root access
  authorized_key:
    user: root
    state: present
    key: https://gitlab.com/pilasguru.keys
    validate_certs: False

fingerprint de certificados ssh

Con el tiempo uno va coleccionando muchos certificados, algunos dedicados a un determinado proyecto, otros dedicados a algun cliente y, por supuesto los propios. En ese repositorio de certificados que suele ser la carpeta ~/.ssh/ hay que agregar los certificados que por algun motivo distribuimos en algunos servidores… en fin, llegará el día que necesitemos identificar algun certificado privado.

Así que estos son los comandos para obtener el fingerprint (huella dactilar) de certificados privados.

Certificado ssh

$ openssl rsa -in id_rsa -pubout -outform DER | openssl md5 -c
Enter pass phrase for .ssh/id_rsa:
writing RSA key
a2:d7:19:27:fa:89:43:aa:59:fd:ac:eb:71:3f:fb:a8

Como ven, mi certificado privado tiene passphrase y, para leerlo se require que la escriba.

Certificado pem (AWS)

openssl pkcs8 -in .ssh/proyectoX  -inform PEM -outform DER -topk8 -nocrypt | openssl sha1 -c
d3:ff:c0:cf:6f:25:a1:88:b5:c7:9e:9b:ba:b9:57:a4:bb:45:62:68

Los certificados que creamos en AWS se suelen guardar sin passphrase y el fingerprint se muestra inmediatamente.

Google-Authenticator: doble validación para tus cajas Linux

google-authenticator Cuando accedemos a nuestros servidores Linux mediante login (consola) o secure shell (SSH remoto) nos validamos como forma normal de dar seguridad al acceso. Estos mecanismos pueden ser mejorados en los niveles de seguridad mediante configuraciones en /etc/security (login) o ajustes y certificados en SSH; pero la validación en dos pasos, con clave («lo que se«) y también con código de un-solo-uso («lo que tengo») vuelve el proceso de validación mucho más seguro.

En este artículo se describe cómo instalar en el servidor Linux la validación en dos pasos de Google para pedir el código único de acceso inmediatamente luego de validar la clave. Los pasos descriptos son para CentOS 7, pero conceptualmente son equivalentes a los que requiere Debian, donde también lo he instalado; así que vamos:

Requisitos previos

Se requieren los paquetes para compilar el módulo de PAM correspondiente. Una primer opción es instalar todo el ambiente de desarrollo:

yum group install "Development Tools"

O si, solo quieres lo mínimo necesario, deberían ser suficiente estos paquetes:

yum install git autoconf make gcc pam-devel

Fuentes de google-authenticator

Clonamos el repositorio git con la última versión del código:

git clone https://github.com/google/google-authenticator.git

Los fuentes también incluyen las aplicaciones para móviles, pero a nosotros no nos interesan ahora.

Compilación e instalación

Seguimos el documento de instalación dado por los desarrolladores, indicando solamente dónde queremos el módulo, para que lo tome automáticamente CentOS:

cd google-authenticator/libpam/
./bootstrap.sh
./configure --exec-prefix=/usr/lib64
make
make install

(solo ‘make install’ requiere privilegios de root, por lo que debería precederse de ‘sudo’, si corresponde)

Instalación en login

Agregar módulo PAM en archivo /etc/pam.d/login inmediatamente debajo de la linea del módulo ‘system-auth’, o como último módulo del tipo ‘auth’:

auth required pam_google_authenticator.so

Instalación en SSH

El módulo tiene que ser agregado en el archivo /etc/pam.d/sshd, también como último módulo del tipo ‘auth’:

auth required pam_google_authenticator.so

Además en el archivo de configuración del servidor SSH /etc/ssh/sshd_config habilitar:

ChallengeResponseAuthentication yes

para que siga el procedimiento de autenticación de PAM.

Reiniciar servidor sshd

systemctrl restart sshd

Configuración de usuarios

Cada usuario debe inicializar el sistema de códigos de un único uso y sincronizarlo con la aplicación de su celular y no es mi objetivo profunzar mucho en esto, pero el usuario ejecuta:

$ google-autenticator

y el sistema le hará unas preguntas de configuraciones de seguridad y generará un archivo .google_authenticator en el home del usuario. En ese archivo se incluyen también algunos códigos de emergencia y el código para iniciar la aplicación del móvil a calcular códigos.

Resultado

Y ya queda activo para ese usuario; aqui con login:

linuxbox login: rodolfo
Password:
Verification code:

Aquí con ssh:

$ ssh rodolfo@linuxbox
Password:
Verification code:
Last login: Wed May 6 17:10:16 CDT 2015 from r167-anteldata.net.uy on ssh:notty
Last login: Wed May 6 17:09:04 2015 from 167.60.140.132
[rodolfo@linuxbox ~]$

El sitio de XModulo tiene un buen conjunto de tutoriales sobre la instalación y configuración de google-authenticator y más información también está disponible buscando un poco.

Administración de llaves SSH para aplicaciones

Las llaves de SSH permiten, por defecto validar la conexión al destino y cifrar el tráfico entre el cliente y el servidor. Con algo de configuración es posible validar el orígen contra el servidor y de esa forma en lugar de conocer la clave para acceder, la validación es por certificados. Cuando empezamos a utilizar aplicaciones y a automatizar los accesos aparecen los compromisos de seguridad, esta presentación aborda las configuraciones básicas para la administración de las llaves SSH cuando se usan para otorgar accesos a las aplicaciones.

Público objetivo: Casi cualquiera que utilice SSH para vincularse con servidores, equipos y aplicaciones remotas.

Requisitos: Conocimientos de SSH o haberlo utilizado como cliente.

Presentación realizada en:

  • 15 nov 2014 – Techmeetup 2014 – (Meetup Space) – Torre de las Comunicaciones, Montevideo, Uruguay

Receta de Tunel para llegar a tu computador

A casi todos que trabajamos en tecnologías de la información nos ha pasado tener alguna vez la necesidad de que, ya sea un compañero, un gerente, un cliente, o alguien más, acceda a nuestra computadora y nos hemos encontrado con problemas de todo tipo, desde que estamos detrás de un firewall en una red privada, nuestra aplicación está en una máquina virtual, nuestro tráfico es solo saliente mediante proxy, etc. etc.

Muchos utilizan algunas herramientas que permiten dar algun acceso, aunque más no sea a compartir la pantalla, tal vez por Google Hangout, mediante Skype, ScreenHero, Team Viewer o con soluciones más optimas como NGrok.

Esta presentación, en formato ligthning talk de 5 minutos, es una receta para construir un tunel, solamente disponiendo de cualquier máquina accesible con Linux, utilizando SSH, y permitiendo abrir un canal que al conectarse a él se accede hasta nuestra máquina o aplicación local.

Público objetivo: Está pensado para cualquier persona que tenga problemas con compartir una aplicación con personas remotas.

Requisitos: Ganas de divertirse

Ligthning talk presentada en:

  • 15 nov 2014 – Techmeetup 2014 – Torre de las Comunicaciones, Montevideo, Uruguay

Raspberry Pi Model B+

Hoy recibí y puse a funcionar mi nueva Raspberry Pi Model B+

La «cajita» que puse se trata de un tupper que compré por la suma de $ 10 (aprox. US$ 0.41) en el supermercado y corté prolijamente con la tijera de la Victorinox

La verdad que ha sido un acierto la idea de poner todos los puertos hacia el mismo lado.  La última foto muestra el lugar donde quedará en «producción»:  arriba de un ropero.

Instalación

Luego de copiar con el comando dd el archivo con la imagen del sistema Respbian a la tarjeta MicroSD, en un netbook que tiene bahía de SDCard; simplemente la conecté a la red y le di corriente, viendo cómo las luces parpadeaban como booteando.

Procedí a hacer un escaneo de hosts con el comando nmap y ahí estaba el Raspberry PI booteado y esperando que me conectara por SSH:

nmap-ssh

y luego ejecutar el comando raspi-config como root para entrar a una interfaz de configuración que ayuda terminar la configuración.

Captura de pantalla 2014-10-07 a las 6.47.33 PM

Con unos ajustes más, como colocarle una IP en el DHCP de mi router para que esté en el rango de mis «servidores» y montar un pendrive en el /etc/fstab quedé pronto para configurar el servidor transmision como describe mi artículo anterior.

Realmente muy simple este procedimiento de instalación.

Información adicional

Sugiero consultar el artículo de Hussam Al-Hertani titulado «Installing Raspbian on the Raspberry Pi & using SSH and VNC to remotely connect to the Raspberry Pi», que indica los pasos en particular para instalar y algunas configuraciones adicionales que pueden ser de interés.

Copiando archivos de un servidor remoto a otro con SCP

Muchas veces me he visto pasando datos de un servidor remoto a otro, ya sea moviendo un sitio web, un dump de base de datos o un maildir con correos. Generalmente utilizo scp (Secure Copy) o rsync sobre ssh para conectar server_origen con server_destino.

Pero qué pasa si un server no se ve con otro; o solo quiero ejecutar comandos en mi host local. En esos casos, descargo los datos a mi host local y los subo al servidor de destino. Pero lo ideal sería conectar a ambos servidores y que el comando ejecute de una sola vez. Sería como (que no funciona para estos casos):

$ scp  server_origen:archivo.tgz  server_destino:archivo.tgz

El problema radica en que la copia se quiere iniciar (obviamente) desde server_origen y éste no tiene la configuración requerida para conectarse a server_destino. Puede verse claramente invocando con -v el scp:

$ scp  -v  server_origen:archivo.tgz  server_destino:
...
Executing: program /usr/bin/ssh host server_destino, user (unspecified), command scp -v -d -t --
...

A veces, con un poco de configuración se puede salvar este problema y lograr el propósito deseado: que los archivos de server_origen lleguen a server_destino, pero no quiero hacer esas configuraciones, quiero algo que esté disponible para mi linea de comando en mi host local de la forma más simple posible.

1. stdOUT – stdIN

Entonces ejecutar una salida estándar en server_orgien que se guarda en un archivo en server_destino, es una solución simple que lo hace:

$ ssh server_origen 'cat archivo.tgz' | ssh server_destino 'cat > archivo.tgz'

los datos terminan pasando dos veces por el ancho de banda al host local, pero no se ocupa el disco local.

2. SCP con parámetros

Claro que si se se puede conectar un servidor con otro, se pude ejecutar pasando los parámetros necesarios para el scp entre uno y otro:

$ ssh server_origen 'scp -Ppuerto archivo.tgz usuario@server_destino:' 

3. Túnel para aplicaciones

Llegado al caso raro que un servidor remoto no se vea con otro, o que se levante un servicio en 127.0.0.1 de server_destino (mysql o rsync) se puede armar un túnel a través del host local para pasar los datos:

 
$ ssh -R 5001:127.0.0.1:5002 server_origen
$ ssh -L 5002:127.0.0.1:3306 server_remoto

y en este ejemplo, ejecutar directamente el comando mysql en server_origen para que conecte con el mysql del server destino:

$ ssh server_origen 'mysql -P5001 -uroot -p base-datos-server_destino < base-datos-server_origen.sql'

En los comandos que se ejecutan en el host local permiten a través del puerto 5001 abierto en server_origen conectar con 127.0.0.1:3306 de server_remoto y cargar el dump de la base de datos.

Automatizar proceso en screen

Uno de mis programas favoritos para administrar servidores es screen pues permite multiplexar una terminal como si fuera varias terminales (ventanas de comandos); es decir que luego de establecer una conección al servidor (mediante SSH) se pueden poner a correr varios programas como si se tuviera varias conexiones establecidas a la vez.

Además se puede salir y desconectarse del servidor, dejando corriendo cada uno de esos programas.  Al volver a conectarse se pueden re-tomar esas terminales que se dejaron abiertas. Sería como poner a correr un programa en un PC y apagar el monitor que se enciende al día siguiente; esto hace screen, cuando se desconecta y se vuelve a conectar a los servidores remotos (en la nube).

Generalmente conecto por SSH e invoco screen, dentro del cual pongo a correr lo que necesito; pero me surgió la necesidad auotmatizar (sin mi intervención) todo para actuar en varios servidores y aquí describo como lo he hecho.

Se puede invocar screen con el programa a correr y quedar desvinculado (deattached) de la terminal screen, invocándolo de esta forma:

screen -dmS prueba watch ls -al
  • -d hace que screen se invoque en forma desvinculada, es como escribir «C-a d» dentro de screen
  • -m hace que screen ignore si hay otro screen corriendo
  • -S prueba es el nombre de la sesión de screen, que luego puede ser usado para gestionar la misma en forma automatizada

ahora solo hay que llamarlo en una sesión ssh:

ssh -p222 -i ~/.ssh/cert1 rodolfo@server.remoto screen -dmS prueba watch ls -al

(los parámetros de la sesión ssh son ejemplo y deben adaptarse al caso particular)

Luego de ejecutar esto se obtiene nuevamente el prompt local ($), pero ha quedado corriendo una sesión screen en el servidor remoto que está ejecutado el watch ls -al, veámoslo:

$ ssh -p222 -i ~/.ssh/cert1 rodolfo@server.remoto screen -ls
There is a screen on:
	24411.prueba	(00/22/2113 33:44:55 PM)	(Detached)
1 Socket in /var/run/screen/S-root.
$
$ ssh -p222 -i ~/.ssh/cert1 rodolfo@server.remoto ps ax | grep -i screen
24411 ?        Ss     0:00 /usr/bin/SCREEN -dmS prueba watch ls -al

para apagarlo, también remotamente, se puede enviar la señal TERM al PID remoto:

ssh -p222 -i ~/.ssh/cert1 rodolfo@server.remoto 'kill $(screen -ls | grep prueba | cut -d. -f1)'

para los screen de nuestra sesión prueba. Si se quieren apagar todos los screen, se puede invocar más fácilmente asi:

ssh -p222 -i ~/.ssh/cert1 rodolfo@server.remoto 'kill $(pidof SCREEN)'

Mi requerimiento en varios servidores, me llevó a armar un pequeño script que recibe por parámetros start/stop y devuelve la lista de screen corriendo:

#!/bin/bash
# ejecuta screen remotos en los SERVERS

SERVERS="server1 server2 server3 server4 server5"

case $1 in
start) for i in $SERVERS; do
       ssh -p222 -i ~/.ssh/cert1 rodolfo@$i screen -dmS prueba watch ls -al
       done ;;
stop)  for i in $SERVERS; do
       ssh $i 'kill $(pidof SCREEN)'
       done ;;
*)     typeset -i a=1
       for i in $SERVERS; do
          echo "$a ==== $i"
          ssh $i '/usr/bin/screen -list | grep Detached'
          a=$a+1
       done ;;
esac

exit 0

Raspberry Pi como cliente torrent

Hace ya tiempo pre-compré un Raspberry Pi, tuve mi plazo de espera (como de 3 meses) y lo recibí hace casi 6 meses atrás en casa; pero desde aquel momento no me hice un tiempo para atender a este hermoso aparatito. Pero esta semana comencé a armarlo en forma decidida hasta crear un cliente Bittorrent y podes descargar archivos y compartirlos.

En este artículo describo brevemente cómo lo hice.

2013-03-09-20.40.45

Instalación

Luego de tener arrancado y configurado en la red el Raspberry Pi con Raspbian procedí a instalar transmission-daemon que fue lo que encontré más adecuado luego de analizar un poco otras opciones como uTorrent

apt-get install transmission-daemon

Crear los directorios necesarios para transmission-daemon donde esté montado el disco externo, en este caso /data (que lo coloco en el /etc/fstab para que lo monte siempre):

cd /data
mkdir torrent
cd torrent
mkdir info finish temp
chown debian-transmission info finish temp

Editar archivo de configuración /etc/transmission-daemon/settings.json y cambiar

«download-dir»: «/data/torrent/finish»,

«incomplete-dir»: «/data/torrent/temp»,
«incomplete-dir-enabled»: true,

editar archivo de daemon /etc/default/transmission-daemon y cambiar

CONFIG_DIR=»/data/torrent/info»

reiniciar transmission para que cree la estructura por defecto en /data/torrent/info

/etc/init.d/transmission-daemon restart

detener transmisión:

/etc/init.d/transmission-daemon stop

Crear un symlink del archivo creado al /data/torrent/info

cd /data/torrent/info
rm settings.json
ln -s /etc/transmission-daemon/settings.json

Nota: Si se arma al revés, dejando en /etc/transmission-daemon un symlink hacia el archivo original en /data/torrent/info el sistema lo sobre-escribirá cada vez con información por defecto (parece ser algo hardcoded).

Iniciar transmisión nuevamente

/etc/init.d/transmission-daemon start

Conectar la interfaz web (tunel ssh)

Transmission-daemon quedará esperando conexiones en el puerto definido en rpc-port del archivo /etc/transmission-daemon/settings.json, por defecto el 9091; así que http://IP-RaspberryPi:9091 me conectará con la interfaz de administración de transmission.

Conectar desde internet requiere abrir los puertos y redirigirlos a al Raspberry Pi. Se podría hacer con el puerto 9091, pero la seguridad estaría basada en la validación de transmission, así que preferí reenviar el puerto 22 y armar cada vez un tunel con el servicio SSH.

ssh -p22 -L 9091:localhost:9091 pi@micasa.dyndns.org

y conecto con el navegador desde cualquier lugar de internet a http://localhost:9091 para acceder a la consola de administración que me pedirá primero usuario/clave de transmission.

Descargar archivos del disco externo a mi notebook

Algunos documentos en la web sugieren utilizar ownCloud para bajar los archivos desde el Raspberry Pi. Es una solución interesante, pero requiere un servidor web con soporte PHP que van a recargar el Raspberry Pi, y una configuración adicional.

¿Para qué?, si tenemos SSH que es una puerta a la felicidad, entonces con SSHFS dejo disponibles los archivos descargados en mi notebook y los puedo abrir y copiar normalmente como cualquier otro archivo; con la ventaja que no es necesario ningún nuevo servicio o configuración.

Este es el comando que utilizo, para montar en una carpeta bajo mi home que he creado con el nombre RaspberryPi

sshfs -p22 pi@micasa.dyndns.org:/data/torrent/finish RaspberryPi/

Otros documentos en la red

De gran ayuda fue el artículo de Electro titulado «Cliente Torrent con Raspberry Pi», que fue mi guía para toda mi configuración.

También encontré un documento de Jose L. Romero titulado «Raspberry Pi como cliente torrent», que me permitió obtener algunos otros tips para mi configuración original.

Copiar base de datos MySQL de un servidor a otro

Tengo un servidor en producción por allá en la nube y quiero tener otra réplica (asincrónica) de algunas bases de datos MySQL. Buscando la solución más sencilla y rápida llegue a este script que se ejecuta en el servidor de réplica y que trae la base de datos remota y la deja activa en el MySQL local.

ssh shelluser@server.remoto.com «mysqldump -uusuario -pclave123 basedatos | gzip -c1» | gunzip -c | mysql -uroot -ppassword basedatos

Los comandos ente comillas mysqldump -uusuario -pclave123 basedatos | gzip -c1 se ejecutan en el servidor remoto mediante la conexión ssh que debe poder realizar el usuario ‘shelluser’, para sacar por estándar output el dump compactado de la base de datos.

Localmente se recibe por estandar input con los comandos gunzip -c | mysql -uroot -ppassword basedatos, que descomprimen y ejecutan los comandos del dump en el mysql local contra la base de datos que se indica.

El gzip y el gunzip es opcional y lo que busca hacer es comprimir el tráfico que se transfiere mediante SSH, y solo sería necesario si la base que se está bajando es de cierto volumen.