Google+

jueves, 28 de abril de 2016

Certificados SSL gratis





Esta entrada es de Alberto Gonzalez, la cual fue subida a su blog "http://blog.inittab.org" ,pero me parecía muy interesante y la difundo de nuevo con su permiso.

Hoy vengo a contaros que se pueden conseguir certificados SSL válidos en todos los navegadores, y sistemas operativos, por cero Euros. Aunque realmente lo que quiero contar es como ponerlo en marcha rápidamente, que es lo que espero no sepáis para que terminéis de leer esto 🙂

Let’s Encrypt lleva unos meses funcionando y posiblemente para cuando termine de escribir esta entrada ya habrán generado más de dos millones de certificados. Su objetivo no es acabar con la mafia y el timo de (la mayoría de) los certificados SSL de pago. Su propósito es el que tráfico de Internet viaje cifrado, para que al menos les cueste algo más de presupuesto espiarnos a todos aquellos que lo hacen.

No voy a entrar en detalle sobre el protocolo que desarrollaron (ACME), sólo comentaré las piezas que necesitamos conocer y espero que con un poco de copiar y pegar estéis funcionando en minutos.

Software

Existen varias implementaciones del “cliente ACME” necesario para gestionar la petición de certificados. De entre ellos yo elegí acme-tiny porque su código es sencillo de entender y no tiene apenas dependencias, básicamente Python y openssl. En su repositorio de github tenéis sus instrucciones de uso, muy fáciles de seguir, pero si lo queréis algo un poco más fácil he creado un pequeño script en shell, usa acme-tiny para funcionar y sólo requiere como argumento el nombre, o nombres, de dominio para los que solicitar el certificado.
También necesitaremos un servidor web, aunque el certificado SSL sea para un servidor de correo, XMPP, o lo que se os ocurra. Es necesario porque Let’s Encrypt hará una petición a nuestro servidor web para validar que el dominio del certificado solicitado es realmente nuestro. El funcionamiento a grandes rasgos es: El “cliente ACME” solicita un certificado a Let’s Encrypt, estos piden al cliente que ponga un fichero que pruebe que el dominio es nuestro (challenge) en el servidor web y posteriormente Let’s Encrypt pide al servidor web del dominio en cuestión el fichero acordado. Si el fichero está allí y es correcto, se entiende que el dominio está bajo nuestro control y el certificado se emite.

Configuración

Lo primero que necesitaremos (además de tener acme-tiny  (enlace para “wget-ear”) y opcionalmente mi script (enlace para “wget-ear”)) es un directorio para guardar claves privadas y certificados. Para no ejecutar acme_tiny como root crearemos ese directorio con permisos de escritura para un usuario no privilegiado (no es buena idea usar alguno bajo el que se ejecute Apache/nginx o algún servicio), podemos usar nuestro propio usuario (en mi caso será “agi“). Ya que, en Debian, tenemos los directorios /etc/ssl/(private|certs), yo elegí /etc/ssl/letsencrypt:

# mkdir /etc/ssl/letsencrypt
# chown agi:ssl-cert /etc/ssl/letsencrypt
# chmod 750 /etc/ssl/letsencrypt

Bajaremos el certificado intermedio de Let’s Encrypt para que no de problemas la cadena de validación de nuestro certificado SSL. Lo dejaremos en el directorio creado:

# cd /etc/ssl/letsencrypt
# wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem

Crearemos una clave privada para establecer la comunicación con Let’s Encrypt:

# cd /etc/ssl/letsencrypt
# openssl genrsa 4096 > account.key
# chmod 600 account.key
# chown ago account.key

Ahora crearemos el directorio donde el “cliente ACME ” dejará los ficheros de validación (challenge) y que el servidor web tendrá que devolver cuando Let’s Encrypt lo solicite:

# mkdir /var/www/letsencryptchallenges
# chown agi /var/www/letsencryptchallenges

Y configuraremos el servidor web para que sirva el contenido de ese directorio. Si tenemos un sólo dominio lo podemos hacer en la configuración es éste, y si tenemos varios configurar el directorio de forma global. A forma de ejemplo, esta sería la configuración para un servidor Apache:

Alias /.well-known/acme-challenge/ /var/www/letsencryptchallenges/
<Directory /var/www/letsencryptchallenges>
  Options None
  AllowOverride None
  Order allow,deny
  Allow from all
</Directory>

Y esta para un servidor nginx:

location /.well-known/acme-challenge/ {
  alias /var/www/letsencryptchallenges/;
  try_files $uri =404;
}

Llegado este punto, si no vas a usar mi script deberías seguir las instrucciones de acme-tiny para crear un CSR (Petición de firma de certificado), instalar el certificado y programar una tarea periódica que lo renueve.
Si vas a usar mi script deberías repasar las variables de configuración que tiene al principio para ajustar los ficheros y directorios que usará (los comentados anteriormente). Si estás siguiendo literalmente los pasos que llevamos hasta ahora posiblemente sólo tendrás que cambiar el path al script acme_tiny.py (apuntar la variable ACME_TINY al path donde lo dejaras y no olvidar dar permisos de ejecución a ambos). Si ya has recargado la configuración del servidor web, para que se sirva correctamente el directorio de los ficheros challenge, sólo queda una cosa que hacer, pedir el nuevo certificado:

## Ejecutar con el usuario no privilegiado, no como root!
## Lo más sencillo es dejar new_cert en el PATH (p.e. /usr/local/bin)

$ new_cert midominio.com

## Si queremos un certificado para varios (sub)dominios podemos pasar todos
## como argumentos al script.
## IMPORTANTE: En este caso, asegúrate de que el servidor web devolverá
## el fichero challenge correctamente en todos ellos
$ new_cert midominio.com www.midominio.com eldominiodemiprimo.com

Si todo fue bien, deberíamos tener varios ficheros, que toman su nombre del primer dominio especificado en la llamada a new_cert, en el directorio de trabajo que usemos. Los importantes son: DOMINIO.key, la clave privada, y DOMINIO_chained.crt, el certificado solicitado con el certificado intermedio de Let’s Encrypt. Con ellos tendremos que configurar el virtual HTTPS de nuestros dominios. Ejemplo en Apache:

<VirtualHost *:443>
  ServerName DOMINIO
  SSLEngine on
  SSLCertificateFile /etc/ssl/letsencrypt/DOMINIO_chained.crt
  SSLCertificateKeyFile /etc/ssl/letsencrypt/DOMINIO.key
......
</VirtualHost>

Ejemplo en nginx:

server {
  listen 443;
  server_name DOMINIO;
  ssl on;
  ssl_certificate /etc/ssl/letsencrypt/DOMINIO_chained.crt;
  ssl_certificate_key /etc/ssl/letsencrypt/DOMINIO.key;
...
}

Existen varios parámetros (tanto en los servidores web mencionados como en otro tipo de servidores) para mejorar la seguridad y compatibilidad SSL. En el sitio github de acme_tiny mencionan algunos (para deshabilitar SSLv3 e inferiores y corregir posibles ataques conocidos), aunque yo soy fan de la herramienta de análisis (y  recomendaciones) de Qualys SSL Labs. Así que no os quedéis en instalar el certificado y darle un repaso a parametrización del SSL.

Mantenimiento

Los certificados de Let’s Encrypt, al menos en el momento que escribo estas líneas, tienen una vigencia de tres meses. Por ello es importante que preparemos un mecanismo automático de renovación. Que consiste en algo tan simple como una entrada de cron que solicite un nuevo certificado antes de que caduque el actual. En mi caso tengo un fichero en /etc/cron.d llamado local-letsencrypt (el prefijo local- me permite diferenciar los ficheros instalados por el gestor de paquetes de los creados por mi) con el siguiente contenido (y donde digo nginx, digo apache2, postfix, prosody, dovecot, …):
# Ajustar el nombre de usuario, el path a new_cert y el comando para recargar
# la configuración del servidor correspondiente (salvo que uséis nginx y systemd)
0 6 1 * * agi /usr/local/bin/new_cert DOMINIO(s) && sudo systemctl reload nginx

# Y no olvidéis permitir a vuestro usuario ejecutar ese comando con sudo en
# el /etc/sudoers:
agi ALL=NOPASSWD: /bin/systemctl reload nginx

## O sin depender de sudo (recomendación de Tincho):
0 6 1 * * root su -u agi -c "/usr/local/bin/new_cert DOMINIO(s)" && systemctl reload nginx

Cuidado con las cosas gratis

Para los que no se fían de las cosas gratis, les recomiendo que sigan los pasos anteriormente descritos y luego envíen 200 EUR a mi cuenta de Paypal. Una vez al año, por la renovación, claro. Les garantizo que sus  datos viajarán cifrados igualmente que con el certificado más caro de [insertar entidad certificadora aquí].

$ exit

miércoles, 27 de abril de 2016

¿Qué puede hacer EXPECT por ti?


Buenos días a tod@s!

El otro día vi un post que me gustó bastante, sobre cómo hacer backup de los diferentes elementos de red físicos (Firewall, Switches, Cabinas de almacenamiento, etc…)

Seguramente si tiene administración web podremos hacer una copia sin ningún problema. Pero si queremos automatizar la tarea, usaremos el acceso CLI, en el siguiente ejemplo, nuestras “victimas” serán unos switches CISCO, colocados en diferentes plantas de un edificio.

Vamos a por ello!!!!!!!

Lo primero que necesitamos es un servidor tftp donde subir nuestras copias, en nuestro servidor, deberemos crear un usuario que tenga permisos de escritura para poder subir los archivos, por supuesto tiene que tener conectividad con las máquinas que queramos copiar.
Existen muchos clientes gratuitos y muy fáciles de instalar.

Cuando tengamos esto, necesitaremos una máquina Linux y a nuestro gran amigo EXPECT.

¿Cómo funciona? 

Facil, lo que hay que poner es el comando que esperas recibir en la consola y el que tu teclearías, no os preocupéis, dejo comentado el script para que podáis identificar cómo se hace.

Lo primero será entrar en cada una de nuestras máquinas e introducir nuestro usuario y password, recordad que los hemos debido crear antes.

Introducimos el usuario 


Router(config)# ip ftp username javi


Introducimos la password


Router(config)# ip ftp password linuxtargz


Ahora nuestro switch guardará nuestras credenciales. Sólo nos falta crear nuestro script.




El código será el siguiente:

#!/usr/bin/expect
spawn  date +%u 
expect -re "."
set hoy $expect_out(buffer) >> guardamos la variable "hoy" como nuestra fecha 

spawn /usr/bin/telnet 10.0.1.6 >>nos conectamos a la máquina que queremos copiar, en este caso por telnet

expect "Username: " >> Nos pide el usuario
send "usuario\n"       >> Introducimos el usuario que esperaría recibir e introducimos un retorno de carro.

expect "Password: "
send "CiscoSwitch3p\n"

expect "PilaCore_planta3>"
send "enable\n"

expect "Password: "
send "P@ssw0rd12\n"

expect "PilaCore_Planta3#"
send "copy running-config ftp \n"

expect -re "Address or name of remote host .. "
send "172.22.14.73\n"

expect -re "Destination filename .pilacore_plta5a-confg.. "
send "switch_planta3-$hoy\n"      >> Aquí enviamos la fecha que tenemos en nuestra variable

expect "PilaCore_Planta3#"

close


**** Para que podáis ver qué funciona en todos los entornos os dejo también el script que copia varias switches brocade***

#!/usr/bin/expect
spawn  date +%u
expect -re "."
set hoy $expect_out(buffer)

set switches [list 172.22.2.21 172.22.2.22 172.22.2.27 172.22.2.29]
foreach switch $switches {

spawn /usr/bin/telnet $switch

expect "Enter password: "
send "admin\n"

expect ">> Main# "
send  "cfg/\n"

expect ">> Configuration# "
send "ptcfg/\n"

expect "Enter hostname or IP address of FTP/TFTP server: "
send "172.22.14.73\n"

expect "Enter name of file on FTP/TFTP server: "
send "$switch-$hoy\n"

expect "Enter username for FTP server or hit return for TFTP server: "
send "javi\n"

expect "Enter password for username on FTP server: "
send "linuxtargz\n"

expect ">> Configuration# "

close

}




Ahora solo os faltaría dar permisos de ejecución al script que acabáis de crear. 

¿Cómo hacemos eso? 

Con "chmod 644 archivo"


Este script podríamos programarlo con un "cron" y hacer que se ejecutara una vez al día a la hora que queramos. 

La copia se guardará con la fecha del día en el que se hizo.

Espero que os haya resultado útil.

Un saludo amig@s!