Cómo monté mi servidor


Las páginas que estás viendo están (Sep2006: estaban) alojadas en mi propio servidor (IP 217.126.10.173), que está en mi habitación encendido todo el día. Aquí explico las ideas que tuve durante el montaje y los respectivos problemas y soluciones.

En lo que invertí más tiempo fue en la parte teórica: pensar todos los detalles (todos) sobre papel. Cuando ya tuve todas las decisiones hechas pude empezar a montarlo y a solucionar los imprevistos.

En total tardé menos de un mes, a ritmo lento (era mi mes de vacaciones). Aquí pondré todo en orden cronológico.

Septiembre 2006: cuando lo apagué, escribí otro artículo, en donde explico las cosas que pasaron, qué problemas me dio, y qué mejoraría. Véase: Qué tal funcionó mi servidor.


  1. Problema
  2. Formas de alojar una web
  3. ¿Qué ordenador elijo?
  4. ¿Dónde meto este trasto?
  5. Lo que tengo que comprar
  6. Mi primera vez con la grimpadora
  7. Más cables
  8. ¿Qué sistema operativo le pongo?
  9. Particiones
  10. Hostname
  11. Necesito nuevo kernel...
  12. ¿y qué kernel le pongo?
  13. Parches del kernel
  14. make menuconfig
  15. La maldita 100tcl no va
  16. Kernel monolítico
  17. 100 Mbits
  18. Paquetes
  19. Necesito poco consumo
  20. Están pasando cosas...
  21. No al ARP poisoning
  22. Acceso remoto
  23. ¿Qué hora es?
  24. Problemas con cron
  25. Usuarios y grupos
  26. El servidor web
  27. Si no es Apache, ¿cuál elijo?
  28. CGIs, ¿qué es eso?
  29. Virtual hosting... vhosting para los amigos
  30. El entorno para chroot
  31. Opciones de thttpd
  32. Logs
  33. Un watchdog para el servidor web
  34. Servidor FTP
  35. Acceso al FTP desde fuera
  36. Empiezan los problemas serios: esto se cuelga
  37. Comparar distancias entre ordenadores
  38. No pierdo el honor; arreglo lo del cuelgue
  39. iptables
  40. Cambios en el router
  41. Cómo probé el virtual hosting yo solito
  42. Quiero un contador; no tengo PHP
  43. Copias de seguridad periódicas
  44. Trabajar cómodamente en mi web
  45. Cambios en el dominio
  46. Conclusiones
  47. Sobre este documento




Problema

Primero, algo de introducción y de pruebas con la cámara. Éste soy yo (Daniel Clemente Laboreo, 19 años), éste es mi ordenador (Celeron 800, 192 Mb RAM), aquí es donde vivo (Gavà, Barcelona), y esto es una foto del sol.

Mi página web, www.danielclemente.com, ha pasado por muchos servidores gratuitos (galeon.com, freewebz, iespana, host.sk, y más) y quería algo estable, fácil de actualizar (porque sinó la página también es 'estable'), y más elegante que los sitios gratuitos y llenos de publicidad.


Formas de alojar una web

Pensé en:

Me decidí por la última opción por ser la más divertida de todas.


¿Qué ordenador elijo?

Lo más importante para mí al decidir fue:

  1. Que gastara poca electricidad
  2. Que no hiciera ruido

Todo está relacionado, y además implica que el ordenador tenía que ser poco potente, en el sentido estricto de la palabra. Lo que pagas a tu compañía eléctrica por un aparato determinado depende de su potencia (en watts) y del tiempo que haya estado encendido. Es fácil de calcular, aunque no digo que sea exacto ya que, al ser corriente alterna, lo que pagas (S) está relacionado con lo que gastas (P) mediante el factor de potencia de tu instalación eléctrica. Veamos un ejemplo del fácil:



AQUÍ METÍ LA PATA :

Estas notas de "como máximo" las he añadido después de que mucha gente haya leído el artículo y me haya corregido: cuando en una fuente pone 350 W, se refiere a la potencia máxima que puede llegar a proporcionar, pero para saber el consumo en un instante determinado hay que sumar el de la CPU, placa, disco duro, etc., y según dicen puede ser de unos 100 W (eso quiere decir que la potencia será de 100 W para arriba, hasta 350).

Act. Septiembre 2005: Hice pruebas del consumo, y mi portátil gasta 9 W, unos 6 ó 7 euros al año. Más información: ¿Cuánto gasta un ordenador?.

Continúa el artículo...



Es muy caro, por eso necesito otro ordenador. Busqué miniordenadores (mini PCs, placas micro-ATX, ITX y barebones) por Barcelona, pero lo mínimo que tenían era de 200 W (11'5 € al mes en mi casa). Pero se fabrican hasta de 50-60 W, ¡yo quería uno de esos! (serían 3 € al mes). Desgraciadamente, nos intentan convencer de que "cuanto más potente, mejor" y de que "si hace mucho ruido es porque es muy potente". Las dos cosas son mentira; lo único cierto es la definición de potencia: "cuanto más potente, más gasta".


Hay maravillas como ésta (586 a unos 200 Mhz con 128 Mb SDRAM, CompactFlash o disco duro, ...), pero salen bastante caras por el transporte desde el extranjero. Las VIA EPIA (silenciosas) son demasiado potentes para mis necesidades y además no me atrevo a comprar un aparato desconocido (para mí) sin verlo antes.


Entonces pensé en los portátiles, una muestra de lo avanzada que está la tecnología (¿por qué se sigue fabricando todo tan grande y chapucero si desde hace décadas se sabe hacer pequeño y bien?). Sólo les vi ventajas:

Yo no les veo desventajas, pero por lo que me han dicho:

OCR812

Decidí hacer lo del portátil, pero después tuve otras ideas: yo ya tenía un aparato encendido las 24 horas al día y que tenía un servidor web, pero aún no me había dado cuenta. Es mi router. Uno normal, Office Connect Remote 812 ADSL de 3Com, con una web de configuración servida por un Allegro-Software-RomPager/2.10. Probablemente tenga un sistema operativo tipo UNIX por dentro; sea cual sea me veo capaz de manejarlo e instalar nuevos programas o mi propio servidor http. El problema es que 3Com no explica a nadie cómo hacerlo ni deja intentarlo; el interior del aparato es secreto y no les interesa decirlo. No por comportarse así dan un producto mejor, ya que el OCR 812 tiene muchísimos fallos.


WRT54G

Hay otro aparato con más suerte en eso: el punto de acceso wireless Linksys WRT54G. Es tan cerrado como el que yo tengo (al principio Linksys no dio el código de todo el software GPL que usa), y también tiene fallos, como el mío. El caso es que a través de uno de esos fallos se puede acceder a todo el sistema Linux que lleva dentro y ejecutar programas, como un servidor ssh, un IDS, o un servidor web (aunque ya lleva uno para la configuración). Y el servidor sería rápido porque estaría en lo más externo de mi red.

Este AP/router lo compran a montones los linuxeros sólo por esto, pero los problemas que le veo son:

Es una pena, porque es barato, consume muy poco ( ¡¡¡ 10 W !!! o sea 60 céntimos al mes), y además de regalo me permitiría freir mi cerebro y el de los vecinos con microondas de 2'4 GHz...



Al final hice lo del portátil: por 200 € compré por Internet (de segunda mano, claro) un Toshiba Portégé 300CT: Pentium 133 MMX, 32 Mb RAM, 1'5 Gb disco duro, USB, infrarojos, PCMCIA, disquetera externa, sin CD ni red, con tarjeta de sonido, y pantalla 16:9 en la que puedo poner las X a 1024x600 :-) Lo mejor: es muy pequeño y consume muy poco: máximo 30 W (la mitad que una bombilla). En euros, 1'7 al mes. Ver fotos:


300ct_1 300ct_2 300ct_3 300ct_4


¿Dónde meto este trasto?

Tenía que buscar un sitio por mi habitación que me quedara lejos de la cama (para no oír posibles ruidos), poco caliente y al que llegaran cables. Lo dejé en la galería que hay al lado de mi habitación; aquí hay unas fotos de antes y después, a ver si descubres dónde está escondido:

sitio1 sitio2

Lo que tengo que comprar

Para integrar este ordenador en mi red necesitaba unas cosillas:


Mi primera vez con la grimpadora

Podía haber comprado cables hechos, pero quería aprender a hacer eso de 'grimpar'. Aún no he investigado por qué hay diferentes formas de ordenar los 8 cablecitos de dentro; creo que depende de si conectan router con router, PC con PC o router con PC (y se llaman MDI y MDI-X). Lo que hice fue coger un cable muy largo que ya tenía, fijarme en cómo estaba hecho y hacer lo mismo.

Puse por las dos puntas la siguiente ordenación: si se coge el latiguillo con el [futuro] cable apuntando hacia nosotros y con el trocito que sobresale por la parte de abajo, el orden de izquierda a derecha es:

verde,   verde/blanco,   naranja/blanco,   azul,   azul/blanco,   naranja,   marrón/blanco,   marrón


grimpadora

Nunca había usado una grimpadora, pero es un aparato que te lo hace todo: corta el cable, lo pela (para que queden sueltos los cablecitos de colores), y una vez que los has conseguido meter dentro en orden, chafa el plástico para que no se suelten. En unos minutos de retorcer y retorcer cablecitos ya conseguí hacer uno. Lo probé, funcionó, y puse 4 ó 5 latiguillos más sin miedo.

Tal como temía, una vez acabados los cables la grimpadora pierde toda su utilidad, así que si puedes, no te compres tú una, ¡pídesela a un amigo!



Más cables

Con tanto cable, la red irá más lenta y además cogerán bastante polvo.



cables_1 cables_2 cables_3

Por ahora mi situación es ésta; fíjate que el ordenador grande lo tengo en la galería pero la pantalla, teclado y ratón están lejos, en una mesa. Es por el ruido... sólo tengo un ventilador y el de la fuente de alimentación; los dos Enermax (que fabrica sólo componentes silenciosos), pero aún así se oyen mucho incluso a la mínima velocidad. Y eso que la caja está forrada con material aislante acústico... Además, mi CPU y mi pantalla también hacen mucho ruido, pero esa es otra larga historia que me gustaría poder explicar algún día. [HECHO].



30m 30m 30m 30m 30m 30m

Adivina de quién es este cable de 30 metros que une mi switch con el router OCR 812. Fíjate en cómo atraviesa la puerta y demás obstáculos... :-)


¿Qué sistema operativo le pongo?

Creo que no hay dudas... Windows Server 2003 es el mejor. Me sale un 33% más barato que Linux, la instalación es un 70% más fácil, es mucho más seguro y además viene con IIS, que es un 276% más rápido que los servidores web de Linux, según cuentan algunas empresas que no tienen mejores cosas que hacer.

Dejando aparte todas las chorradas que pueda decir la gente que quiere tu dinero, básicamente tenía que elegir entre Linux o no-Linux (*BSD, Hurd, otros). He usado OpenBSD algún tiempo, pero no me siento capaz de hacer un sistema seguro porque no me lo conozco tanto como Linux. Pero me gustaría más poner un BSD, porque Linux tiene demasiados fallos (demasiados = 1 o más), y más que los BSD.


tux

Entonces me tocó elegir distribución... no pensé mucho; quería Debian por el apt-get (para las actualizaciones de seguridad, porque no quiero tener que enterarme por casualidad de fallos graves). Elegí una estable porque no me importaba tener programas viejos; los quería seguros, pocos en número y que no hubiera que actualizarlos. De todas formas el kernel y los programas importantes me los compilé yo.


La instalación la hice por disquets (buuuuuuffff.......) Recuerdo que el portátil no tiene CD ni red.



Particiones

No se puede poner todo mezclado en una partición raíz por el tema de los logs: si algún gracioso empieza a generar accesos a mi sitio, empezará a gastar espacio de mi disco. Imaginemos que es muy gracioso y que sigue hasta llenarlo todo; eso podría afectar al funcionamiento de otros programas (no habría espacio ni para los ficheros temporales). Por eso los logs van en una partición aparte, para que si se llena entera no moleste a todo lo demás.

Naturalmente, quiero un sistema de archivos con journalling por si se apaga a lo bestia. Elegí ext3 porque se lleva muy bien con Linux, y porque no veo muchas diferencias entre los otros que he probado, xfs y reiserfs.


Para entretenerme algo más, los servidores estarán en un entorno chroot (lo explico más adelante), y todo este entorno (que incluye los logs) tendrá su propia partición. En total me quedan los 1625 Mb así:


hda1 /home 150 Ya cabe lo necesario
hda2 /f 500 El entorno chroot, con las webs
hda5 /f/log 50 Los logs
hda6 swap 50 (Luego decidí que no la quería)
hda4 / 875 Para todo lo demás

¿Por qué no quiero swap? Bueno, creo que 32 Mb de RAM son suficientes, pero lo importante es lo siguiente: el disco duro va a estar la mayor parte del tiempo apagado. Cuando haga falta grabar algo en swap, habría que volver a hacer girar el disco, y eso gasta electricidad, tiempo y además hace ruido. De eso se estropea innecesariamente el motor.


Hostname

Esta vez no perdí mucho tiempo pensando... se llamará amarok. En realidad es un disco de Mike Oldfield que me gusta mucho, pero lo elegí por la misma razón que él: suena bien. Quiere decir 'lobo' en algún idioma nórdico. Mis otros aparatos con nombre en red son pc (el grande, un nombre muy original) y trasto, un Pentium-I 120 con 16 Mb de RAM y que ocupa más que el mío.


Necesito nuevo kernel...

...pero no tengo red ni CD, y estoy cansado de los disquets. La tarjeta de red PCMCIA me funcionará después, con el kernel nuevo.

Lo que hice fue pasarle los archivos por wireless (en mi universidad, la UPC), con una tarjeta que no costó mucho configurar. Una vez hecho esto ya no usé más el wireless.


¿y qué kernel le pongo?

En principio yo quería un 2.2, porque es el que lleva más años probando su seguridad y porque no necesito características especiales; pero luego descubrí que si conseguía hacerlo funcionar era a base de parches: para ext3, para la tarjeta de red, para pcmcia, ... en fin, que no lo veía muy elegante. Al final me decidí por un 2.4.24 sólo por esto, por ser más 'limpio'. El 2.6 no me sirve, es demasiado nuevo para poner en un servidor.


Parches del kernel

Al 2.4.24 le apliqué el parche patch-2.4.25-pre8, que contiene las cosas nuevas que se le añadieron al 2.4.24 cuando lo bajé.

Tenía interés especial en 'arreglar' una cosa que me parece que deberían tener todos los sistemas operativos: la sección de datos de la pila no debe ser ejecutable. Así se evitan los 'buffer overflows' en los que se mete código en un sitio donde sólo tendría que haber datos (texto, números, ... pero no instrucciones).

Hay varios parches que hacen estas cosas, por ejemplo GrSecurity, OpenWall, HAP, LIDS o StackGuard. Me quedé con OpenWall porque es mucho más sencillo y menos ambicioso que GrSecurity, y porque funciona también en kernels 2.2 (por si acaso...). Cuidado: esto no hace maravillas; si hay algún bug de BOF, alguien puede explotarlo si le interesa, pero le costará más. Como ejemplo hay que leer la Phrack 56, 0x05 (o en español).

En total recompilé unas 20 veces el kernel... pero ya tenía las ideas claras desde el principio, así que me quedó bastante bien a la primera; el resto fue para arreglar imprevistos (ver siguiente punto). Los detalles:

La maldita 100tcl no va

La PCMCIA de red, la meto y no pasa nada (ni logs ni ruidos ni luces ni nada). Por un mensaje perdido en Internet descubro la posibilidad de que se arregle poniendo en la BIOS que las PC Card han de funcionar en modo 16 bits. Lo pruebo, y funciona (la detecta). Me pasé días con esto.


Kernel monolítico

Pues sí, esto me dio algunos problemas, sobre todo con la tarjeta de red PCMCIA (que puede estar conectada o desconectada). Al final conseguí que todo fuera muchísimo mejor (cargaba lo necesario nada más conectar, instantáneamente) y pude quitar el paquete pcmcia-cs, porque ya nadie tenía que decidir cuál era el módulo apropiado para cargar.

Por cierto, el kernel me ocupó 724 kb, los módulos nada... :-) y carga rapidísimo.


100 Mbits

Cuando me fue la tarjeta de red, descubrí estas velocidades de 1'5 Mb/s. ¡Ojalá el ADSL estándar en España fuera así de rápido!

Por suerte había preparado todo para que fuera compatible con 100 Mbits: la tarjeta de red era 10/100, el switch también y la que ya tenía en mi PC también. El router 3Com 812 sólo va a 10 Mbits... :-( pero bueno, no hago muchas más conexiones por mi red.

Mi conexión al exterior era a través de un ADSL 256/128 Kbits (¡sólo 128 Kbits de subida!, eso es enviar datos a un máximo de 16 Kb/s). Además es carísimo, 45 €/mes (siempre por culpa del monopolio de Telefónica), aunque por lo menos va bien: pocos meses he notado que haya cortes de conexión.


Paquetes

Quité muchos programas que no necesitaba. Al final me quedé sólo con 129 paquetes... y con muchas cosas innecesarias y peligrosas que hacen todo más interesante, como nc, gcc, nmap o tcpdump.

El servidor web y el de ftp los compilé a mano.


Necesito poco consumo

Ajusté la BIOS para que la pantalla y el disco duro se apagaran a los 3 minutos de inactividad. Creo que ya es suficiente, porque si estuviera al mínimo (1 minuto) y alguien se pone a mirar mi página y pasa 2 minutos en cada página (si hay suerte), el disco estaría encendiéndose a cada petición y apagándose después. Creo que sale más a cuenta 3 minutos. Por cierto, que si mi BIOS no hubiera tenido esa opción, hdparm -S va muy bien.

También le mando que nunca se suspenda y que esté en el modo lento. Y ya no se me ocurren más formas de hacer que gaste menos (mmmm.... aparte de unas placas solares, pero eso es otra historia).


Están pasando cosas...

syslog.conf

En todos mis Linux configuro el syslog para que me muestre todo (*.*) por una consola libre, por ejemplo /dev/tty10, y así poder ver antes todo lo que pasa.

Me di cuenta de que, aunque yo no hiciera nada, había varias cosas que estaban ejecutándose periódicamente y que yo no había pedido, así que las quité. Quito inetd, anacron, at (no lo necesito) y desactivo esos molestos MARKs que salen periódicamente.

Además, lo dejo todo más sencillo de lo que estaba: hago que todos los logs (*.*) vayan al mismo fichero, /var/log/syslog, además de /dev/tty10 como he dicho antes. Las emergencias se mandan directamente a los usuarios conectados, y todos los demás archivos de log no los necesito; los borro. De todas formas no los iba a mirar.

Ahora ya hay tranquilidad en el syslog, interrumpida sólo por el cron cada día, semana y mes. Compruebo que los logs se roten bien; sí.


No al ARP poisoning

El ARP poisoning y los MITM son muy divertidos, pero no en mi red :-) Si alguien entra como root a mi PC de uso diario tendrá que pensar un poquito más para molestar al servidor, porque tiene la tabla ARP con MACs estáticas. Ya he probado con todo lo que conozco y ningún intento de cambiarlas ha tenido éxito.

Desgraciadamente, mi router no se deja ponerle una tabla ARP estática... no tiene esa función :-( y eso que es bastante caro.

Por cierto, también activé las SYN cookies para hacer más complicados los SYN floodings.


Acceso remoto

Por el sitio en el que he dejado escondido el portátil, más me vale tener formas de manejarlo a distancia...

Pero nada de rlogins ni chapuzas gigantescas como telnets sin contraseña. Usaré SSH para las comunicaciones, y sólo pc (el ordenador grande) podrá entrar por SSH al servidor, desde fuera no se puede [directamente]. Claro que conectándose primero al grande y desde ahí al servidor.... bueno, no doy ideas.


¿Qué hora es?

Las 5:05 de la mañana... Pero en fin, estoy de vacaciones. Bueno, a lo que iba:

Mis relojes suelen ir entre 10 y 20 minutos adelantados, y alguno se atrasa sólo. Para colmo, el portátil tiene la pila gastada y no mantiene la hora al apagarse. Existe una solución muy bonita: actualizar la hora por Internet. De eso se encarga el protocolo NTP.

En Debian he usado el programa ntpdate para sincronizarse con algunos servidores españoles; puse un script que se ejecuta al arrancar y cada día (mediante cron) y lo primero que hizo fue fallar diciendo que no había servidores apropiados:

Lo que decía: "no servers suitable for synchronization"

Lo que realmente quiere decir: "Estás usando demasiado la red, por lo que los paquetes con la hora me tardan mucho en llegar y por tanto no son exactos"

Por eso lo ejecuto cada día por la mañana a horas raras.


Por cierto, que esto de las horas me sirvió para aprender algo de terminología: CET, CEST, GMT, ...


Problemas con cron

Básicamente, uno: que yo ponía ahí ficheros ejecutables (scripts) o enlaces a ellos, pero no todos se ejecutaban. ¿Por qué? Pues porque les faltaba la primera línea:

#!/bin/sh

Y cuidado con el $PATH... porque no es lo mismo tu shell que las condiciones en las que se ejecuta lo del cron.


Usuarios y grupos

Esto también es importante pensárselo bien... poca gente usa eso de los grupos, y haciéndolo aprendí a tener cuidado con lo de los permisos (u, g, o).

Lo interesante de /etc/passwd :

root:x:0:0:root:/root:/bin/bash
webo:x:1000:1000:webo,,,:/home/webo:/bin/bash
dc:x:1001:1000:,,,:/home/dc:/bin/bash
ip:x:1002:1000:,,,:/home/ip:/bin/bash
efetepe:x:1003:1003:,,,:/home/efetepe:/bin/bash


El /etc/shadow no te lo voy a poner, pero ya te aviso de que las contraseñas son bastante absurdas (eso sí, las mías suelen ser de 20 caracteres para arriba).

O sea, que hay un grupo llamado webo, al que pertenecen los usuarios que tienen web (en este caso dc e ip). El efetepe es, como su nombre indica, para poder subir o bajar archivos fácilmente.


El servidor web

¿Qué me hace falta? Eso es lo que necesito saber. Parece que al hablar de "buen servidor web en Linux" hay que hablar de Apache, pero no quiero Apache. Tiene algún fallo (demasiados, pues no debería tener ninguno) y es muy extenso, tanto que no conseguiría aprender a manejarlo por completo. Y en mi ordenador no voy a poner cosas que no sepa usar. Además, es que no necesito todo lo que tiene Apache. Ni me gusta su licencia...

Quiero algo sencillo. Probando varios servidores diferentes empiezo a ver qué cosas ofrecen, y si me interesan. Decido que no necesito PHP por ser demasiado complicado, pero que lo de generar páginas mediante scripts de bash (que es lo que siempre había querido) se puede hacer con CGIs.

También veo lo útil que es el 'virtual hosting': asociar varios dominios a la misma IP y que el servidor decida cada vez cuál le han pedido para saber qué página dar. Eso me servirá para....... bueno, más bien les servirá a mis amigos que quieran que les aloje algo. Que asocien su dominio a mi IP y ya está, nada de frames o subcarpetas.

En total: quiero un servidor web sencillo, fácil de meter en un chroot, sin PHPs, con CGIs y con virtual hosting.


Si no es Apache, ¿cuál elijo?

Estuve mirando varios (hay muchísimos, algunos muy curiosos):

CGIs, ¿qué es eso?

Antes lo único que sabía de los CGIs era que permitían ejecutar programas en Perl y que se usaban para los contadores, pero ahora ya los he descubierto del todo.

Un CGI no es más que un programa cuya salida se mandará al visitante web. Imagina que haces un

cualquier_comando > fichero  # toda la salida se queda grabada ahí
nc -l -p 80 <fichero # servir ese fichero.... :-)

Por eso puedes hacer cosas tan bonitas como:

#!/bin/bash
echo "Content-type: text/html"
echo
fortune
cat << EOF
<br><br>Hola, esto es una prueba en HTML, <br>
<b>probando</b>, <i>probando</i>.
<br> Mi uptime:
EOF
uptime

O incluso:

#!/bin/bash
echo "Content-type: image/jpeg"; echo; cat imagen.jpg

El echo ése suelto es para ese ENTER que hay que hacer para mandar cada petición/respuesta HTTP.


Virtual hosting... vhosting para los amigos

Eso mismo. Al ponerme un servidor ya sabía que habría más cosas alojadas aparte de mi web, y ya que me he preocupado de montarlo prefiero que sirva de algo más que de contenedor para la basura que es mi web.

Mucha gente crea carpetas en su servidor, por ejemplo www.miservidor.com/~pepe, o www.serv.com/users/yo o cosas así, lo malo es que si no te gusta esa dirección tienes que hacer una redirección por HTTP, y eso es muy feo.


Lo del virtual hosting es mucho más elegante: imaginemos que Google y Slashdot leen esta web y me piden alojar sus páginas en mi servidor. Entonces los root servers de DNS traducirían google.com y slashdot.org a mi IP, 217.126.10.173.

Y si vienen de los dos sitios a mi IP, ¿cómo distingo qué página dar a cada visitante? Pues por la petición HTTP que me hacen. Ejemplo:

GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7a) Gecko/20040215
Accept: text/xml,application/xml,application/xhtml+xml,text/html, etc, etc, etc
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

Fíjate en el campo Host, ése es el que le dice qué dominio ha pedido. Con esta información, que entiende mi servidor, ya sé qué página dar, en este caso será la / (lo dice la petición GET) del host www.google.com.


Esta petición es HTTP/1.1, por tanto es obligatorio especificar el Host. El problema es que en HTTP/1.0 es opcional y en HTTP/0.9 no hay nada de eso (sólo un GET página). Puedes ver en qué consiste cada versión aquí: HTTP 0.9, HTTP 1.0, HTTP 1.1.

Por suerte no quedan muchos navegadores que usen la 0.9 (al menos yo no he visto ninguno). En todo caso, mi idea es tener como mínimo dos webs: la mía, a la que se entra desde www.danielclemente.com o danielclemente.com, y una 'por defecto' a la que se entrará si no has especificado ningún Host o si has escrito la IP a mano. Esta página tendría un índice de las páginas que alojo en mi servidor y la forma de entrar en ellas.


El entorno para chroot

Dentro del directorio /f tenía que crear una estructura de directorios y archivos propia de un sistema UNIX para que se ejecutara el servidor web y los programa CGIs. El chroot lo que hace es convertir en raíz (/) el directorio especificado, por lo que si, dentro de la jaula, el usuario root te hace un rm -rf /, sólo te habrá borrado el directorio de chroot.

Lo primero que pensé es que ya habría mini-distribuciones de Linux preparadas para esto que contengan los programas necesarios: bash, ls, gcc, perl, ... Seguro que hay, pero no busqué mucho y decidí hacerlo a mano. Descubrí que es muy fácil si se usan las herramientas apropiadas. Esta captura de pantalla deja claro el proceso ('captura' en modo texto aquí):


Ejemplo chroot

Y así con cada programa, tienes que copiar las librerías que necesita (ya sabes, man ldd si no sabes qué hace).


Opciones de thttpd

Lo bueno de elegir un servidor sencillo es que pude revisar todo el código fuente y leerme y entender por completo el manual de uso. Sabiendo manejar el programa entero, no tuve ningún problema.

thttpd no necesita archivo de configuración; todas las opciones se pasan como parámetros. Por eso me hice un script que hacía lo siguiente:


#!/bin/sh
/bin/thttpd -p 80 -d /f -r -u webo -dd web -c "\
217.126.10.173/cgi-bin/*|\
danielclemente.com/cgi-bin/*|\
www.danielclemente.com/cgi-bin/*|\
amarok/cgi-bin/*|\
172.26.0.11/cgi-bin/*\
" -l /f/log/este_mes -v

Explicación:

El proceso se arranca como demonio; para hacer pruebas va bien el -D que lo deja en primer plano.


Logs

Me hice este script que rota y archiva los logs, muy sencillo. Está en /etc/cron.monthly

#!/bin/sh
# Rotar logs. EJECUTAR EL PRIMER DÍA DE CADA MES
logs
cd /f/log

rm -f hace12meses.gz
mv hace11meses.gz hace12meses.gz
mv hace10meses.gz hace11meses.gz
mv hace9meses.gz hace10meses.gz
mv hace8meses.gz hace9meses.gz
mv hace7meses.gz hace8meses.gz
mv hace6meses.gz hace7meses.gz
mv hace5meses.gz hace6meses.gz
mv hace4meses.gz hace5meses.gz
mv hace3meses.gz hace4meses.gz
mv hace2meses.gz hace3meses.gz
mv hace1mes.gz hace2meses.gz
/bin/gzip este_mes
mv este_mes.gz hace1mes.gz

kill -HUP `pidof thttpd` || /root/servweb

Si no sabías lo que era rotar logs, pues ya lo sabes (es descartar el más viejo para que quepa uno nuevo; sólo tengo 12 posiciones). La última línea reinicia el servidor web o, en caso de que no esté activo, lo inicia.

También podía haber usado herramientas automáticas que lo hacen, como logrotate. Pero mi script es más sencillo porque tiene sólo lo que yo quiero.


Un watchdog para el servidor web

Puede que, por alguna razón rara, el proceso thttpd muera y me quede sin servidor. Por eso me hice un 'watchdog', o 'perro guardián', que comprueba periódicamente si está activo y si no lo está lo inicia. Al principio se ejecutaba cada día porque no encontré un /etc/cron.hourly (lo mímino era daily)... pura vagancia. Luego le añadí 05 *    * * *   root    /root/wdogweb al /etc/crontab para ejecutarlo cada hora a los 05 minutos.

El script es realmente sencillo y muy bonito:

#!/bin/sh
pidof thttpd || /root/servweb
# equivale a:   if ! pidof thttpd; then /root/servweb; fi

Me han comentado que hay utilidades como daemontools que se encargan de arrancar y vigilar servicios, pero ahora que ya he aprendido a usar cron creo que no me hace falta otro programa para hacer lo mismo. No digo que no sea útil; al contrario, va muy bien por si tienes muchos servidores.


Servidor FTP

Necesito uno para dos cosas:

  1. Subir/bajar archivos de la web, no sólo yo sinó cualquier otro usuario
  2. Espacio temporal para chorradas al que pueda acceder desde cualquier sitio.

Y quiero uno como el servidor web, que sea sencillo y elegante (sin chapuzas). Me miré muchos (me fue bien un 'apt-cache search ftp' en una Debian inestable), pero eran difíciles de entender, y muchos no funcionaban o directamente no compilaban por fallos en el código. Al final acabé usando 'el de siempre': mi preferido, el pure-ftpd.

Lo compilé con la opción de chroot virtual (--with-virtualchroot), que encierra a cada usuario en su directorio personal, pero si hay un enlace que lleva fuera deja seguirlo. Éste es el caso, ya que el usuario dc, por ejemplo, tiene en su home /home/dc el enlace simbólico /home/dc/web que le lleva a /f/web/danielclemente.com (su web). Sin esta opción no deja salir del $HOME de ninguna manera.

El servidor lo arranco con este comando:

/usr/local/sbin/pure-ftpd -A -B -u 100 -C 5 -4 -E -k 90

Qué hace cada cosa:

Acceso al FTP desde fuera

Quiero una cuenta FTP multiuso que sirva para dejar notas y ficheros sueltos y poder acceder desde cualquier sitio. Será casi público, pero con contraseña.

No voy a usar las cuentas de la web, porque el FTP es inseguro (va en texto plano) y no hay conexión SSH directa al servidor, por tanto no puedo usar sftp. Eso no va muy bien y puede dar problemas, pero no doy acceso SSH por seguridad (más adelante me lo pensaré).

Por tanto, lo que hice fue crear una cuenta 'basura', de nombre efetepe, grupo efetepe, y una contraseña realmente absurda.


Empiezan los problemas serios: esto se cuelga

Ahora me tocaba hacer un cortafuegos y probar la seguridad, así que le hice varios nmap como de costumbre. Lo curioso fue que al cabo de varios nmaps empezó a tener los puertos cerrados. Me extrañó, porque aún no había puesto ningún IDS, pero luego descubrí -levantándome y sacándole de su sitio- que se había quedado colgado. (Quizás es un nuevo sistema de seguridad; lo he visto en acción en las últimas versiones de Windows).

No me costó mucho descubrir cuál era el problema, ya que al pasar archivos grandes por FTP pasaba lo mismo. Curiosamente, el ping -f lo aguantaba, pero los escaneos rápidos de nmap no. Usando las opciones de velocidad de nmap, vi que se colgaba sólo con -T3 para arriba, el -T2 ya iba bien. Lo característico del -T2 es que manda los paquetes en serie, o sea uno detrás del otro. -T3 ya empieza a mandar varios a la vez, y eso es lo que hacía que se colgara la tarjeta de red PCMCIA.


Comparar distancias entre ordenadores

Haciendo pruebas con el ping -f y otros descubrí el 'ping adaptativo', estaba en la primera página del man ping. La sintaxis es ping -A host y consiste en mandar pings lo más rápido que pueda sin perder paquetes. Eso no quiere decir 'muy muy rápido', sinó lo más rápido posible. Si ve que se pierden paquetes manda más despacio.

Mandamos un ping, que viaja a través del cable, llega a su destino y vuelve en forma de respuesta. Nada más llegar mandamos otro, y así todo el rato. Por el tiempo que tardan en volver podemos adivinar cómo de lejos está el destino. Naturalmente, depende de muchas condiciones, por eso no he hablado de medir distancias sinó de comparar. Las pruebas que he hecho en mi casa son creíbles y se corresponden con la topología de mi red.

Supongo que si se llaman ICMP echo request y reply es por esto; también podemos saber cómo de lejos está una pared por el tiempo que tarda en llegar el eco.


No pierdo el honor; arreglo lo del cuelgue

La verdad es que no tenía ni idea de por qué fallaba la tarjeta de red, sólo sabía que no era normal. Probé muchas cosas sin parar, porque no puedo ir diciendo por ahí que 'mi Linux se cuelga y no sé cómo arreglarlo'. Después de tocar muchas cosas y de compilar muchos kernels, descubrí la opción mágica que lo solucionaba:

Dentro de la sección de dispositivos de red, en la del 8139too, "RealTek RTL-8139 PCI Fast Ethernet Adapter support", hay una que pone "Use PIO instead of MMIO". Hay que activarla.

Ahora aguanta sin problemas un while :; do nmap -vv -P0 -T5 -p1-65535 -r amarok; done


iptables

Nada complicado; el servidor usará FTP y HTTP desde fuera y SSH desde mi ordenador 'grande' (cuya dirección MAC es estática y por tanto siempre corresponderá a la misma IP).

Además sólo analizo las conexiones nuevas (las que sólo tienen el bit SYN activado), acepto las de loopback, no acepto UDP, y sí que dejo ICMP request y reply. Todo lo demás lo ignoro (DROP). Las conexiones salientes las acepto (para que funcione el FTP) pero el forwarding no.

Me queda este script para ejecutar al inicio:


#!/bin/sh
# Mi cortafuegos; 13/2/2004 1:49 AM, Daniel Clemente

iptables -F INPUT

iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state NEW -i lo -j ACCEPT

iptables -A INPUT -m state --state NEW -i eth0 -p tcp --dport 20 -j ACCEPT
iptables -A INPUT -m state --state NEW -i eth0 -p tcp --dport 21 -j ACCEPT

iptables -A INPUT -m state --state NEW -i eth0 -p tcp --dport 80 -j ACCEPT

iptables -A INPUT -m state --state NEW -i eth0 -s 172.26.0.2 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m state --state NEW -i eth0 -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -m state --state NEW -i eth0 -p icmp --icmp-type echo-reply -j ACCEPT

iptables -P INPUT DROP


iptables -F FORWARD
iptables -P FORWARD DROP


iptables -F OUTPUT
iptables -P OUTPUT ACCEPT


Cambios en el router

El ordenador destino por defecto es el grande, de nombre pc. Para el servidor sólo tuve que redirigirle los puertos 20, 21 y 80; el resto de puertos se refieren al ordenador grande.

Normalmente el router (OCR 812) tiene una página web de configuración en el puerto 80; la cambié al puerto 8000 de esta forma:


disable network service httpd
set network service httpd socket 8000
enable network service httpd
save all

Cómo probé el virtual hosting yo solito

Ahora necesitaba probarlo todo un poco: pedí que me hicieran unos escaneos de puertos, pero aún me quedaba mucho por probar sobre lo de servir páginas distintas dependiendo de la página pedida.

Puse dos páginas diferentes: una para cuando se entrara por 172.26.0.11 y otro para cuando se entrara por 217.126.10.173. ¿Cuál es el problema? Pues que si yo, desde el host pc (172.26.0.2), intento conectar a 217.126.10.173, la petición llega al router, y éste debería redirigirla al servidor (172.26.0.11) aplicando el NAT, pero no lo hace. No lo hace porque está configurado para aplicar estas reglas de redirección de puertos sólo a las conexiones que vienen de la red ATM que tiene configurada, o sea de fuera.

Para simular conexiones desde fuera lo más cómodo es tener una shell en algún ordenador y conectar desde ahí, pero en ese momento no tenía ningún login y password preparados para eso. Lo que hice fue buscarme unos proxys de Telefónica, configurar mi navegador, y acceder a mi IP (pública). Entonces la petición sí que venía de fuera, y el router la redirigía al puerto 80 del servidor. Le dije al Mozilla que no usara proxy para acceder a los 172.26.0.*, y así ya podía entrar al mismo ordenador de dos formas distintas, y cada una recibiendo una respuesta distinta.


Quiero un contador; no tengo PHP

Cuando usaba PHP me hice un index.php que incluía un contador en modo texto, y no me costó mucho. Pero ahora he decidido no poner PHP en el servidor web, y tengo que hacerme un contador nuevo. ¿Qué puedo hacer?


Podría instalar PHP como un programa (en vez de como extensión de servidor) y hacer que se ejecute como CGI, pero para hacer un programita que suma 1 a una variable no me hace falta todo eso.


Es fácil hacer un contador en bash. El siguiente comando ya sirve:

echo $(( `cat cont` + 1 )) > cont

El problema es que no puedo incrustar en mi index.html el contenido del archivo cont. Me gustaría hacer un <#include "cont"> pero en HTML eso no se puede hacer y thttpd no es de los que tienen Server Side Includes (bueno, tiene, pero no es nada cómodo).


Podría hacer que el fichero index.html fuera un ejecutable (CGI) que mediante echos mande la página y con un 'cat cont' meta el número correspondiente en el sitio que toca. Me parece bastante chapucero... prefiero tener todos los CGIs en el mismo sitio.

En HTML no se puede incrustar contenido text/html, pero sí imágenes (se hace con la etiqueta IMG). O sea, que mi CGI podría crear una imagen, y hacer un cat mandándola con el Content-type correspondiente. Y ahora, ¿cómo creo una imagen -por ejemplo un PNG- que tenga escrito un número? Eso lo hacen los magníficos programas de ImageMagick; por ejemplo con este comando:

# blanco.png es todo blanco.        Seguro que hay formas mejores de hacer esto...
convert -font helvetica  -pointsize 25 -fill blue -draw "text 5,22 '142857'" blanco.png texto.png

Aparte de ser muy chapucero, esta solución requiere meter muchísimos programas, librerías y fuentes dentro del chroot, y además sería bastante lento.

142857

Encontré otro programa (también dentro de ImageMagick) muy útil, es montage y sirve para juntar imágenes. Me bastaría con tener los dígitos del 0 al 9 cada uno en un archivo, y luego, mediante un script, ir juntando cifras para hacer cada número. Por último, servir la imagen con un cat. Ejemplo:

montage 1.png 4.png 2.png 8.png 5.png 7.png 142857.png

Sería lento, pero tampoco mucho. Tendría que hacer el script que creara la lista de parámetros a partir del número leído; ahora mismo no se me ocurre ninguna forma fácil de hacerlo, pero con sed, awk o perl se puede. Me falta tiempo para esto... antes tengo que aprender a usar los paquetes de coreutils y leerme el man bash.


Tiene que haber programas que hagan solos lo de crear una imagen con un número escrito. No busqué mucho, pero encontré uno, swc (simple web counter), pero no me gustó porque ha tenido un fallo importante de seguridad y -lo importante- porque usa imágenes GIF, que es un formato con un sistema de compresión patentado por Unisys Corporation, el LZW. Me da asco meterme en estos temas, así que mejor no uso el programa. Yo lo veo como una trampa.


Resumiendo, que no puedo incrustar texto en HTML, pero sí imágenes (IMG). Entonces me acordé de que también se pueden incluir scripts; ahí vi la solución. Hice un script llamado cuenta así:

#!/bin/bash
echo "Content-type: text/plain"
echo

echo -n $(( `cat cont` + 1 )) > cont

echo -n document.write\(\"
cat cont
echo -n \"\)\;

Y luego sólo tenía que incluírlo en todas las páginas que quiera con <SCRIPT TYPE="text/javascript" SRC="cgi-bin/cuenta"></SCRIPT>

El problema es que no todos los navegadores soportan JavaScript. Normalmente los que no lo soportan tampoco muestran imágenes, así que creo que mi solución es tan efectiva como la de la imagen. De todas formas sigue siendo una chapuza que he de arreglar cuando me aburra.


Copias de seguridad periódicas

Siempre hay que hacer una copia de seguridad de todo; aunque la web esté en mi casa es posible que el portátil se queme (tal como han pronosticado algunos) o que el disco duro deje de girar de tanto arrancarlo y pararlo. Prefiero no fiarme y mantener una copia actual en mi ordenador grande (desde ahí la puedo pasar a CDs).

Lo hice con este script, bakupa, que es para ejecutar en el ordenador grande (172.26.0.2). 172.26.0.11 es el servidor.

#!/bin/sh
# Esto hace una copia de la web del servidor, y la archiva
# 17-2-2004 Daniel Clemente

dia=`date +%Y_%m_%d`
mkdir temp
echo Pon password del usuario dc
scp -r dc@172.26.0.11:/f/web/danielclemente.com/* temp
tar jcvf ${dia}.tar.bz2 temp
rm -rf temp

Trabajar cómodamente en mi web

Lo de tener un servidor FTP rápido donde dejar la web ya es bastante cómodo, pero quiero más: quiero montar el árbol de directorios de mi web (en el servidor) en un directorio local.

Para eso está el NFS, pero es muy complicado de configurar y a veces poco seguro. Samba estaba bien, pero no quiero instalarle más cosas al servidor, y menos eso (a ver si ahora va a tener tantos recursos compartidos como los Windows que me encuentro por Internet).

Lo que me interesa son los módulos para el kernel que implementan un sistema de archivos basado en FTP o en SSH. No hay que tocar nada del servidor, sólo tener los servidores correspondientes. O sea, que los kernels los tengo que modificar en el ordenador 'grande', el servidor no lo toco para nada.

Hay un proyecto llamado lufs que hace todo esto con muchos sistemas de archivos, pero lo vi demasiado extenso comparado con los proyectos que trabajan sólo con uno.

El de FTP es ftpfs, y me fue bien pero me daba un error de "Stale NFS file handle" al querer cambiar de directorio. De todas formas, el FTP no es seguro, así que probé por SSH.

El de SSH se llama shfs y es muy fácil de usar. Aquí (Linuca) vi un tutorial que me ayudó un poco con unos problemas que tuve con el kernel. Lo conseguí poner, y, bueno, funciona perfectamente. Tampoco hay mucho más que decir.

mi pantalla

Ahora puedo usar Mozilla Composer y mis programas preferidos para tocar archivos del servidor sin tener que instalarlos en el servidor.




Cambios en el dominio

Ahora mi página sería accesible para todos cuando escribieran mi dirección IP en su navegador (por suerte tengo IP fija y sería siempre la misma). Pero lo que yo quiero es que se pueda entrar desde www.danielclemente.com.

¿Qué hace falta para eso? Pues comprar (en realidad alquilar por un año) un dominio libre y hacer que se traduzca a mi IP cuando alguien lo escriba. Hay unos cuantos ordenadores importantes por el mundo que mantienen una tabla con la equivalencia entre cada nombre de dominio y cada IP: son los servidores DNS.

Para que añadan un registro que apunte a tu IP tienes que pagar, aunque no mucho. Por ejemplo, yo lo compré en GoDaddy por unos 9 dólares USD, y vale por un año. No voy a hacer propaganda de ninguna empresa; busca 'domain registrars' que es que como se llaman en inglés. Que sepas que un .com te puede salir por $7 o $30 dependiendo de en dónde te dejes timar, y un .es de 100 euros para arriba, más gastos de patentes, tasas, trámites, etc. (¡viva el Ministerio de Ciencia y Tecnología!).

Ah, el registro de un .com suele ser fácil. Tienes que dar datos ciertos sobre tu nombre, dirección, teléfono y e-mail, y pagar con tarjeta de crédito (una de esas 'virtuales' ya vale). Como pagas, tienes soporte técnico que te ayudará en todo.


Una vez "comprado" el dominio, hay varias opciones (todas hay que buscarlas desde el 'Centro de control' de la web del registrador): por ejemplo, puedes redirigirlo a otra página, poner un mensaje de 'En venta', alojar algún archivo (pero con publicidad ya que el hosting se paga aparte) o decir directamente a qué IP está ligado ese dominio.


Lo que yo hice fue informar a todo el mundo de que www.danielclemente.com = 217.126.10.173. De eso se encargan los servidores DNS; pero como yo no tenía ganas de poner un servidor DNS en mi ordenador, usé los servidores de GoDaddy para añadir esa entrada mediante una opción de su web (es un servicio que dan gratis). Como todos los DNS están relacionados, un cambio en uno de ellos se propaga a todos los del mundo en unas horas.

Encontré una opción perdida en la web que permitía editar el archivo de zonas DNS; desde ahí pude incluir la línea A necesaria. Quedó así:


Nombre de zona Tipo Valor
@ A 217.126.10.173
www CNAME @

La A da la traducción de danielclemente.com (que sale representado como @) y el www es un alias a @, o sea, que tanto danielclemente.com como www.danielclemente.com resuelven a mi IP. De hecho, todos los subdominios traducen a mi misma IP, así que seguro que podría quitar el www ése.

Tuve que esperar dos días para que los cambios surtieran efecto, y después fue muy bonito ver la 'propagación DNS': poco a poco esta información fue llegando a todos los servidores -incluso a los pequeños, pero más tarde- empezando desde los de la empresa de dominios hasta llegar a todos los del mundo. Es fácil comprobarlo usando órdenes como éstas:

    dig www.danielclemente.com  # Uso los servidores configurados en mi /etc/resolv.conf
    dig @195.235.113.3 www.danielclemente.com  # A ver qué hay en el de Telefónica
    dig @PARK3.SECURESERVER.NET www.danielclemente.com  # A ver qué piensan los de GoDaddy (los primeros en actualizarse)

Conclusiones

Por fin tengo mi servidor montado; creo que me he enrollado bastante en algunos puntos pero tenía ganas de hacerlo.

Resumiendo, he montado mi propio servidor desde cero tanto a nivel hardware como software. En realidad es poca cosa (servidor web y ftp), pero lo poco que hace lo hace muy bien. Lo he pensado todo mucho y creo que he tomado la mejor decisión en cada momento, con varias excepciones: sé que he hecho bastantes 'chapuzas' (o 'problemas que no he resuelto de forma elegante'), pero soy consciente de ello y las arreglaré cuando haya aprendido lo suficiente.

He aprendido mucho, y lo importante es que no me he repetido. Ya pasé muchos meses escribiendo y pensando cómo montar un servidor que hiciera de todo para mi instituto (fue mi 'Treball de Recerca' del Bachillerato, y ganó un premio CIRIT de la Generalitat). Todo el tiempo que perdí con eso no lo he vuelto a perder aquí, y tampoco se parecen mucho. En el servidor-que-hace-de-todo de mi instituto sólo tuve que instalar cada cosa, una detrás de otra. En este estudio resuelvo mis necesidades personales, y eso cuesta mucho más que hacer apt-gets.

Una conclusión importante que deberías sacar si ya has leído hasta aquí es que el documento se acabará pronto...

Septiembre 2006: bueno... no del todo, porque cuando apagué el servidor (dos años y medio después), escribí qué tal funcionó mi servidor.


Sobre este documento

Valid HTML 4.01


Copyleft  (GFDL) Febrero 2004  Daniel Clemente.   Correo: ver "Contacto", Web: www.danielclemente.com