viernes, julio 03, 2015

GoAccess para el análisis de logs Apache desde la terminal

Recientemente estaba peleando con los archivos de log de uno de mis servidores web teniendo que explorarlos a mano ya que no tenía muchas ganas de instalar ningún analizador tipo AWstats o similar. 

Buscando alguna solución de terminal me he encontrado con GoAccess. Una herramienta que permite explorar los logs de apache o Nginx en tiempo real y desde la terminal. Es especialmente útil si lo que queremos es dar un vistazo rápido al estado de nuestro servidor conectando por ssh y ver las principales estadísticas de páginas servidas, visitantes, errores, ancho de banda, etc.

 

Tan sencillo como instalarlo mediante apt-get...

$sudo apt-get install goaccess

...y cargando el fichero que queremos analizar...

$goaccess -f /var/log/apache2/access.log -a

Ten en cuenta que, dependiendo de tu configuración, es posible que necesites tener permisos de root para poder acceder al archivo de log. 

Puedes usar directamente el ratón o las flechas para recorrer el informe. Con el tabulador vas pasando por lo distintos paneles y con ENTER/Q vas ampliando o reduciendo la información que muestra cada panel. Con S puedes desplegar las opciones de cada panel. Tienes un listado completo de las instrucciones en la página del manual o directamente en la web.

Otro aspecto interesante es que puede cargar múltiples archivos de log al mismo tiempo:

$zcat -f /var/log/apache2/*log | goaccess

¡Incluso los gz si queremos!

$zcat -f /var/log/apache2/*log* | goaccess

O todos a la vez...

Y lo que me parece más alucinante, no necesitas ni tenerlo instalado en tu servidor, puedes rescatar tus logs por ssh y analizarlos en tu propia máquina

ssh root@server 'cat /var/log/apache2/access.log' | goaccess -a

Goaccess permite incuso generar informes en html, json o csv si es lo que prefieres. En la misma página del manual lo tienes. 

En definitiva es una herramienta sencilla y rápida con un bajo consumo de recursos que permite hacer análisis de logs sin tener que instalar ni configurar ningún software web. 


martes, febrero 17, 2015

Postfix - Configurando un servidor de correo en debian / raspberry pi

La mayor parte de las instrucciones de este artículo están extraídas del magnífico artículo de Sam Hobbs y que forma parte de una serie más completa de instalar un servidor de correo completo con servidor web etc.

Requerimientos

En mi caso sólo pretendo configurar mi Rasberry Pi para que sea capaz de enviar correos electrónicos y recibir algunos correos electrónicos en las cuentas de usuario o reenviarlos a cuentas exteriores. ¿no me explico bien? A ver si así:
  • Quiero poder enviar correos electrónicos desde las cuentas de usuario (como "pi") y desde algunas programas como el fail2ban o el php.
  • Los correos que se reciban para ciertos usuarios (como "pi") estarán disponibles al loguearse por ssh.
  • Quiero que existan ciertas direcciones virtuales (como gonzalo@zoogon.net) que cuando reciban correo lo reenvíen directamente a mi cuenta de gmail.
  • Las cuentas de correo NO serán accesibles por pop3 ni imap, para eso hace falta más software. Accederé directamente desde la línea de comandos.
  • Quiero que la instalación esté protegida para que nadie pueda hacer envíos de correo desde este servidor.

Prerrequisitos

Debes disponer de un dominio propio. En mi caso lo he contratado con NameCheap y las pantallas de configuración que mostraré serán las de ellos. Otros servicios de dominio deberían servirte igual mientras te permitan crear subdominios y especificar si los registros son tipo A, txt y registros MX (date una vuelta por este artículo si no sabes de lo que estoy hablando)

Lo normal sería que tu Raspberry Pi esté configurada con una ip fija detrás de un router. Asegúrate de que tienes redirigido el puerto 25 del router a la RPi. Si además tu ip externa es dinámica (lo que sería normal) puedes utilizar el cliente ddclient para mantener tus registros DNS actualizados (ejemplo con namecheap y raspberry pi)

Con sudo hostname nombre-maquina.dominio.com establece el nombre de tu máquina. (debe ser completo o fqn) Deberías verlo actualizado en /etc/hostname

$ cat /etc/hostname 
rpi.midominio.net

Preparando los dominios

En tu registrador de DNS tiene que ofrecerte la posibilidad de configurar a qué servidores mail tiene que vincular los correo midominio.net. En mi configuración puedes ver que tengo definidos dos subdominios rpi y mail del tipo A (que corresponden con una dirección). En realidad, para mi caso ambos dominios están vinculados a la misma máquina pero lo he preparado por si quisiera instalar un segundo servidor de correo para backup.

El registro de subdominio @ con los valores de v=spf1 mx a ~all del tipo TXT Record es importante porque muchos servidores de correo no reconocerán el nuestro como válido si no lo incluimos.

En la parte de definir los servidores de correo lo que estoy indicando con la @ es que para cualquier correo que llegue a mis direcciones debe redirigir el mensaje a mail.midominio.net y en caso de no encontrarlo lo debe hacer  rpi.midominio.net. El valor MX PREF indica la prioridad a la hora de seleccionarlos.

En el artículo de Sam sobre configurar correctamente un DNS tienes unas buenas explicaciones de qué significa cada cosa.

Instalando y configurando postfix

Voy a ir rápido en muchas de las instrucciones.  Te recomiendo que le des un vistazo al artículo que menciono al principio del post si quieres profundizar. La única diferencia es que yo no he llegado a instalar dovecot para acceder por pop3 e imap.

Comienza instalando postfix y las herramientas de mail

$sudo apt-get update && sudo apt-get install postfix mailutils

Te preguntará que tipo de servicio deseas instalar, le decimos que "sitio en internet". Si hemos configurado el hostname correctamente lo cogerá. Tendrás algunos warnings referentes a ipv6, no te preocupes enseguida lo solucionaremos.

Editar /etc/postfix/main.cf y añade lo siguiente al final del archivo

#usar sólo el protoclo ipv4, evitamos mensajes de warning
inet_protocols = ipv4

#establecemos restricciones para que no cualquiera se pueda 
#conectar a nuestra máquina y hacer envíos a direcciones 
#de correo externas
smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_unauth_destination

#establecemos unas restricciones en el saludo a la máquina
smtpd_helo_required = yes
smtpd_helo_restrictions =
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname,
        reject_unknown_helo_hostname
        check_helo_access hash:/etc/postfix/helo_access

virtual_alias_maps = hash:/etc/postfix/virtual

Puedes ver referencias a dos archivos que vamos a crear. El primero /etc/postfix/helo_access sirve para spammers que pretendan hacerse pasar por nuestras máquinas.  Debería contener los dominios que tenemos registrados para el correo, en mi caso:

midominio.net          REJECT          Get lost - you're lying about who you are
mail.midominio.net     REJECT          Get lost - you're lying about who you are
rpi.midominio.net      REJECT          Get lost - you're lying about who you are

El segundo contendrá los mapeos de direcciones virtuales que queremos introducir

webadmin@midominio.net mi-correo-en@gmail.com
rpi@midominio.net       pi

Esto significa que cualquier correo que llegue a webadmin@midominio.net saldrá rebotado a mi cuenta de gmail. Cualquier correo que llegue a nombre de rpi@midominio.net se dirigirá a la bandeja de entrada del usuario "pi". Cualquier otro correo entrante será rechazado.

Ha llegado el momento de arrancar definitivamente postfix. Mapeamos ambos archivo virtuales y reiniciamos el servicio.

$sudo postmap /etc/postfix/virtual
$sudo postmap /etc/postfix/helo_access
$sudo service postfix restart

No deberías ver ningún mensaje de error.

Probando el servicio de envío

Antes de nada saber dónde debemos buscar los mensajes de error y log. Prepárate para lanzar los siguientes comandos 

$cat /var/log/mail.log
$cat /var/log/mail.err

En esos logs encontramos la información de los problemas así como los eventos que suceden en postfix: intentos de conexión, correos enviados y recibidos, etc. Estos archivos rotan frecuentemente y podemos verlos ampliados con mail.log.1, mail.log.2...

Empezamos por lo básico e intentamos enviar directamente un mensaje a nuestra cuenta de gmail. Cada línea se introduce por separado:

$ mail mi-cuenta@gmail.com
Cc: 
Subject: mensaje de prueba de postfix
estas son las líneas de contenido del mensaje para acabarlo y enviar pulsa Ctrl+D
$

El comando acaba sin que aparentemente pase nada pero internamente mail se configura con postfix que inserta el mensaje en su cola de salida e inicia el proceso de comunicación con los servidores de gmail para enviar el mensaje. Poco segundos después deberías ver el mensaje en tu bandeja de entrada aunque es muy probable que haya ido a parar a tu bandeja de spam, si es así ábrelo e indica que no es spam para que acepte futuros mensajes.

Puedes comprobar el proceso de comunicación en el mail.log y las últimas líneas deberían ser algo así.

Feb 17 18:27:21 rpi postfix/pickup[7381]: C64EB42481: uid=1000 from=
Feb 17 18:27:21 rpi postfix/cleanup[7395]: C64EB42481: message-id=<20150217172721 .c64eb42481="" rpi.midominio.net="">
Feb 17 18:27:21 rpi postfix/qmgr[7382]: C64EB42481: from=, size=432, nrcpt=1 (queue active)
Feb 17 18:27:22 rpi postfix/smtp[7397]: C64EB42481: to=, relay=gmail-smtp-in.l.google.com[74.125.140.27]:25, delay=0.89, delays=0.18/0.06/0.42/0.22, dsn=2.0.0, status=sent (250 2.0.0 OK 1424194042 ca16si30265556wib.105 - gsmtp)
Feb 17 18:27:22 rpi postfix/qmgr[7382]: C64EB42481: removed
   
Si el mensaje parece que se ha enviado correctamente pero no llega deberías comprobar el mail.log. A mi me ha llegado a pasar que algún servidor de correo tenía mi IP (dinámica) marcada como generadora de spam. Bastón con acceder al mail.log, comprobar por qué me habían rechazado el correo y acceder a un formulario web para solicitar que la volvieran a habilitar como aceptable.

Probando la recepción de correo
Ahora tocaría recorrer el camino inverso. Hay una dirección de correo que corresponde a un usuario de mi sistema pi@rpi.midominio.net. Desde gmail escribo un mensaje a la misma y uno segundos después acceso por ssh de nuevo a la rpi para comprobar que ha llegado y...

$ ssh pi@rpi.midominio.net
Linux rpi.midominio.net 3.18.7+ #755 PREEMPT Thu Feb 12 17:14:31 GMT 2015 armv6l
[...]
You have new mail.
pi@rpi ~ $

Lo puedes leer usando el mismo comando mail y pulsando 1

$ mail
"/var/mail/pi": 1 mensaje 1 nuevo
>N   1 Gonzalo Cao Cabeza mar feb 17 18:41  44/1923  mensaje de vuelta
? 1
Return-Path:
X-Original-To: pi@rpi.midominio.net
Delivered-To: pi@rpi.midominio.net
Received: from mail-wg0-f51.google.com (mail-wg0-f51.google.com [74.125.82.51])
by rpi.midominio.net (Postfix) with ESMTPS id ABA6342480
for ; Tue, 17 Feb 2015 18:41:02 +0100 (CET)
Received: by mail-wg0-f51.google.com with SMTP id y19so37464344wgg.10
        for ; Tue, 17 Feb 
[...]

Si examinas el mail.log encontraras unas líneas similares a cuando enviaste el correo.

Nos quedan probar las direcciones que hemos virtualizado. Sólo sirven para recibir correo: en el caso de pi@midominio.net la deberíamos recibir en la misma cuenta del caso anterior y para la cuenta webadmin@midominio.net debería recibirla directamente en mi cuenta de correo de gmail.

Asegurando nuestro servidor

Como ya tengo instalado fail2ban lo único que he tenido que hacer es ampliar los jail activados. Edito el /etc/fail2ban/jail.conf y realizo el siguiente cambio

[postfix]
enabled  = true
port     = smtp,ssmtp
filter   = postfix
logpath  = /var/log/mail.log

Con un simple comando podemos observar si fail2ban ha detectado algún comportamiento extraño.

$ sudo fail2ban-client status postfix
Status for the jail: postfix
|- filter
|  |- File list: /var/log/mail.log 
|  |- Currently failed: 0
|  `- Total failed: 0
`- action
   |- Currently banned: 0
   |  `- IP list:
   `- Total banned: 0


miércoles, febrero 11, 2015

Protegiendo el servidor SSH con fail2ban

Configurando fail2ban

Dados los repetidos ataques de fuerza bruta que estoy sufriendo al puerto SSH de mi raspberry pi por parte de ciertas ips desde china he revisado algunos sistemas de protección adicional además de los que ya implementé en su día.

De entre ellos el método más sencillo y que me está resultado más divertido en la instalacion de fail2ban. Este software revisa los logs de diversos servicios autentificados (ssh, apache, smtp...) buscando ataques de fuerza bruta y bloqueando las ips hostiles mediante la introducción de reglas en el iptables. Se pueden seleccionar los servicios que se quieren examinar (fails) y determinar las políticas (o acciones) que se que quieren emprender.

Pero vamos directamente al tema. La instalación básica ya nos servirá:

$sudo apt-get update
$sudo apt-get install fail2ban

Como siempre los ficheros de configuración están en /etc, vamos a darle un vistazo a /etc/fail2ban/jail.conf buscando concretamente estas dos secciones

...
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8
bantime  = 60000
maxretry = 3

...
[ssh]

enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6

En negrita he marcado las partes que más interesan. Puedes ver que he fijado que la acción por defecto es bannear durante 1 hora, que salta al tercer error detectado y lo he activado para el servicio ssh. Salvo el tiempo de baneo todas las demás opciones estaban fijadas por defecto y el servicio ya está en marcha. Si haces cambios en la configuración recuerda reiniciarlo con sudo service fail2ban restart.

Pasado un tiempo podrás ver qué está haciendo examinando el log de fail2ban...

$ cat /var/log/fail2ban.log 
...
2015-02-11 06:52:14,590 fail2ban.server : INFO   Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.6
2015-02-11 06:52:14,602 fail2ban.jail   : INFO   Creating new jail 'ssh'
2015-02-11 06:52:14,665 fail2ban.jail   : INFO   Jail 'ssh' uses Gamin
2015-02-11 06:52:15,011 fail2ban.filter : INFO   Added logfile = /var/log/auth.log
2015-02-11 06:52:15,022 fail2ban.filter : INFO   Set maxRetry = 6
2015-02-11 06:52:15,038 fail2ban.filter : INFO   Set findtime = 600
2015-02-11 06:52:15,047 fail2ban.actions: INFO   Set banTime = 60000
2015-02-11 06:52:15,800 fail2ban.jail   : INFO   Jail 'ssh' started
2015-02-11 08:11:08,505 fail2ban.actions: WARNING [ssh] Ban 183.136.216.4
2015-02-11 10:05:25,417 fail2ban.actions: WARNING [ssh] Ban 183.136.216.3
2015-02-11 11:58:04,950 fail2ban.actions: WARNING [ssh] Ban 115.239.228.9

... o directamente comunicando con el proceso...

$ sudo fail2ban-client status ssh
Status for the jail: ssh
|- filter
|  |- File list: /var/log/auth.log 
|  |- Currently failed: 1
|  `- Total failed: 22
`- action
   |- Currently banned: 3
   |  `- IP list: 183.136.216.4 183.136.216.3 115.239.228.9 
   `- Total banned: 3

Puedes comprobar cómo ha intoducido las reglas en el iptables con

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
fail2ban-ssh  tcp  --  anywhere             anywhere             multiport dports ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain fail2ban-ssh (1 references)
target     prot opt source               destination         
DROP       all  --  115.239.228.9        anywhere            
DROP       all  --  183.136.216.3        anywhere            
DROP       all  --  183.136.216.4        anywhere            
RETURN     all  --  anywhere             anywhere   

Yo me he hecho un pequeño script lllamdo f2b_status.sh para de un sólo vistazo comprobar la última actividad del fail2ban

#!/bin/bash
echo
echo "---------------"
echo "Fail2Ban report"
echo "---------------"
echo
echo "Last 20 lines of fail2ban.log"
echo "-----------------------------"
cat /var/log/fail2ban.log | tail -n 20 
echo
echo "fail2ban service status"
echo "-----------------------" 
sudo fail2ban-client status ssh
echo
exit 0

Cómo crear baneos permanentes a ciertas ips

Lo único malo de los baneos es que se acaban (salvo que pongamos bantime  = -1) y es interesante poder introducir reglas que baneen ips definitivamente. Hay una manera muy sencilla: crear un archivo /etc/fail2ban/ip.blacklist y poner una ip por línea (no añadir un retorno de carro al final del archivo o generará un error)

Después abrimos el fichero de la acción por defecto, que si no lo hemos alterado debería ser /etc/fail2ban/action.d/iptables-multiport.conf, y dejar la acción que ejecuta al inicio "actionstart" como sigue:

actionstart = iptables -N fail2ban-
              iptables -A fail2ban- -j RETURN
              iptables -I -p -m multiport --dports -j fail2ban-
              cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban- 1 -s $IP -j DROP; done

Ahora, cada vez que iniciemos el servicio baneará directamente las ips que encuentre el ip.blacklist. Puedes banear rango enteros, algunos ejemplos:


$ cat /etc/fail2ban/ip.blacklist 
183.136.216.4
183.136.216.3
115.239.228.9
115.239.228.0/24

Baneando IPs permanentemente de forma automática

Si como yo te estás hartando de meter manualmente ciertas ips en el blacklist podemos utilizar otra aproximación al problema. Primero: hacer todos los baneos permanentes con bantime=-1,  ten en cuenta que seguirás necesitando usar ip.blacklist para conservar las ips bloqueadas al reiniciar el servicio. Segundo: hacer que  la acción de banear añada directamente la IP al ip.blacklist.

MUCHO OJO:   si no tienes acceso físico al servidor asegúrate de incluyes alguna ip que tengas controlada en ignoreip, podría darse el caso de que un día te equivoques tres veces con la contraseña ¡y no puedas acceder nunca más!

Vamos al lío, comenzamos cambiando /etc/fail2ban/jail.conf

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8 192.168.0.0/24
bantime  = -1
maxretry = 3

Hemos fijado el bloqueo a permanente y añadido una regla para que ignore los fallos que provengan de la red local. Vamos a cambiar las acciones del /etc/fail2ban/action.d/iptables-multiport.conf, vamos a alterar actionstart y actionban

...

actionstart = iptables -N fail2ban-
              iptables -A fail2ban- -j RETURN
              iptables -I -p -m multiport --dports -j fail2ban-
              cat /etc/fail2ban/ip.blacklist | while read IP; do iptables -I fail2ban- 1 -s $IP -j DROP; done

...

actionban = if ! iptables -C fail2ban- -s -j DROP; then iptables -I fail2ban- 1 -s -j DROP; fi
            # Add offenders to local blacklist, if not already there
            if ! grep -Fxq ',' /etc/fail2ban/ip.blacklist; then echo ',' >> /etc/fail2ban/ip.blacklist; fi

...

Ahora cada vez que banee una ip lo hará de una forma permamente y la incluirá dentro del ip.blacklist. Por el momento si quieres eliminar una IP del blacklist deberás hacerlo manualmente editando el archivo y reiniciando el servicio.

Otra aproximación al problema más avanzada es banear permanentemente sólo aquellas ips que te den problemas de forma reiterada, por ejemplo, aquellas que ya has baneado dos o tres veces. Para eso estás obligado a crear un nuevo jail que, en este caso examine los propios logs del fail2ban buscando las ips hostiles. No estoy seguro de que sea la aproximación más adecuada, introduce más carga de trabajo en el fail2ban y además los hostiles suelen utilizar conjuntos de ips para realizar los ataques con lo cual puedes recibirlos desde varios cientos de IPs. En cualquier caso tienes una buena descripción de la estrategia en este artículo.

viernes, noviembre 21, 2014

Apache2 + PHP + Ubuntu: Configurar carpetas de usuario para ejecutar script php desde el servidor web

Harto siempre de tener que jugar con los permisos para poder editar los archivos en /var/www estuve revisando cómo habilitar un directorio de mi espacio de usuario para hacer desarrollo en PHP.

La cosa tiene algo más de miga de lo que parece, no basta hacer un enlace simbólico o crear directamente un virtualHost porque te dará problemas con los permisos. Al final la solución más rápida que encontré fue usar "a2enmod userdir" que permite crear un directorio "public_html" en todas las carpetas de usuario.

La cosa es tal que así
 $sudo a2enmod userdir  
 $sudo service apache2 restart  
Para activar que apache2 sirva los directorios de usuario. Después creas un directorio en tu carpeta de de usuario llamado public_html y ahí puedes poner un archivo de prueba.
 $cd ~  
 $mkdir public_html  
 $echo "<?php echo 'Hello world' ?>" >> public_html/index.php  
Ahora ya puedes abrir tu navegador e ir a http://localhost/~nombreusuario/ y debería abrirte el index.php y mostrar algo como:
 <?php echo 'Hello world' ?>  
El código php aparece porque de entrada la configuración de PHP está deshabilitada por motivos de seguridad. No es preciso recordar que lo que estamos haciendo es peligroso y únicamente debería hacerse para máquinas de desarrollo que no tengan acceso del exterior.

Para habilitar el php en el directorio de usuario vamos al archivo /etc/apache2/mods-enabled/php5.conf y comentar las siguientes líneas
 #<IfModule mod_userdir.c>  
 #  <Directory /home/*/public_html>  
 #    php_admin_flag engine Off   
 #  </Directory>  
 #</IfModule>  
Reiniciar el servidor apache con
 $sudo service apache2 restart  
...et voilà! Ya ejecutamos scripts php desde nuestra carpeta de usuario.

Convertir nuestra carpeta de usuario en el directorio por defecto

Si lo que queremos es que al visitar http://localhost vaya directamente a nuestra carpeta de usuario hay que cambiar el DocumentRoot de nuestro site. Edita /etc/apache2/sites-available/000-default.conf y cambiamos la línea DocumentRoot por:
 DocumentRoot /home/usuario/public_html  
..y reiniciar de nuevo el servicio
 $sudo service apache2 restart  

viernes, julio 18, 2014

Comparando el contenido de directorios para linux y mac con diff

El otro día estuve probando un par de servicios de sincronización (por cierto, Copy está de lo más interesante). El caso es que antes de borrar los contenidos que teníamos en Dropbox quería asegurarme que se había copiado correctamente todo y tenía que hacerlo necesariamente desde MacOS.

Para comparar el contenido de dos directorios lo más fácil el usar el comando diff, que ya había utilizado anteriormente para comparar el contenido de dos ficheros. Es tan sencillo como abrir una terminal y escribir:

$ diff -rq directorio1 directorio2

Por ejemplo:

$ diff -rq prueba_diff_1/ prueba_diff_2/
Los archivos prueba_diff_1/documento.txt y prueba_diff_2/documento.txt son distintos
Los archivos prueba_diff_1/.DS_Store y prueba_diff_2/.DS_Store son distintos
Sólo en prueba_diff_1/: Spot OFICIAL.mp4
Sólo en prueba_diff_2/: wetransfer-af86cd.zip

En el caso particular de MacOS me generaba muchas líneas indicando que en todos los directorios los archivos .DS_Store eran distintos. Como son archivos que en realidad no importan me interesaba ignorarlos. Eso se puede hacer con la opción "-x '*.extension_a_ignorar' "

Por ejemplo 

$ diff -rq -x '*.DS_Store' prueba_diff_1/ prueba_diff_2/
Los archivos prueba_diff_1/documento.txt y prueba_diff_2/documento.txt son distintos
Sólo en prueba_diff_1/: Spot OFICIAL.mp4
Sólo en prueba_diff_2/: wetransfer-af86cd.zip

...y una cosa importante es que es muy rápido procesando grandes volúmenes de archivos.

viernes, junio 06, 2014

Añadiendo un RAID 1 a una instalación de ubuntu 14.04 preexistente

Vamos a añadir dos discos de 1TB formando un RAID 1 a un servidor que ya tiene instalado previamente un disco de 140GB con su sistema operativo Ubuntu 14.04.

Me he inspirado en estos dos artículos

http://feeding.cloud.geek.nz/posts/setting-up-raid-on-existing/
http://www.guia-ubuntu.com/index.php?title=Crear_una_Software_RAID

Preliminares
Son dos discos WD SATA de 1TB, instalados normalmente y comprobado que están disponibles con
lsblk. Los ha identificado como /dev/sdb y /dev/sdc

Al pasarle el fdisk me ha dicho que no estaban alienados correctamente (más información en este artículo)

Solucionado con el comando:
sudo fdisk -H 224 -S 56 /dev/sdb (seguido de 'w' cuando nos pregunte para confirmar los cambios)
sudo fdisk -H 224 -S 56 /dev/sdc

Asegurarse de que tenemos todo el software instalado con
sudo apt-get install mdadm rsync initramfs-tools

Iniciamos

Creo las particiones (en mi caso una única partición primaria con todo el disco) con
sudo fdisk -/dev/sdb

  • m para ayuda
  • n nueva particin
  • p de primaria
  • valores predeterminados para el resto
  • 1
  • t para indicar el tipo
  • L para listar
  • fd para Linux Raid Auto


Como lo he hecho varias veces durante las prueba al final he usado cfdisk, una alternativa mucho más interactiva y fácil.

Una vez creadas las particiones creamos el RAID con

sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1

Aceptamos y empieza a crearlo en segundo plano. Podemos consultar el estado con:
$cat /proc/mdstat 
Personalities : [raid1] 
md0 : active raid1 sdc1[1] sdb1[0]
      972725056 blocks super 1.2 [2/2] [UU]
      [>....................]  resync =  0.8% (8456320/972725056) finish=82.6min speed=194392K/sec

Tomate un cafetín o dos que la cosa va para rato

Finalizada la creación del RAID hay que formatearlo. Asegúrate de que identificador de dev le ha asignado:
$ sudo mkfs.ext4 /dev/md0

Y finalmente preparamos en el montaje
$sudo mkdir /media/raid

Editamos el fichero /etc/fstab y añadimos
/dev/md0        /media/raid     ext4    defaults,       0       0

Con sudo mount -a nos deja montadas todas las particiones

Ya puedes crear las carpetas que desees en el RAID ten en cuenta el tema de los permisos para saber si los usuarios podrán escribir en ellas.

...y reinicia... para encontrar un error :-(

Por alguna razón Como no había guardado la configuración del RAID no encuentra el dispositivo /dev/md0 así que me salto el montaje y cuando ejecuto
$ sudo mdadm --detail --scan
ARRAY /dev/md/woody:0 metadata=1.2 name=woody:0 UUID=230eecee:2560d588:bf244ba0:f0adfdd8

...me encuentro con el que el dispositivo ha pasado a ser /dev/md/woody:0.

El caso es que no es mucho problema puesto que el RAID sigue existiendo con otro nombre. Modifico el /etc/fstab
/dev/md/woody:0 /media/raid ext4 defaults 0 0

...y en previsión de futuros errores y para que se guarde correctamente la configuración  (aunque Ubuntu autodetecta los RAIDs al arrancar) algo lo siguiente. Añadir al /etc/mdadm/mdadm.conf los dispositivos usados

DEVICE /dev/sdb* /dev/sdc*  
 (verás que la línea está comentada)

...y también añadimos los datos de los arrays creados (es conveniente que te pases a root y no lo hagas con sudo, puede darte problemas)
mdadm --detail --scan >> /etc/mdadm/mdadm.conf  

Por último y para dejarlo fino del todo lanzamos la reconfiguración de mdadm para que seleccionar chequeos periódicos, la dirección email donde tiene que enviar los avisos...
sudo dpkg-reconfigure mdadm

Esto último instalará un proceso del tipo mdadm --monitor --scan --daemonize que chequeara los discos e irá enviando informes por corre electrónico. Para estar seguro de que funciona correctamente tienes que tener instalado y configurado correctamente postfix. Para probarlo puedes hacer un kill al proceso mdadm --monitor arrancado y probarlo manualmente con:

$ sudo mdadm --monitor /dev/md0 --test --mail=tumail@ejemplo.com

Eso dejará el proceso arrancado y a los pocos minutos deberías recibir un correo electrónico. Si no es así primero deberás comprobar que el postfix esta correctamente configurado.

Podemos instalar adicionalmente las smartmoontols y programar un chequeo periódico para detectar la degradación de los discos (por si tienen tasas de fallo demasiado elevadas)

$ sudo apt-get install smartmontools
$ sudo smartctl -d sat --all /dev/sdb #test basico para discos SATA

...y lo instalamos para que semanalmente realice un chequeo y envíe un correo en caso de problemas
# new test to RAID involved disks with mailing
/dev/sdb -d sat -o on -S on -s (S/../.././02|L/../../6/03)  -m USUARIOCORREO@EJEMPLO.COM
/dev/sdc -d sat -o on -S on -s (S/../.././02|L/../../6/03)  -m USUARIOCORREO@EJEMPLO.COM


También existe un GUI que podemos usar (si conectamos por ssh activa la opcion -X)
$ sudo apt-get install gsmartcontrol
$ sudo gsmartcontrol


Algunos comandos útiles


Si dejamos de detectar el RAID en algún momento
sudo mdadm --detail --scan

Para detener y eliminar un RAID si no lo hemos configurado correctamente
sudo mdadm --stop /dev/md0
sudo mdadm --remove /dev/md0 (no ha sido necesario en mi caso)
Para eliminar los superblock
sudo mdadm --zero-superblock /dev/sda1 /dev/sdb1 /dev/sdc1 (particiones involucradas)

Monitorizar el estado del RAID
cat /proc/mdstat  o sudo mdadm --query /dev/md0 o sudo mdadm --detail /dev/md0

Similar para monitorizar el estado de los discos
sudo mdadm --query /dev/sdb1 o sudo mdadm --examine /dev/sdb1

Probando performance del disco
http://askubuntu.com/questions/87035/how-to-check-hard-disk-performance