KVM: Configurar Bridged Networking – Adaptador Puente


Bueno, resulta que entrando en el mundo de la virtualización, este es un tema de consulta permanente, así que merece la presente entrada.

Aplicable a: Fedora / CentOS / Redhat con KVM / qemu / libvirt

– Deshabilitar el Network Manager. Aparentemente el Network Manager no soporta el bridging.

# chkconfig NetworkManager off
# chkconfig network on
# service NetworkManager stop
# service network start

Otra opción para no deshabilitar el servicio es editar el /etc/sysconfig/network-scripts/ifcfg-eth0 y agregar la entrada: “NM_CONTROLLED=no”.

– Creamos las interfaces bridge:

Editar el /etc/sysconfig/network-scripts/ifcfg-eth0 y agregar la entrada:

BRIDGE=br0

Crear el archivo /etc/sysconfig/network-scripts/ifcfg-br0

con un contenido similar a este:

DEVICE=br0
TYPE=Bridge
BOOTPROTO=dhcp
ONBOOT=yes
DELAY=0

Ojo que “Bridge” es case-sensitive y va como en el ejemplo.

– Restarteamos la red

# service network restart

– Configuramos las iptables para que permitan que el trafico sea redirigido forwarded a través del bridge:

# iptables -I FORWARD -m physdev –physdev-is-bridged -j ACCEPT
# service iptables save
# service iptables restart

Opcionalemente podemos evitar que el trafico del puente sea procesado por las reglas de las iptables. Esto lo hacemos modificando los parámetros del kernel en el /etc/sysctl.conf y agregando las siguientes líneas:

net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

Luego, releemos los parametros del kernel:

# sysctl -p /etc/sysctl.conf

– Restarteamos el libvirt daemon:

# service libvirtd reload

Ahora, debería aparecer el “shared physical device” habilitado.

– Podemos chequear el bridge de la siguiente manera:

# brctl show
bridge name     bridge id               STP enabled     interfaces
virbr0          8000.000000000000       yes
br0             8000.000e0cb30550       no              eth0

Ojo que este bridge es completamente independiente del virbr0.

El virbr0 se utiliza unicamente para hacer NAT.

Configurando Quotas de disco


Para poder establecer quotas de disco en una determinada partición debemos indicar un parametro adicional en el momento del montaje de la partición.
Esto lo hacemos agregando el parametro “usrquota” (para usuarios) o el parametro “grpquota” (para grupos) en el /etc/fstab.
Por ejemplo, para establecer las quotas de usuario y grupo en el punto de montaje “home”:
/dev/hda2 /home ext3 defaults, usrquota 1 1

Remontamos la partición para que tengan efectos los cambios que hicimos en el fstab:
# mount -o remount /home

Creamos la base de datos de quotas en el filesystem:
# quotacheck -vcugm /home

Iniciamos las quotas:
# quotaon -a /home

Para establecer las quotas:
# edquota usuario

Disk quotas for user usuario (uid 500):
  Filesystem                                               blocks       soft       hard     inodes     soft     hard
  /dev/mapper/VolGroup00-LogVol00    2044          0          0           315         0         0

Significado de cada campo:
Blocks: Son bloques utilizados. 1k blocks.
soft: Limite Soft, a partir de donde avisa.
hard: Limite Hard, a partir de donde niega la escritura.
Inodes: Limite de inodos utilizados.
soft: Limite Soft, a partir de donde avisa.
hard: Limite Hard, a partir de donde niega la escritura.

O podemos hacer directamente 
# setquota usuario 4096 5120 40 50 /home

Para consultar las quotas podemos usar los comandos quota o repquota entre otros.

Configurar iJab chat client con ejabberd


Bueno, como esta configuración me dió bastante laburito, acá vamos con los detalles.
Primero vale la pena aclarar que lo que vamos a hacer es instalar el cliente jabber iJab, que es un cliente web que se posiciona en la parte inferior del navegador y se asemeja mucho al cliente de chat web de gmail o de facebook.

Consideremos además que, independientemente del cliente que usemos, debemos instalar un servidor jabber. Yo he instalado el ejabberd sobre CentOS.

El servidor jabber se puede descargar desde aqui: http://www.ejabberd.im/
El cliente web iJab se puede descargar desde aqui: http://code.google.com/p/ijab/

Puertos: en el dominio donde se instale el jabber, debe abrirse los siguientes puertos para que puedan funcionar con el cliente iJab y el jabber: 5222, 5280, 5269.

Respecto de la instalación del servidor jabber, es bastante intuitiva, solo remarcaré los puntos importantes en el archivo de configuración para que el servidor funcione correctamente con este servicio:
En el ejabberd.cfg, asegurarse de que las siguientes secciones están habilitadas y seteadas:

{hosts, [“jabber.example.com”]}.


{listen,
{5280, ejabberd_http, [
                       %%{request_handlers,
                       %% [
                       %%  {[“pub”, “archive”], mod_http_fileserver}
                       %% ]},
                       %%captcha,
                       http_bind,
                       http_poll,
                       web_admin
                      ]}


{modules,
      {mod_http_bind, []},

Teniendo esto configurado, si apunto el navegador a: http://jabber.example.com:5280/http-bind/

Debería tener como respuesta una página con algo así:
ejabberd mod_http_bind
An implementation of XMPP over BOSH (XEP-0206)
This web page is only informative. To use HTTP-Bind you need a Jabber/XMPP client that supports it.

Yendo a la configuración del iJab, vamos a descomprimir el paquete directamente dentro de /var/www/html/ijab.

En dicho directorio, configuramos un .htaccess con el siguiente contenido:
AddDefaultCharset UTF-8
Options +MultiViews

        RewriteEngine On
        RewriteRule http-bind/ http://jabber.example.com:5280/http-bind/ [P]

En el paquete del iJab hay un archivo a configurar: el ijab_config.js
Dentro hay que modificar las siguientes líneas:
        domain:”example.com”,
        http_bind:”http://jabber.example.com/http-bind/”,
        host:”localhost@jabber.example.com”,
        port:5222,
        server_type:”ejabberd”,

 
Luego, en el /etc/httpd/conf/httpd.conf creamos el siguiente directorio virtual:
VirtualHost *:80>
  ServerName jabber.example.com
  DocumentRoot /var/www/html
 
     Options +Indexes +Multiviews
     AllowOverride all
 
  AddDefaultCharset UTF-8
  RewriteEngine on
  RewriteLogLevel 9
  RewriteRule http-bind/ http://jabber.example.com:5280/http-bind/ [P]
  CustomLog /etc/httpd/logs/http-bind_access.log combined
  ErrorLog /etc/httpd/logs/http-bind_error.log

Restarteamos el apache y listo.
# service httpd restart

Con esta configuración en el apache estamos seteando los archivos de log para poder verificar cualquier problema. En principio, antes de configurar el apache hay que verificar que el http-bind esté funcionando correctamente en la dirección http://jabber.example.com:5280/http-bind/

Si esto no devuelve la respuesta del servidor jabber, hay algo mal configurado en el mismo.

Lentitud en Mysql


El tema es que por una situación muuuuyyy particular, un cliente me pidió sacar el Mysql que tenía funcionando perfectamente en un linux CentOS para pasarlo a un Windows 2003 Server …!!! WTF !!

Entonces, me pongo manos a la obra, le instalo el motor, le instalo el repositorio de datos en un storage externo que tenía, restauro los datos, etc, etc, etc.
La cuestión es que cuando va a levantar los sitios que laburan con ese mysql, las primeras consultas funcionan, pero luego se pone cada vez mas lento hasta ya no responde para nada….
Buscando el motivo por todos lados, mientras el cliente me putea en todos los lenguajes que conoce, encuentro en los logs del mysql “unauthenticated user”. Prácticamente una línea por cada consulta emitida contra el servidor.
Buscando info por ahí encuentro que no es un problema con el usuario del mysql sino que es un tema de resolución de nombres (DNS’s). Resulta que el mysql además de comprobar el usuario, trata de resolver el host. Al estar en un windows sin DNS, no tenía manera de resolver el nombre del host.
Hay varias maneras de solucionarlo: Hacer resolver el windows instalando un DNS, utilizar todas las referencias con IPs en vez de nombres de host, o agregar en el my.cnf una línea: “skip-name-resolv”.
Espero haber llegado a tiempo para alguno con el mismo problema.

Buscar y eliminar archivos por antiguedad


Esto siempre resulta útil para realizar taréas de mantenimiento del filesystem:
Buscar y eliminar archivos con mas de 3 días de antiguedad:

# find /home/ -mtime +3 -exec rm -rf {} \;

Si queremos que sean los que tienen menos de 3 días de antiguedad, reemplazamos el +3 por -3.
Si queremos que sean los que tienen exactamente 3 días de antiguedad, reemplazamos el +3 por 3.

Migrar Servidores a Linux


La migración de sistemas de plataformas Windows a plataformas Linux surge de la necesidad lisa y llana de abaratar costos. Este es un resumen (muy resumido) de mis experiencias:

Escenario: Tenía una serie de servidores Windows, en su mayoría W2003R2, brindando los siguientes servicios:
– File Server, Mail Server, Proxy, Antivirus, Active Directory, Sql Server.

La cuestión es que de a poco y con paciencia es posible migrarlos a todos…, o casi todos a Linux.

– El Active Directory + el File Server se puede configurar directamente en un Linux con Samba + Ldap. El ldap (openldap) nos va a dar la funcionalidad de autenticación de usuarios mientras que el samba nos va a brindar los recursos compartidos necesarios para trabajar con archivos en la red.

– Con Squid reemplazamos cualquier proxy.

– Respecto del servidor de mail, he sido bastante masoquista al respecto (eso dicen ja, ja). Me he dedicado a instalar un servidor QMail con listas RBL que para instalarlo, me ha llevado unas cuántas horas de “plática” con él.

– Respecto de la base de datos, la mejor manera de reemplazar el SQL server es migrando los datos y el código a Mysql o Postgres.
El tema es el siguiente: los datos son fáciles de migrar. Inclusive hay herramientas que realizan dicha taréa. Pero en mi caso, tengo cientos de Stored Procedures… éstos si o sí requieren un análisis y traducción de código que no he visto que realice ninguna herramienta, con lo cuál, en mi caso, el costo de migración es sumamente alto.
Otro tema a evaluar en el caso de la base de datos es la aplicación que hace uso de dicha base. Es posible migrar su enlace a la base?

– Respecto del antivirus, no he encontrado un reemplazo realmente eficiente para el Symantec Corporate Server. Este antivirus, trabaja una base de virus centralizada y hace un deploy a todos los clientes windows conectados.
Creo que la mejor solución para este reemplazo va a surgir cuando pueda reemplazar todos los clientes windows por clientes Linux !!!

scripts: qmail usage statistics


Aquí varios scripts utilizados para analizar el uso del servidor de correo qmail. Se pueden utilizar independientemente o el primero llamará al resto:

[root@test scripts]# cat chkStatus.sh 
#!/bin/bash
echo ""
echo ""
echo "Consultas de estado. Servidor Qmail"
echo "==================================="
echo ""
echo "TCP Server Hits:"
/root/scripts/chkTcpServerHits.sh $1|cut -c12-50
echo "RBL Hits:"
/root/scripts/chkRblHits.sh $1|cut -c12-50
echo "SPAM Hits:"
/root/scripts/chkSpamHits.sh $1|cut -c13-50
echo "Spam Deleted: "
/root/scripts/chkSpamHitsDeleted.sh $1|cut -c13-50
echo "Virus Hits:"
/root/scripts/chkVirusHits.sh $1|cut -c13-50
echo "Qtrap Hits:"
/root/scripts/chkQtrapHits.sh $1|cut -c12-50
echo "Failure:"
/root/scripts/chkFailure.sh $1|cut -c12-50
echo "Pop3 Hits:"
/root/scripts/chkPopHits.sh $1|cut -c12-50
echo "Send Local:"
/root/scripts/chkSendLocal.sh $1|cut -c12-50
echo "Send Remote:"
/root/scripts/chkSendRemote.sh $1|cut -c12-50
echo ""
echo "Estado de las colas: "
qmailctl queue
echo ""
echo "Uptime: "
uptime
echo ""

[root@test scripts]# cat chkTcpServerHits.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de tcpserver: pid de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco "rblsmtpd" en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-smtpd/*|grep "tcpserver: pid"| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkRblHits.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de rblsmtpd de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco "rblsmtpd" en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-smtpd/*|grep "rblsmtpd:"| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkSpamHits.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de SPAM de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%c --date=$1|cut -c5-15`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco para determinar la cantidad de lineas que lo contienen
cat /var/spool/qscan/qmail-queue.log|grep "smells like SPAM"|cut -c6-16| \
# busco la fecha
grep "$fecha" | \
# cuento numero de lineas
wc -l
# end
exit

[root@einstein scripts]# cat chkSpamHitsDeleted.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de SPAM eliminado de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%c --date=$1|cut -c5-15`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco para determinar la cantidad de lineas que lo contienen
cat /var/spool/qscan/qmail-queue.log|grep "deleting message..."|cut -c6-16| \
# busco la fecha
grep "$fecha" | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkVirusHits.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de virus de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%c --date=$1|cut -c5-15`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco para determinar la cantidad de lineas que lo contienen
cat /var/spool/qscan/qmail-queue.log|grep "there be a virus"|cut -c6-16| \
# busco la fecha
grep "$fecha" | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkQtrapHits.sh 
#!/bin/bash
# 20070418-hvivani-Obtiene total dets del qtrap  de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
fechaQtrap=`date +%m/%d/%y --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco en los logs para determinar la cantidad de lineas que lo contienen
cat /home/vpopmail/qtrap/logs/qtrap.log|grep "$fechaQtrap"|wc -l
# end
exit

[root@test scripts]# cat chkFailure.sh 
#!/bin/bash
# 20070418-hvivani-Obtiene total de failure de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-send/*|grep "failure: "| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkPopHits.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de tcpserver: pid de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco "rblsmtpd" en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-pop3d/*|grep "tcpserver: pid"| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkSendLocal.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de entregas locales de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco "rblsmtpd" en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-send/*|grep "to local "| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

[root@test scripts]# cat chkSendRemote.sh 
#!/bin/bash
# 20070417-hvivani-Obtiene total de entregas remotas de los logs de qmail para una fecha pasada por linea de comandos.
fecha=`date +%Y-%m-%d --date=$1`
# imprimo fecha. Puede cambiarse para otros dias
echo $fecha | \
# coloco una coma
awk '{printf $0","}' \
# busco "rblsmtpd" en los logs para determinar la cantidad de lineas que lo contienen
cat /var/log/qmail/qmail-send/*|grep  "to remote "| \
# convert Time Atomic International timestamp to normal human readable format <-- motherfucker yeahhh!!!
/usr/local/bin/tai64nlocal | \
# busco el human readable timestamp para todas las instancias de la fecha
grep $fecha | \
# cuento numero de lineas
wc -l
# end
exit

script para verificar conexión


Este script verifica la conexión con un determinado servidor. Puede ser utilizado con un router/modem y, eventualmente reiniciarlo a través de un comando expect / spawn.

[root@test scripts]# cat chkconn 
dd=`date +%d`
mm=`date +%m`
YY=`date +%Y`
HH=`date +%H`
MM=`date +%M`
d=0
u=0
HOSTS="www.google.com newton 10.0.1.4 fabrica.dyndns.org"
for HOST in $HOSTS
do
   ping $HOST -c 1|grep " 0% packet loss" > /dev/null
   if [ $? = 0 ] 
   then
      echo "$YY$mm$dd$HH$MM $HOST está levantado"
      let "u=u+1" 
   else
      echo "$YY$mm$dd$HH$MM $HOST no es accesible" >> /var/log/chkconn.log
      let "d=d+1"
   fi
done
echo
#echo "$u sistemas levantados"
#echo "$d sistemas inaccesibles"
#### Si hay mas de tres servidores inaccesibles, reinicia el modem ADSL
#if [[ $d > 3 ]]
#then
#   echo "$YY$mm$dd$HH$MM - Hay $d sistemas off-line" >> /var/log/chkconn.log
#   /usr/bin/expect /root/scripts/reboot.exp
#else
#   echo "Ok."
#fi

 

[root@test scripts]# cat reboot.exp 
spawn telnet 10.0.1.4

expect "NetDSL>"
send "reboot\r"

expect "r"