Aug 30, 2009

Virus Conficker

En Octubre de 2008 Microsoft dio a conocer una vulnerabilidad que afectaba a los sistemas operativos Windows 2000, XP, Vista, Server 2003 y Server 2008. Microsoft libera el parche 958644 junto con su boletín de seguridad MS08-67, fuera de su ciclo de actualizaciones mensuales y considerándolo con el riesgo de crítico. Esta vulnerabilidad sin autenticación permite la ejecución remota de código arbitrario si un sistema afectado recibe una solicitud RPC y la compartición de archivos está habilitada.

Esta vulnerabilidad es aprovechada por el virus Conficker, gusano informático capaz de infiltrase en los sistemas con la posibilidad de dañar y realizar acciones maliciosas sin el consentimiento del usuario. Este tipo de virus tiene la peculiaridad de multiplicarse rápidamente por la red, además de ocultarse y protegerse para evitar su eliminación.

Hasta el momento se conocen tres generaciones del Conficker que varían sus métodos de infección y de propagación, así como las acciones que ejecutan en los equipos infectados. Cada una de las sucesivas generaciones incorpora las características de la anterior, así como nuevas funcionalidades.

Primera generación

En esta primera generación, el malware suele llegar a través de un enlace en un correo electrónico. Si el usuario lo pulsa y el equipo no está protegido, puede infectarlo.

A su vez, la nueva máquina afectada escanea todo el segmento de red al que pertenece en busca de máquinas con recursos compartidos publicados. Para ello lo que hace es ejecutar peticiones masivas al puerto SMB (445).

Si el gusano detecta un equipo con un recurso compartido, aprovechaba para replicarse a ella ejecutando código de forma remota a través de una llamada al servicio RPC.

En esta primera fase fueron apareciendo nuevas variantes, las cuales fueron incorporaron novedosas técnicas de auto-protección: deshabilitación del firewall y del antivirus, bloqueos de los accesos a páginas web de seguridad y actualizaciones de Windows, etc.

Microsoft publicó entonces un listado de los dominios utilizados por el Conficker.

Segunda generación

En esta segunda generación del Conficker (Febrero 2009), el virus es capaz de propagarse a través de unidades de almacenamiento externas. Para ello, una máquina infectada copia dentro de la unidad extraíble dos fichero: un ejecutable (que contiene el virus) y un archivo autorun.inf que instala el virus automáticamente al introducir el dispositivo en otro computador no protegido correctamente por un antivirus.

Además esta segunda generación es capaz de conectarse a otros servidores de Internet para descargar nuevas variantes del virus, lo que provoca que si el fichero de firmas del antivirus no se encuentra correctamente actualizado, esta nueva variante puede infectar rápidamente a otros equipos.

Tercera generación

Esta nueva generación (Marzo 2009) tiene la capacidad de comportarse también como un troyano, que además de deshabilitar los sistemas de protección de una máquina, puede implementar métodos de autoprotección para inmunizarse de los diferentes sistemas de seguridad:
  • Se copia dentro de la carpeta del sistema y deja otras copias en otros directorios de Windows. Estas copias se establecen con los atributos de sólo lectura y ocultación, restringiendo de esta forma su acceso por parte de los usuarios.
  • Añade una entrada en el registro de Windows que se ejecuta nada más iniciar el sistema operativo.
  • Registra un servicio con un nombre aleatorio utilizando ciertas palabras claves, consiguiendo de esta forma parecer un proceso normal del sistema.
  • Parchea aquellos procesos y APIs que puedan suponer un riesgo para el gusano.
Un síntoma muy claro que aparece con esta tercera generación del Conficker es el bloqueo de cuentas de usuarios en el dominio. El gusano intenta propagarse por la red copiándose en los recursos compartidos a través de una lista de usuarios que obtiene del propio sistema infectado y empleando para ello un diccionario de contraseñas débiles.

Si la política de bloqueo de la máquina atacada está activada, tras cierto número de intentos fallidos dejará la cuenta inaccesible.

Además esta nueva variante posee un potente sistema P2P, con lo que cada una de las máquinas infectadas podría conectarse con el resto de equipos afectados y descargar una nueva variante del virus más actualizada a través de esta vía.

Para esta tercera generación, la lista de dominios afectados ha aumentado de 50.000 a 250.000, lo que hace cada vez más difícil el control y bloqueo de los mismos.

Aug 25, 2009

Almacenamiento compartido en red: GFS2 + iSCSI (II)

En esta segunda parte del artículo Almacenamiento compartido en red: GFS2 + iSCSI, vamos a ver cómo securizar la infraestructura con SELinux e iptables.

SELinux

Si se tiene activado SELinux con la opción de enforcing (bloqueo), éste va a impedir el funcionamiento normal del cluster bloqueando ciertas acciones que en base a las políticas de seguridad que trae por defecto, no son correctas o no están permitidas.

La solución pasa por crear un módulo de política local para SELinux que permita dichos accesos. Este módulo se puede generar a partir de los eventos registrados en el archivo audit.log.

Primero vamos a activar SELinux en modo permisivo en todos los nodos. Dicha opción habrá que establecerla en su fichero de configuración. También habrá que reiniciar las máquinas para que todos los ficheros se etiqueten correctamente.
[... ~]# vim /etc/selinux/config
...
SELINUX=permissive
SELINUXTYPE=targeted

SELinux en modo permisivo registrará las alertas de seguridad en el fichero audit.log pero no bloqueará las acciones.

A continuación vamos a vaciar el fichero de uno de estos nodos (por ejemplo en centos01); seguidamente detendremos e iniciaremos el cluster en todos los nodos y a partir de los eventos registrados en el archivo audit.log, generaremos un módulo de política local (cluster.te) y lo instalaremos.
[root@centos01 ~]# >/var/log/audit/audit.log

[root@centos01 ~]# service gfs2 restart
[root@centos01 ~]# service cman restart
[root@centos01 ~]# service rgmanager restart
[root@centos01 ~]# service clvmd restart

[root@centos01 ~]# audit2allow -m local -l -i /var/log/audit/audit.log > cluster.te

[root@centos01 ~]# cat cluster.te
module local 1.0;

require {
type ccs_t;
type tmpfs_t;
type initrc_t;
class sem { unix_read write unix_write associate read destroy };
class shm { write unix_read unix_write associate read destroy };
class file { read write };
}

#============= ccs_t ==============
allow ccs_t initrc_t:sem { unix_read write unix_write associate read destroy };
allow ccs_t initrc_t:shm { write unix_read unix_write associate read destroy };
allow ccs_t tmpfs_t:file { read write };

Antes de poder instalar el módulo, habrá que compilarlo (cluster.mod) y obtener el paquete de seguridad correspondiente (cluster.pp), el cual ya podremos instalar en todos los nodos (el mismo paquete generado en centos01 lo utilizaremos en centos02 y centos03).
[root@centos01 ~]# checkmodule -M -m -o cluster.mod cluster.te

[root@centos01 ~]# semodule_package -o cluster.pp -m cluster.mod

[root@centos01 ~]# semodule -i cluster.pp

Y ya por último, para activar SELinux en modo enforcing (bloqueante) en todos los nodos ejecutaremos el comando setenforce 1. Y para hacer que este cambio sea persistente tras sucesivos reinicios de la máquina, activaremos esta opción en el fichero de configuración de SELinux.
[... ~]# setenforce 1

[... ~]# cat /etc/selinux/config
...
SELINUX=enforcing
SELINUXTYPE=targeted

Iptables

Los puertos que hay que abrir en iptables son los utilizados por los servicios cman (Cluster Manager, 5404 y 5405 UDP), tgtd (3260 TCP), modclusterd (16851 TCP) y dlm (Distributed Lock Manager, 21064 TCP).

A continuación se muestra el contenido del fichero de configuración de iptables para el nodo centos01 (igual que para los otros dos nodos pero con el puerto empleado por el target iSCSI).
[root@centos01 ~]# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport ssh -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p udp -m multiport --dport 5404,5405 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 3260 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 16851 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 21064 -j ACCEPT
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j REJECT
COMMIT

[root@centos01 ~]# service iptables restart

[root@centos01 ~]# chkconfig iptables on

Y para los nodos centos02 y centos03:
[... ~]# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport ssh -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p udp -m multiport --dport 5404,5405 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 16851 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 21064 -j ACCEPT
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j REJECT
COMMIT

[... ~]# service iptables restart

[... ~]# chkconfig iptables on

Aug 17, 2009

Almacenamiento compartido en red: GFS2 + iSCSI (I)

En el presente artículo vamos a desarrollar una arquitectura de almacenamiento compartido a la que accederán de forma concurrente un par de máquinas. Las pruebas van a ser realizadas bajo un sistema operativo de tipo CentOS 5.3.

El área de datos sobre el que se configurará el acceso compartido será un volumen lógico (LogVol00) cuyo sistema de archivos será GFS2 (Global File System 2). GFS es un sistema de ficheros nativo creado por Red Hat y distribuido bajo licencia GNU, que puede ser utilizado de forma local (como por ejemplo ext3) o en cluster, de manera que varios nodos puedan estar trabajando simultáneamente sobre él sin peligro a que se corrompan los datos. La capacidad máxima de almacenamiento de GFS2 es de 8 EB.

En la figura siguiente puede observarse que el espacio de almacenamiento compartido se instalará sobre la máquina centos01, el cual será exportado a los nodos centos02 y centos03 a través del driver iSCSI (Internet Small Computer Systems Interface).


iSCSI permite la interconexión directa entre dispositivos de almacenamiento y computadores, encapsulando para ello el protocolo SCSI (familia de protocolos para comunicaciones con dispositivos de entrada/salida, especialmente dispositivos de almacenamiento) a través de una red TCP/IP. iSCSI puede utilizar tarjetas hardware dedicadas o emplear iniciadores iSCSI junto con targets (u objetivos) SCSI para establecer la conectividad a través de tarjetas Ethernet. En este artículo se empleará la segunda opción.

Cada una de las máquinas deberá tener registrado los nombres de todos los nodos en el fichero /etc/hosts.
[... ~]# cat /etc/hosts
...
192.168.1.11 centos01 centos01.local
192.168.1.12 centos02 centos02.local
192.168.1.13 centos03 centos03.local

SELinux e iptables deberán estar desactivados en los tres nodos. Al final del artículo veremos la forma de configurarlos correctamente para que no interfieran en el sistema de almacenamiento.

[... ~]# setenforce 0

[... ~]# service iptables stop

Lo primero que vamos a hacer es instalar el software necesario en los tres nodos.
[root@centos01 ~]# yum install lvm2-cluster rgmanager gfs2-utils scsi-target-utils

[root@centos02 ~]# yum install lvm2-cluster rgmanager gfs2-utils iscsi-initiator-utils

[root@centos03 ~]# yum install lvm2-cluster rgmanager gfs2-utils iscsi-initiator-utils

En el nodo centos01 editaremos el fichero de configuración del demonio tgtd (encargado de servir los espacios de almacenamiento compartido), indicando el volumen o dispositivo a exportar, el nombre de usuario y contraseña que será necesario emplear por parte de los clientes para poder conectarse al volumen, y las direcciones IP de los clientes a los que se les estará permitido conectarse.

El volumen servidor se conoce como objetivo y es definido a través de un nombre cualificado. El estándar iSCSI establece que tanto los objetivos como los iniciadores tienen que tener un nombre que siga el patrón iqn.[yyyy-mm].[dominio invertido]:[identificador].

Por último, haremos que el servicio tgtd no sea persistente tras sucesivos reinicios de la máquina, ya que como veremos más adelante, será el propio cluster el encargado de iniciarlo y detenerlo automáticamente.

[root@centos01 ~]# cat /etc/tgt/targets.conf
<target iqn.2009-08.local:vol00>
backing-store /dev/VolGroup01/LogVol00
incominguser iscsi_user d6m1p9
initiator-address 192.168.1.12
initiator-address 192.168.1.13
</target>

[root@centos01 ~]# chkconfig tgtd off

Y en los nodos centos02 y centos03 haremos lo mismo pero con los demonios iniciadores (iscsid e iscsi). En el fichero de configuración especificaremos los datos de autenticación para poder descubrir el volumen y conectarnos a él.
[... ~]# cat /etc/iscsi/iscsid.conf
...
node.session.auth.authmethod = CHAP
node.session.auth.username = iscsi_user
node.session.auth.password = d6m1p9
discovery.sendtargets.auth.authmethod = CHAP
discovery.sendtargets.auth.username = iscsi_user
discovery.sendtargets.auth.password = d6m1p9
node.conn[0].timeo.noop_out_interval = 15
node.conn[0].timeo.noop_out_timeout = 15

[... ~]# chkconfig iscsid off

[... ~]# chkconfig iscsi off

Seguidamente vamos a crear el volumen lógico que se empleará como espacio compartido en centos01, empleando para ello una partición de 64 GB que ya tendremos creada previamente y etiquetada como Linux LVM.
[root@centos01 ~]# fdisk -l
...
Disposit. Inicio Comienzo Fin Bloques Id Sistema
/dev/sdb1 1 8354 67103473+ 8e Linux LVM

Primero habrá que crear un volumen físico sobre esa partición, después el grupo de volúmenes (VolGroup01) y por último el volumen lógico (LogVol00).
[root@centos01 ~]# pvcreate /dev/sdb1

[root@centos01 ~]# vgcreate VolGroup01 /dev/sdb1

[root@centos01 ~]# lvcreate -l 100%FREE -n LogVol00 VolGroup01

Una vez que ya se tenga el volumen lógico, crearemos dentro de él un sistema de archivos GFS2. El parámetro lock_dlm indica el protocolo de bloqueo a emplear, siendo lock_dlm (DLM - Distributed Lock Manager) para el caso de acceso concurrente y lock_nolock para el caso de acceso de un único nodo. Con la opción de -t se especifica el nombre del cluster y el nombre que le queremos dar al sistema de archivos, y con la opción -j se indica el número de nodos que accederán concurrentemente al sistema de archivos.
[root@centos01 ~]# mkfs.gfs2 -p lock_dlm -t mycluster:gfs2_data -j 3 /dev/VolGroup01/LogVol00

Una vez construido el volumen, reiniciaremos el servicio tgtd y haremos que los nodos centos02 y centos03 descubran ese espacio de almacenamiento ofrecido por centos01. Cuando se realice la operación, dicha información quedará registrada de forma permanente en los directorios /var/lib/iscsi/nodes/ y /var/lib/iscsi/send_targets/.

De esta forma cada vez que posteriormente se inicie el cluster, se utilizarán dichos datos para conectarse. Si en un momento dado se quiere prescindir de dicho volumen, habría que eliminarlo de los directorios mencionados, o si por ejemplo se quiere añadir un nuevo espacio de almacenamiento compartido, habría que volver a ejecutar el comando "iscsiadm -m discovery..." para descubrirlo previamente.

Decir también que una vez que se tiene registrado un espacio de almacenamiento, el demonio encargado de realizar su importación será iscsi.
[root@centos01 ~]# service tgtd restart

[... ~]# service iscsid restart

[... ~]# iscsiadm -m discovery -t sendtargets -p centos01.local
192.168.1.11:3260,1 iqn.2009-08.local:vol00

[... ~]# ls /var/lib/iscsi/nodes/
iqn.2009-08.local:vol00

[... ~]# ls /var/lib/iscsi/send_targets/
centos01.local,3260

Para ver los dispositivos exportados por el servidor centos01 se puede ejecutar el siguiente comando:
[root@centos01 ~]# tgtadm --lld iscsi --op show --mode target

A continuación se va a crear un archivo denominado cluster.conf el cual refleje la arquitectura de los tres nodos (deberá estar situado en las tres máquinas).
[... ~]# cat /etc/cluster/cluster.conf
<?xml version="1.0"?>
<cluster alias="mycluster" config_version="1" name="mycluster">
<fence_daemon clean_start="0" post_fail_delay="0" post_join_delay="3"/>
<clusternodes>
<clusternode name="centos03.local" nodeid="1" votes="1">
<fence>
<method name="1">
<device name="centos03.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
<clusternode name="centos02.local" nodeid="2" votes="1">
<fence>
<method name="1">
<device name="centos02.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
<clusternode name="centos01.local" nodeid="3" votes="1">
<fence>
<method name="1">
<device name="centos01.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
</clusternodes>
<cman/>
<fencedevices>
<fencedevice agent="fence_scsi" name="iscsi"/>
</fencedevices>
<rm>
<failoverdomains>
<failoverdomain name="failover_centos01" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos01.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos02" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos02.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos03" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos03.local" priority="1"/>
</failoverdomain>
</failoverdomains>
<resources>
<script file="/etc/init.d/iscsi" name="iscsi"/>
<script file="/etc/init.d/iscsid" name="iscsid"/>
<script file="/etc/init.d/tgtd" name="tgtd"/>
<clusterfs device="/dev/sdb" force_unmount="1" fsid="45982" fstype="gfs2" mountpoint="/mnt/gfs2_iscsi/" name="resource_gfs2_iscsi" self_fence="0"/>
</resources>
<service autostart="1" domain="failover_centos01" exclusive="0" name="service_centos01">
<script ref="tgtd"/>
</service>
<service autostart="1" domain="failover_centos02" exclusive="0" name="service_centos02">
<script ref="iscsid">
<script ref="iscsi">
<clusterfs ref="resource_gfs2_iscsi"/>
</script>
</script>
</service>
<service autostart="1" domain="failover_centos03" exclusive="0" name="service_centos03">
<script ref="iscsid">
<script ref="iscsi">
<clusterfs ref="resource_gfs2_iscsi"/>
</script>
</script>
</service>
</rm>
</cluster>

En una primera sección (clusternodes) se definen los nombres de los tres nodos (clusternode name) así como su método fencing asociado. El fencing viene a ser una especie de protección o de bloqueo que hace que los nodos esperen en esa "barrera" para poder sincronizarse.

Para el caso del ejemplo anterior, se ha declarado un dispositivo (fencedevice) de tipo fence_scsi en el nodo centos01, y a continuación se ha asociado a los tres nodos (fence). Esto significa que si por ejemplo iniciamos centos01, éste esperará a finalizar su proceso de arranque hasta que los otros dos nodos se hayan conectado al servidor iSCSI, o si por ejemplo arrancamos centos02 y centos03, y centos01 todavía no está inicializado, esos dos nodos esperarán hasta que el servicio iSCSI esté listo antes de lanzar el cliente.

La otra sección principal del fichero de configuración es la de los recursos. Se han definido cuatro recursos: los scripts de los iniciadores iSCSI (iscsi e iscsid), el script de gestión del objetivo iSCSI (tgtd) y un volumen a ser montado.

Cuando se importe automáticamente el volumen exportado en los nodos centos02 y centos03, éste será accesible a través del dispositivo /dev/sdb (cuando un dispositivo iSCSI es importado, se crea un nuevo dispositivo de bloque de igual forma que si se añadiera un nuevo disco duro).

También se ha creado un dominio (failoverdomain) exclusivo para cada uno de los nodos. De esta forma podremos asociar posteriormente a cada uno de los dominios un determinado servicio (service), el cual iniciará y detendrá ciertos recursos (script ref, clusterfs, ...).

Así de esta forma el servicio service_centos02 hará que cuando se inicie automáticamente (autostart="1"), se ejecute en el nodo centos02 el script iscsid, a continuación el script iscsi y por último, se monte el volumen importado sobre el directorio /mnt/gfs2_iscsi/, el cual tendremos que crear previamente en los nodos centos02 y centos03.
[... ~]# mkdir /mnt/gfs2_iscsi

Ahora sólo tendremos que reiniciar los demonios gfs2, cman, rgmanager y clvmd en cada uno de los nodos, y mediante el comando chkconfig haremos que dichos demonios se inicien automáticamente cada vez que arranque el nodo.
[... ~]# service gfs2 restart

[... ~]# service cman restart

[... ~]# service rgmanager restart

[... ~]# service clvmd restart


[... ~]# chkconfig gfs2 on

[... ~]# chkconfig cman on

[... ~]# chkconfig rgmanager on

[... ~]# chkconfig clvmd on

Si ejecutamos el comando clustat, podremos ver la configuración actual del cluster que acabamos de levantar. Por un lado se tiene la lista de miembros del cluster (Member Name) y por el otro, la lista de servicios definidos (Service Name), así como su propietario (Owner) y estado (State).
[root@centos01 ~]# clustat
Cluster Status for mycluster @ Thu Aug 6 12:55:51 2009
Member Status: Quorate

Member Name ID Status
------ ---- ---- ------
centos03.local 1 Online, rgmanager
centos02.local 2 Online, rgmanager
centos01.local 3 Online, Local, rgmanager

Service Name Owner (Last) State
------- ---- ----- ------ -----
service:service_centos01 centos01.local started
service:service_centos02 centos02.local started
service:service_centos03 centos03.local started

Si en un momento dado deseamos conocer el número de nodos asociados al sistema GFS2, podremos ejecutar el siguiente comando:
[root@centos02 ~]# gfs2_tool journals /mnt/gfs2_iscsi/
journal2 - 128MB
journal1 - 128MB
journal0 - 128MB
3 journal(s) found.

Aug 10, 2009

Almacenamiento compartido en red: GFS2 + GNBD (II)

En esta segunda parte del artículo Almacenamiento compartido en red: GFS2 + GNBD, vamos a ver cómo securizar la infraestructura con SELinux e iptables.

SELinux

Si se tiene activado SELinux con la opción de enforcing (bloqueo), éste va a impedir el funcionamiento normal del cluster bloqueando ciertas acciones que en base a sus políticas de seguridad que trae por defecto, no son correctas o no están permitidas.

La solución pasa por crear un módulo de política local para SELinux que permita dichos accesos. Este módulo se puede generar a partir de los eventos registrados en el archivo audit.log.

Primero vamos a activar SELinux en modo permisivo en todos los nodos. Dicha opción habrá que establecerla en su fichero de configuración. También habrá que reiniciar las máquinas para que todos los ficheros se etiqueten correctamente.
[... ~]# vim /etc/selinux/config
...
SELINUX=permissive
SELINUXTYPE=targeted

SELinux en modo permisivo registrará las alertas de seguridad en el fichero audit.log pero no bloqueará las acciones.

A continuación vamos a vaciar el fichero de uno de estos nodos (por ejemplo centos01); seguidamente detendremos e iniciaremos el cluster en todos los nodos y a partir de los eventos registrados en el archivo audit.log, generaremos un módulo de política local (cluster.te) y lo instalaremos.
[root@centos01 ~]# >/var/log/audit/audit.log

[root@centos01 ~]# service gfs2 restart
[root@centos01 ~]# service cman restart
[root@centos01 ~]# service rgmanager restart
[root@centos01 ~]# service clvmd restart

[root@centos01 ~]# audit2allow -m local -l -i /var/log/audit/audit.log > cluster.te

[root@centos01 ~]# cat cluster.te
module local 1.0;

require {
type ccs_t;
type tmpfs_t;
type initrc_t;
class sem { unix_read write unix_write associate read destroy };
class shm { write unix_read unix_write associate read destroy };
class file { read write };
}

#============= ccs_t ==============
allow ccs_t initrc_t:sem { unix_read write unix_write associate read destroy };
allow ccs_t initrc_t:shm { write unix_read unix_write associate read destroy };
allow ccs_t tmpfs_t:file { read write };

Antes de poder instalar el módulo, habrá que compilarlo (cluster.mod) y obtener el paquete de seguridad correspondiente (cluster.pp), el cual ya podremos instalar en todos los nodos (el mismo paquete generado en centos01 lo utilizaremos en centos02 y centos03).
[root@centos01 ~]# checkmodule -M -m -o cluster.mod cluster.te

[root@centos01 ~]# semodule_package -o cluster.pp -m cluster.mod

[root@centos01 ~]# semodule -i cluster.pp

Y ya por último, para activar SELinux en modo enforcing (bloqueante) en todos los nodos ejecutaremos el comando setenforce 1. Y para hacer que este cambio sea persistente tras sucesivos reinicios de la máquina, activaremos esta opción en el fichero de configuración de SELinux.
[... ~]# setenforce 1

[... ~]# cat /etc/selinux/config
...
SELINUX=enforcing
SELINUXTYPE=targeted

Iptables

Los puertos que hay que abrir en iptables son los utilizados por los servicios cman (Cluster Manager, 5404 y 5405 UDP), gnbd (Global Network Block Device, 14567 TCP), modclusterd (16851 TCP) y dlm (Distributed Lock Manager, 21064 TCP).

A continuación se muestra el contenido del fichero de configuración de iptables para el nodo centos01 (igual que para los otros dos nodos pero con el puerto empleado por GNBD).
[root@centos01 ~]# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport ssh -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p udp -m multiport --dport 5404,5405 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 14567 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 16851 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 21064 -j ACCEPT
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j REJECT
COMMIT

[root@centos01 ~]# service iptables restart

[root@centos01 ~]# chkconfig iptables on

Y para los nodos centos02 y centos03:
[... ~]# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport ssh -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p udp -m multiport --dport 5404,5405 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 16851 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -p tcp --dport 21064 -j ACCEPT
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j REJECT
COMMIT

[... ~]# service iptables restart

[... ~]# chkconfig iptables on

Aug 3, 2009

Sistema de archivos vs Dispositivo de bloque

Compartir un dispositivo de bloque (sharing block device) viene a ser lo mismo que compartir un disco físico.

Por ejemplo, se puede tener un disco duro al que quieran acceder de forma concurrente varias máquinas. El acceso a dicho disco se puede proveer a través de diferentes redes de almacenamiento, también conocidas como redes SAN (Store Area Network).

Una SAN es una red dedicada de alta rendimiento destinada a la transferencia de datos, la cual permite conectar directamente los dispositivos de almacenamiento a los equipos a través de fibra óptica, tarjetas iSCSI (Internet Small Computer Systems Interface) u opciones mucho más económicas como por ejemplo drivers GNBD (Global Network Block Device):

  • SAN Fibre Channel: destinada a la interconexión directa a través de fibra óptica entre dispositivos de almacenamiento y máquinas.
  • SAN iSCSI: destinada a la interconexión directa entre dispositivos de almacenamiento y máquinas a través de una red TCP/IP. iSCSI es un estándar oficial que permite encapsular el protocolo SCSI (familia de protocolos para comunicaciones con dispositivos de entrada/salida, especialmente dispositivos de almacenamiento) sobre redes TCP/IP. Las tarjetas iSCSI resultan mucho más económicas que las líneas de fibra, además de mantener la compatibilidad con las infraestructuras Ethernet ya existentes, así como las ventajas de las redes IP en cuanto a administración, escalabilidad, seguridad y coste se refiere.
  • SAN GNBD: proporciona acceso a almacenamiento de bloques sobre una red Ethernet. GNBD es una solución totalmente software (a diferencia de Fibre Channel que es hardware e iSCSI que es un modelo híbrido - es hardware cuando emplea tarjetas dedicadas o software si su comportamiento se emula -) muy económica que permite compartir de forma directa un dispositivo de bloque a través de una LAN.

La principal ventaja de una red de almacenamiento es que permite a los datos ser transferidos directamente entre discos y máquinas, saltándose el cuello de botella impuesto por el servidor y el control de acceso de la red.



Ese dispositivo de bloque que va a ser exportado en crudo a varias máquinas necesita tener un sistema de ficheros. Podríamos pensar por ejemplo en ext3, pero este sistema de ficheros no nos valdría ya que no está diseñado para arbitrar bloqueos entre accesos, y en consecuencia lo que podría ocurrir si se montase es una corrupción de datos.

En base a ello surgieron sistemas de archivos como GFS (Global File System), GFS2 o OCFS (Oracle Cluster File System), que sí permite que varios equipos puedan acceder de forma concurrente al mismo sistema de ficheros sin ningún tipo de problema.

Por otra parte, compartir un sistema de archivos (sharing file system) significa compartir un directorio que ya ha sido montado y el cual contiene un sistema de archivos cualquiera (ext3, NTFS, GFS2, etc.). Ese directorio lo podemos exportar a otras máquinas por ejemplo a través de Samba o NFS (Network File System). NFS por ejemplo proporciona control de acceso sobre el sistema de archivo montado, permitiendo de esta forma que varios nodos puedan acceder concurrentemente sin ningún tipo de problema.



Otra alternativa a NFS puede ser por ejemplo GlusterFS, que además de permitir exportar un sistema de archivos como hace NFS, incorpora otras mejoras adicionales: almacenamiento distribuido, replicado, alto rendimiento, escalabilidad, etc. NFS o GlusterFS no permiten exportar dispositivos de bloque (por ejemplo directamente una partición /dev/sda1).

Y ya por último, ese área de almacenamiento compartido (sistema de archivos o dispositivo de bloque) al que accederán varios nodos tiene un punto de fallo: si ese espacio se cayera se perdería el acceso a la información.



La solución pasa por construir un espejo activo-activo o activo-pasivo de ese espacio de almacenamiento, ya sea un dispositivo de bloque o un sistema de archivos ya montado, de tal forma que si se pierde el acceso al sistema principal siempre exista una copia replicada. GlusterFS o DRBD (Distributed Replicated Block Device) son aplicaciones ideadas para mantener un mirror de un sistema de almacenamiento en tiempo real.

GlusterFS se puede emplear para hacer espejos de sistemas de archivos ya montados (Ej. - /home) y DRBD para dispositivos de bloque en crudo (Ej. - /dev/VolGroup00/LogVol00).