jueves, diciembre 08, 2005

MLdonkey en mi servidor

Aprovechando que tengo un servidor actualizado en casa (y un fin de semana muy largo...) he decidio instalar el MLdonkey para realizar alguna descarga de copias privadas desde redes P2P. De esta forma, trato de evitar que mi hermano deje encendido el super-AMD, esa bestia de consumo de electricidad ,y aprovechar el pentium II para estos menesteres. Pero soy un poco paranoico en lo que se refiere a la seguridad...

En la actualidad sólo tengo abierto en la máquina servidora el puerto TCP/22 para el ssh y he configurado el servidor SSH de forma robusta. Sin embargo, los programas P2P son un autentico pozo sin fondo de vulnerabilidades. MLdonkey no es ni mucho menos la excepción. Se trata de un monstruo que soporta una multitud de protocolos (eDonkey, Overnet, Kadmelia, Gnutella, FastTrack, ...), ademas de sus propias herramientas de gestión (telnet, web, chat, ...). Ésto supone un número grande de puertos abiertos en nuestro ordenador, puertos que en caso de que el programa esté mal configurado o tenga vulnerabilidades podrían ser utilizados por un cracker para entrar en nuestra máquina.

# fstat | grep mldonkey.*internet
mldonkey mldonkey 19306 5* internet dgram udp *:1290
mldonkey mldonkey 19306 6* internet stream tcp 0xd4d624b4 *:4662
mldonkey mldonkey 19306 10* internet dgram udp *:4666
mldonkey mldonkey 19306 11* internet dgram udp *:15586
mldonkey mldonkey 19306 12* internet stream tcp 0xd4d62644 *:15586
mldonkey mldonkey 19306 13* internet dgram udp *:20995
mldonkey mldonkey 19306 14* internet stream tcp 0xd4d627d4 *:4080
mldonkey mldonkey 19306 15* internet stream tcp 0xd4d62964 *:4000
mldonkey mldonkey 19306 16* internet stream tcp 0xd4d62af4 *:4002
mldonkey mldonkey 19306 17* internet stream tcp 0xd4d62c84 *:0
mldonkey mldonkey 19306 18* internet stream tcp 0xd4d62e14 *:4001
mldonkey mldonkey 19306 19* internet stream tcp 0xd4d4b008 *:1213

No quería que el mldonkey comprometiese la seguridad de todo el servidor, así que como tenía un puente largo... decidí instalarlo en un ambiente chroot. La idea es limitar la ejecución del servicio MLdonkey en un directorio. Así, si el MLdonkey es crackeado, el cracker sólo podrá acceder a los ficheros bajo ese directorio. No podría acceder al resto del sistema Unix ni aunque adquiera permisos de root.

Vayamos paso a paso... Lo primero es instalar el MLdonkey en OpenBSD.

# export PKG_PATH=ftp://ftp.rediris.es/mirror/OpenBSD/pub/OpenBSD/3.8/packages/i386
# pkg_add ${PKG_PATH}/mldonkey-2.5.28.1

Una vez instalado, se decide la ubicación del chroot en el sistema, en mi caso /home/chroot/mldonkey. La gran pega con la que me encontré es que el paquete MLdonkey de OpenBSD está compilado con librerias dinámicas. Ésto obligaba a copiar las librerías a mi ambiente chroot para que el ejecutable pueda hacer uso de ellas. Para averiguar las librerías dinamicas de un binario se puede probar con los comandos ldd y strings.

# ldd /usr/local/bin/mldonkey
/usr/local/bin/mldonkey:
Start End Type Ref Name
00000000 00000000 exe 1 /usr/local/bin/mldonkey
010d5000 210dd000 rlib 1 /usr/lib/libz.so.4.1
0a311000 2a318000 rlib 1 /usr/lib/libm.so.2.0
0516f000 25178000 rlib 1 /usr/lib/libpthread.so.6.1
0903d000 2906e000 rlib 1 /usr/lib/libc.so.38.2
062ac000 062ac000 rtld 1 /usr/libexec/ld.so
# strings /usr/local/bin/mldonkey | grep lib
/usr/libexec/ld.so
libz.so.4.1
libm.so.2.0
libpthread.so.6.1
libc.so.38.2
Zlib.Error
Zlib.deflateInit
Zlib.deflate
Zlib.deflateEnd
Zlib.inflateInit
...

Bien, en principio son 4 librerías (libz, libm, libc y libpthread) las que tengo copiar más el linkador (/usr/libexec/ld.so). El problema es que estas librerías pueden tener dependencias de otras librerías o ejecutables.

# strings /usr/lib/libc.so.38.2 | grep lib
_yplib_timeout
/usr/src/lib/libc/net/inet_net_pton.c
/usr/libexec/auth/login_%s
/usr/src/lib/libc/gen/login_cap.c
libc
# ls /usr/libexec/auth/login_*
/usr/libexec/auth/login_activ /usr/libexec/auth/login_radius
/usr/libexec/auth/login_chpass /usr/libexec/auth/login_reject
/usr/libexec/auth/login_crypto /usr/libexec/auth/login_skey
/usr/libexec/auth/login_krb5 /usr/libexec/auth/login_snk
/usr/libexec/auth/login_krb5-or-pwd /usr/libexec/auth/login_tis
/usr/libexec/auth/login_lchpass /usr/libexec/auth/login_token
/usr/libexec/auth/login_passwd

Parece ser que la cosa se complica. En realidad creo que debería copiar tambien estos programas en el entorno chroot. Pero...

# ldd /usr/libexec/auth/login_passwd
/usr/libexec/auth/login_passwd:
Start End Type Ref Name
00000000 00000000 exe 1 /usr/libexec/auth/login_passwd
05246000 2524a000 rlib 1 /usr/lib/libutil.so.11.0
014fd000 2152e000 rlib 1 /usr/lib/libc.so.38.2
091a7000 091a7000 rtld 1 /usr/libexec/ld.so


¡¡¡La historia interminable!!! Al final decidí copiar al entorno chroot exclusivamente las 4 librerias iniciales y el linkador. Obviando las "dependencias" de libc.

# cd /home/chroot/mldonkey
# mkdir -p home/mldonkey
# chown -R mldonkey:mldonkey home/mldonkey
# mkdir -p usr/local/bin/mldonkey
# mkdir etc
# mkdir usr/lib
# mkdir usr/libexec
# cp /usr/local/bin/mldonkey usr/local/bin/
# cp /usr/lib/libc.* usr/lib
# cp /usr/lib/libz.* usr/lib
# cp /usr/lib/libpthread.* usr/lib
# cp /usr/libexec/ld.so usr/libexec


Además, es necesario copiar al chroot los archivos de configuracion passwd y group. Pero es suficiente con que estos ficheros tengan exclusivamente los usuarios root y mldonkey, asi como sus respectivos grupos, ya que en el chroot no va a haber otros usuarios/grupos diferentes. A parte creé un pequeño script de arranque del servidor en el directorio raiz del chroot (es decir en /home/chroot/mldonkey), para lo cual tuve que copiar el interprete sh que afortunadamente no tiene dependencias con librerías dinámicas.

# mkdir etc
# cp /etc/passwd etc <- borrando todos los usuarios salvo root y mldonkey
# cp /etc/groups etc <- borrando todos los grupos salvo wheel y mldonkey
# mkdir bin
# cp /bin/sh bin
# mkdir var/log
# touch var/log/mldonkey.log
# chown mldonkey:mldonkey var/log/mldonkey.log
# vim /home/chroot/mldonkey/init-mldonkey.sh
#!/bin/sh
cd /home/mldonkey
/usr/local/bin/mldonkey >> /var/log/mldonkey.log 2&>1

A continuación, solo falta lanzar el entorno chroot con el siguiente comando:

# chroot -g mldonkey -u mldonkey /home/mldonkey/chroot /init-mldonkey.sh

De esta forma, ya tenemos el servidor MLdonkey ejecutandose en el chroot /home/mldonkey/chroot. Para finalizar, modifique la configuración del cortafuegos PF de OpenBSD. Mi intención era limitar los puertos de herramientas administrativas de MLdonkey a mi intranet y permitir el acceso desde Internet de los puertos asociados a la red eDonkey, Overnet y Kadmelia.

# vim /etc/pf.conf
if="rl0"
ip="192.168.1.2"
net="192.168.1.0/24"

# Servicios:
# ----------
#
# Por ahora solo se han habilitado los servicios mldonkey y ssh. Para ello,
# se necesita administrar los siguientes puertos:
# SSH:
# TCP 22
# MLDONKEY:
# TCP 4000 -> telnet administracion
# TCP 4001 -> puerto de gui
# TCP 4002 -> puerto de chat
# TCP 4080 -> web administracion
# TCP 1213 -> puerto de gift
# UDP y TCP 15586 -> Overnet
# TCP 4662 -> edonkey
# UDP 4666 -> edonkey
# UDP (y creo TCP tb) 20995 -> kad

tcp_lan = "{22, 4000, 4001, 4002, 4080, 15586, 4662, 20995}"
tcp_inet = "{22, 15586, 4662, 20995}"
udp_lan = "{15586, 4666, 20995}"
udp_inet = "{15586, 4666, 20995}"
#icmp_types = "echoreq"

set optimization normal
set limit { states 10000, frags 5000 }
set block-policy drop
scrub in all

block all
pass quick on lo0 all
pass in on $if proto tcp from any to $ip port $tcp_inet flags S/SA keep state
pass in on $if proto udp from any to $ip port $udp_inet keep state
pass in on $if proto tcp from $net to $ip port $tcp_lan flags S/SA keep state
pass in on $if proto udp from $net to $ip port $udp_lan keep state
pass out on $if proto tcp all modulate state flags S/SA
pass out on $if proto { udp, icmp } all keep state


Pos eso ha sido todo. Si has durado hasta aquí es que tienes más tiempo libre en este finde que yo x-D. Al final, el MLdonkey me funciona a la perfección pero me he quedado con una gran duda que me gustaría que algún alma caritativa me la aclarese: Como se puede determinar, de una forma inequívoca que ficheros son necesarios tener disponibles en el entorno chroot para una aplicacion "x" (librerías, devices, ficheros de cabecera, ...).

3 Comments:

Anonymous Anónimo said...

Joooder, ¿cómo eres tan pero taan friki? ¿No podías limitarte a usar aMule como los demas linuxeros? Ya con eso tu ordenador estaría protegido 1000 veces mas que la media

8/12/05 17:38  
Blogger zako said...

Si y No. Aunque lo de las 1000 veces mas que la media no se si será muy correcto... Lo que esta claro es que el MLdonkey tiene mucho mejor soporte de protocolos P2P que el xMule o aMule y que además los puedo activar/desactivar a mi antojo. Lo que no se, es si *Mule tiene gestion remota por web/telnet para que yo/mishermanos si desean algo puedan acceder y no tener un *Mule en cada ordenador de casa...

Pero la miga de lo que he hecho es en el chroot. Ahora me puedo olvidar del servidor (casi) por completo. No tengo la prisa imperiosa de actualizar *Mule por cada nueva release de seguridad (o incluso esperar ansiosamente en casa a que saquen el parche) porque si me petan el mldonkey lo maximo que obtendran es una shell en un entorno chroot con permisos de mldonkey xDDD. Y aunque fuesen permisos de root no podrian acceder al sistema Unix fuera del chroot... Un windows crackeado es una putada para el dueño pero un Unix crackeado es una platafarmo para lanzar ataques y marrones para el dueño... No me gustan las sorpresas xD

De todas formas si lo he hecho así es porque instalar un *Mule no me aporta nada pero aprender a utilizar chroot.... es otra cosa.

8/12/05 18:54  
Anonymous Anónimo said...

Mmm, me has convencido. Voy a intentar instalar algo con chroot

8/12/05 20:23  

Publicar un comentario

<< Home