Debian
Any stuff about GNU/Linux Debian
Servers package difference => “dpkg-diff”
0Problem
You have two linux servers A and B, you want to know what installed packages are not in both servers (A-B joined with B-A).
Solution
The following script (dpkg-diff.sh, tested on GNU/Linux Debian Lenny/Squeeze).
dpkg-query command and a ssh server must be installed on both servers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ### # FILE: dpkg-diff.sh # AUTHOR: Olaf Reitmaier <olafrv@gmail.com> # LICENSE: GNU/GPL v3 (Visit www.gnu.org for more info) # USAGE: Servers package difference => "dpkg-diff" # WARNING: Modify header vars according to your needs. ## # Header variables s1=server1.example.com s2=server2.example.com u1=testuser u2=$u1 # Exclude lib* packages ft="-v ^lib" f1=/tmp/dpkg-diff.1 f2=/tmp/dpkg-diff.2 # Do not edit this lines unless you know what your doing! ssh $u1@$s1 "dpkg-query --list" | grep '^ii' | awk '{print $2}' > $f1 ssh $u2@$s2 "dpkg-query --list" | grep '^ii' | awk '{print $2}' > $f2 clear echo "Only in $s1" cat $f1 | grep $ft | sort | while read package do if [ $(cat $f2 | grep $package | wc -l) -eq 0 ] then echo -n "$package " fi done echo echo echo "Only in $s2" cat $f2 | grep $ft | sort | while read package do if [ $(cat $f1 | grep $package | wc -l) -eq 0 ] then echo -n "$package " fi done echo echo |
DKIM en Postfix con GNU/Linux Debian
0Introducción
DKIM (Domain Key Identified Email) es un mecanismo de seguridad que permite la autenticación de mensajes de correo electrónico, descrito en el RFC-5585 disponible en http://www.dkim.org/specs/rfc5585.html.
El mecanismo DKIM consiste en utilizar una infraestructura de claves públicas (certificados) y privadas para en principio firmar y posteriomente autenticar un mensaje de correo electrónico.
Los certificados están asociados a dominio (@example.com) o para direcciones de correo electrónico específicas (*@example.com, me@example.com).
Los mensajes salientes son firmados por el emisor, tomando un conjunto de encabezados (headers) aplicando un algoritmo hash con una clave privada para generar una encabezado (DKIM-Signature) que se añade al mensaje.
Los mensajes entrantes son verificados si contienen un encabezado de firma donde se especifica que clave pública consultar vía DNS para realizar la verificación.
Instalación y configuración de Debian para uso con Postfix
Para empezar suponemos que tenemos instalado y configurado en un servidor el servicio Postfix para el dominio “example.com”, en ese mismo servidor se configurará el servicio DKIM aunque esto no es obligatorio.
Instalar el paquete dkim-filter:
1 | apt-get install dkim-filter |
Si no se han generado las claves publicas y privadas, se debe generar una clave de prueba (test) que sirve para depurar y omitir error sin rechazar los correo electrónico, y una clave para producción (“default” en nuestro caso, aunque pueden generarse cuantas sean necesarias).
Primero creamos una carpeta que contendrá las claves públicas y privadas de nuestro dominio “example.com”:
1 2 | mkdir -p /etc/dkim/keys/example.com cd /etc/dkim/keys/example.com |
Gereramos la clave de prueba y de producción respectivamente:
1 2 | dkim-genkey -d example.com -r -s test -t dkim-genkey -d example.com -r |
El parametro -s indica que la clave de prueba será nominada con el selector “test” y la clave de producción como se especificó será nominada con el selector “default”.
Las claves públicas y privadas generadas en el directorio:
1 2 3 4 5 6 | $ ls -l total 16 -rw------- 1 root root 887 Sep 21 2011 default.private -rw------- 1 root root 308 Sep 21 2011 default.txt -rw------- 1 root root 887 Sep 21 2011 test.private -rw------- 1 root root 307 Sep 21 2011 test.txt |
Se almacenan con la extensión “.private” mientras que los registros DNS en formato para bind9 se almacenan en los archivos “.txt” con el siguiente formato:
v=DKIM1; g=*; k=rsa; p=
Para publicar los certificados se deben crear dos (2) registros DNS tipo TXT para los nombres de servidores siguientes:
- El nombre “test._domainkey” del dominio “example.com” con el contenido del
archivo “test.private”. - El nombre “default._domainkey” del dominio “example.com” con el contenido
del archivo “default.private”.
Una vez creado los registros DNS anteriores, la consulta DNS (usando el comando nslookup) para los nombres “default._domainkey” y “test._domainkey” del dominio “example.com” debe arrojar los siguientes resultados:
1 2 3 4 5 6 7 8 9 | $ nslookup -type=txt test._domainkey.tsj-dem.gob.ve 200.44.32.12 Server: 200.44.32.12 Address: 200.44.32.12#53 test._domainkey.tsj-dem.gob.ve text = "v=DKIM1\; g=*\; k=rsa\; t=y\; p=<clave>" $ nslookup -type=txt default._domainkey.tsj-dem.gob.ve 200.44.32.12 Server: 200.44.32.12 Address: 200.44.32.12#53 default._domainkey.tsj-dem.gob.ve text = "v=DKIM1\; g=*\; k=rsa\; p=<clave>" |
Es importante indicar que la expresión
es sensible a mayúsculas y minúsculas tanto en el archivo como en la consulta DNS el resultado debe ser el mismo.
Pero para garantizar que los selectores funcionen correctamente deben eliminarse la extensión “.private” o crear link simbólicos porque los nombres contentivos de la clave pública deben ser iguales a los nombres de los selectores:
1 2 3 4 5 6 7 8 | $ ls -l total 16 lrwxrwxrwx 1 root root 15 Apr 9 16:32 default -> default.private -rw------- 1 root root 887 Sep 21 2011 default.private -rw------- 1 root root 308 Sep 21 2011 default.txt lrwxrwxrwx 1 root root 12 Apr 9 16:32 test -> test.private -rw------- 1 root root 887 Sep 21 2011 test.private -rw------- 1 root root 307 Sep 21 2011 test.txt |
En el archivo de configuración del servicio DKIM en la ruta /etc/dkim-keys.conf:
*@example.com:example.com:/etc/dkim/keys/example.com/test
En el archivo principal de configuración del servicio DKIM /etc/dkim-filter.conf:
Syslog yes
X-Header yes
LogWhy yes
#On-BadSignature accept
#On-DNSError accept
#On-InternalError accept
#On-NoSignature accept
#On-Security accept
On-Default accept
En Debian es modificar el archivo /etc/default/dkim-filter:
SOCKET=”inet:8891@localhost”
Finalmente, activamos el servicio DKIM:
1 | /etc/init.d/dkim start |
Verificar los registros:
1 | /var/log/syslog | grep -i dkim |
Para indicarle a Postfix que debe firmar los correos simplemente colocamos
en el archivo configuración /etc/postfix/main.cf:
# Firma Electrónica – DKIM
milter_default_action = accept
# Postfix ≥ 2.6
milter_protocol = 6
# 2.3 ≤ Postfix ≤ 2.5
#milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Ahora debemos reiniciar Postfix y realizar algunas pruebas:
- Enviar un correo a GMAIL y verificar los encabezados DKIM-Signature y Authentication-Result.
- Seguir las instrucciones del siguiente asisten de verificación de correo electrónico: http://www.brandonchecketts.com/emailtest.php
Para entender mejor el funcionamiento y procedimiento descritos sobre DKIM a continuación consulte y utilice los recursos siguientes:
- Página Principal del Proyecto DKIM (www.dkim.org)
- Fork del Proyecto DKIM (www.opendkim.org)
- http://www.dkim.org/specs/rfc5585.html
- http://www.debiantutorials.com/setup-domainkeys-identified-mail-dkim-in-postfix/
- http://staff.blog.ui.ac.id/jp/2009/04/07/creating-dkim-on-debian-50/
- http://www.brandonchecketts.com/emailtest.php
Recuperación de base de datos MySQL
0I.- MOTORES DE BASE DE DATOS
Los dos (2) motores de base de datos MySQL más usados para almacenar datos en tablas son MyISAM e InnoDB. El primero MyISAM, a diferencia de InnoDB no permite almacenamiento transaccional (conforme a ACID) con capacidades de commit (confirmación), rollback (cancelación) y recuperación de fallas, por eso más estable que InnoDB que es mucho más sensible a corrupciones de datos.
Los motores de base de datos activos pueden visualizarse con el comando:
1 | mysql> show engines; |
II.- ARCHIVOS BASES DE DATOS
En su mayoría los archivos de bases de datos se almacenan en archivos con el nombre de la tabla en una subcarpeta con el nombre de la base datos. Sin embargo, dependiendo del motor de base de datos esto varia como se describe a continuación:
Por cada tabla tipo MyISAM existe un archivo .frm con su estructura, un archivo de datos .MYD (MYData) y un archivo de índice .MYI (MYIndex).
El motor de almacenamiento InnoDB gestiona en cada instancia del servidor de MySQL archivos de datos de espacios de tablas (tablespaces) y archivos de registro (log). Para cada tabla tipo InnoDB existe un archivo .frm registrado en el diccionario de datos de InnoDB (no en el global de la instancia de MySQL), por esta razón no se pueden mover tablas entre bases de datos sencillamente moviendo los ficheros .frm.
Adicionalmente, a menos que la configuración por defecto de InnoDB sea modificada, MySQL crea un archivo de datos (autoextensible) llamado ibdata1 y dos archivos de registro (log) llamados ib_logfile0 y ib_logfile1 que son compartidos por todas las tablas InnoDB de una instancia MySQL. Es posible agregar la opción innodb_file_per_table en la configuración para indicar a MySQL que la información de las tablas InnoDB se almacenen en su propio archivo de datos .IBD.
III.- REPARACIÓN DE BASES DE DATOS
III.A.- SERVIDOR MYSQL EN LÍNEA
Antes de realizar cualquier labor de mantenimiento se deben detener los sistemas que se conectan al servidor de base de datos, o bien, reportar el servidor caído denegando las conexiones.
La manera más fácil de lograrlo es bloqueando las conexiones IP de la red local (Interfaz eth0) en el servidor MySQL utilizando iptables, dependiendo del número de instancias (3306, 3307, 3308) y del número de interfaces los comandos serían los siguientes:
1 2 3 | iptables -I INPUT -i eth0 -p tcp -m multiport --dports 3306 -j REJECT iptables -I INPUT -i eth0 -p tcp -m multiport --dports 3306,3307 -j REJECT iptables -I INPUT -i eth0 -p tcp -m multiport --dports 3306:3308 -j REJECT |
Para desactivar el bloqueo cambiamos “iptables -I INPUT” por “iptables -D INPUT” en los comandos anterior y para ver el listado de las reglas debloqueo activas ejecute “iptables -S”.
Es importante destacar que solo se pueden reparar bases de datos en una instancia de MySQL que se esté ejecutando (en línea).
Un servidor muestra en el log de error los siguientes mensajes cuando se detiene e inicia correctamente:
120301 16:37:11 [Note] /usr/sbin/mysqld: Normal shutdown
120301 16:37:11 [Note] Event Scheduler: Purging the queue. 0 events
120301 16:37:13 InnoDB: Starting shutdown…
120301 16:37:14 InnoDB: Shutdown completed; log sequence number 0 44233
120301 16:37:14 [Note] /usr/sbin/mysqld: Shutdown complete
120301 16:37:24 [Note] Plugin ‘FEDERATED’ is disabled.
120301 16:37:24 InnoDB: Started; log sequence number 0 44233
120301 16:37:24 [Note] Event Scheduler: Loaded 0 events
120301 16:37:24 [Note] /usr/sbin/mysqld: ready for connections.
Version: ’5.1.49-3′ socket: ‘/var/run/mysqld/mysqld002.sock’ port: 3307 (Debian)
Si el servidor MySQL no se está ejecutando entonces continúe en la sección “SERVIDOR DE MYSQL DETENIDO”.
El comando para realizar la reparación es “mysqlrepair” que tiene una sintaxis similar a “mysql”, algunos ejemplos son:
1 2 3 | mysqlrepair -u root -p <base-de-datos> mysqlrepair --socket=/var/run/mysqld/mysqld.sock -u root -p <base-de-datos> mysqlrepair --protocol=tcp --port=3306 -h 127.0.0.1 -u root -p <base-de-datos> |
NOTA: La ruta del socket, la dirección ip, el puerto o el protocolo pueden varias dependiendo del número y ubicación de las instancias del servidor MySQL.
Si una base de datos no pudo ser reparada se debe eliminar y restaurar partiendo un respaldo (dump) previamente hecho con el comando mysqldump, ejecutando el siguiente comando:
1 | mysql --protocol=tcp --port=3306 -u root -p mibasededatos < midump.sql |
Si no tiene un respaldo entonces la información se habrá perdido definitivamente.
III.B.- SERVIDOR DE MYSQL DETENIDO
Si el servidor MySQL no se está ejecutando debemos determinar la causa inspeccionando el log de error del servidor.
Si no está configurado debe activarlo colocando en el archivo de configuración my.cf:
[mysqld]
log-error = /var/log/mysql/mysql.err.log
Si se determina que el servidor no inicia debido a problemas con InnoDB (90% de las veces) entonces se debe proceder como describe a continuación, por el contrario, si el problema es con otro motor de almacenamiento lo más recomendable es restaurar la tabla o base de datos afectada desde cero.
Algunos mensajes que indican problemas con InnoDB son los siguientes:
InnoDB: Page directory corruption: infimum not pointed to
InnoDB: Page directory corruption: supremum not pointed to
InnoDB: Probable reason is database corruption or memory
InnoDB: corruption. If this happens in an InnoDB database recovery, see
InnoDB: http://dev.mysql.com/doc/refman/5.1/en/forcing-recovery.html
InnoDB: how to force recovery.InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.1/en/forcing-recovery.html
InnoDB: about forcing recovery.
Una vez confirmada que la causa está relacionada con InnoDB, debemos intentar que MySQL aplique sus propios mecanismos de recuperación, probando cada uno hasta que logremos iniciar el servidor e intentar rescatar los datos existentes o iniciar la reparación de de las bases de datos. En estos modos de recuperación sólo se pueden ejecutar instrucciones SELECT en caso de que el servidor inicie.
Los mecanismos de recuperación se establecen colocando en el archivo de configuración my.cf lo siguiente:
[mysqld]
# 1 (SRV_FORCE_IGNORE_CORRUPT)
# 2 (SRV_FORCE_NO_BACKGROUND)
# 3 (SRV_FORCE_NO_TRX_UNDO)
# 4 (SRV_FORCE_NO_IBUF_MERGE)
# 5 (SRV_FORCE_NO_UNDO_LOG_SCAN)
# 6 (SRV_FORCE_NO_LOG_REDO)
innodb_force_recovery = 1
Cada vez que intentemos iniciar el servidor al principio del log general o de error aparecerá un mensaje similar al siguiente:
InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on
InnoDB: Skipping log redo
NOTA: Para mayor información sobre los valores innodb_force_recovery de visite 15.8.1. Forzar una recuperación.
El servidor iniciará pero deberá verificarse que inicie de forma limpia (sin errores) como se describe en la sección “SERVIDOR MYSQL EN LÍNEA”.
Si el servidor no inicia entonces debemos deshabilitar el motor de almacenamiento InnoDB colocando en el archivo de configuración my.cf:
[mysqld]
skip-innodb
Si el servidor tampoco inicia entonces debemos descartar el uso del parámetro “skip-innodb”.
No hay otra opción sino dar por perdidos los datos InnoDB de una o varias base de datos y debemos proceder como sigue:
- Detener el servidor MySQL y desactivar “skip-innodb”.
- Hacer un respaldo de los archivos ibdata* a ibdata*.bak
- Hacer un respaldo de los archivos ib_logfile* a ib_logfile*.bak
- Iniciar el servidor.
Si el servidor inicia correctamente entonces tratamos de reparar las bases de datos, de lo contrario hemos llegado al peor caso debemos restaurar todas las bases de datos desde, o bien, reinstalar la(s) instancia(s) afectada(s) del servidor de MySQL.
IV.- REFERENCIAS
Tomadas del Manual de Referencia de MySQL:
- Capítulo 14. Motores de almacenamiento de MySQL y tipos de tablas
- Capítulo 15. El motor de almacenamiento InnoDB
- Sección 15.3. Configuración de InnoDB
- Sección 15.5. Crear el espacio de tablas InnoDB
- Sección 15.13. Estructuras de tabla y de índice
- Sección 15.8. Hacer una copia de seguridad y recuperar una base de datos InnoDB
- Sección 15.8.1. Forzar una recuperación