Mostrando entradas con la etiqueta red. Mostrar todas las entradas
Mostrando entradas con la etiqueta red. Mostrar todas las entradas

sábado, 18 de febrero de 2012

Puertos abiertos en el router: mala idea.

[Introducción chorra]
Juer, vaya día. Estoy tan tranquilo hoy haciendo unas pruebicas con sockets TCP en mi red local, trabajando con el wireshark capturando los paquetes resultantes para ver si, haciendo un par de putadas a una conexión TCP, puedo llegar a romper algo. Nada, intentando explotar una idea que tuve hace dos días y viendo si dá para un post o no. Hasta aquí todo normal.

Resulta que en una de estas he encendido el Transmission ( http://www.transmissionbt.com ), para el que no lo sepa es un cliente de BitTorrent. Si no sabes que es BitTorrent dale aquí aqui . Para la gente con poca memória: P2P. Intercambio de ficheros. ¿Te suena ya?

Bien. Voy a Edit>Preferences>Network>Test Port. "Port closed". Genial. Tendré que crear una regla en el router.

Voy a la configuración del router, veo que ya hay una regla creada para exactamente esto, pero en una IP que no es la mia (es la de otro ordenador de casa, que ahora mismo está apagado). Pos fale. No problemo. Le digo que todo lo que venga por el puerto 61415 me lo mande a mi IP local: 192.168.1.35. Pongo una regla en la configuración del cortafuegos de mi portátil para que accepte conexiones entantes por el puerto 61415. La regla es así:

iptables -A INPUT -p TCP -m state --state NEW --dport 61415 -j ACCEPT


Nótese que el puerto por "defecto" es el 51413, pero como ya está configurado para que lo use otra máquina en mi red, yo estoy usando el 61415 (puerto que he elegido al tuntún). Pruebo otra vez: Edit>Preferences>Network. Cambio el puerto del 51413 al 61415. Le doy a Test Port: "Port open". Genial, ahora esto irá chuscado. Voy a por algo para picar (esto de abrir puertos hace que a uno le entre hambre). Cuando vuelvo la descarga ya está completada. Genial. Apago el Transmission, me pongo algo de música, pongo enmarcha el Wireshark para seguir haciendo pruebas y.... WTF!!!

[Paquetes, Paquetes Everywhere]
Joder, macho. Aún habiendo cerrado el Transmission hay muchísimo tráfico que viene de Internet hacia mi máquina. Pero a saco. Unos 3-4 requests por segundo.

Todas las peticiones son paquetes TCP tipo SYN. O sea, que des de Internet quieren establecer una conexión con mi máquina. Miro el puerto de destino de estas conexiones y es el 61415. Mi ordenador responde a cada una de ellas con un paquete TCP tipo RST, que les dice "ummm.... pos va a ser que no", ya que no tengo ningún servicio escuchando en este puerto.

Vale, tate. Esto es lógico. Hace un momento, cuando tenía el Transmission encendido la gente se conectaba a mi máquina para pillar archivos. He cerrado la aplicación de Transmission, pero esto es algo que la gente de Internet no sabe, por lo que intentan conectarse igualmente a mi PC para pillar ficheros (por esto mandan un TCP-SYN). Mi portátil como no tiene ningún programa escuchando en el 61414, contesta las peticiones con un TCP-RST diciendo... lo siento, no hay nada a lo que te puedas conectar (de esto se encarga el kernel). O sea, esto es normal, y no hay nada malo en que intenten conectarse a mi máquina sin conseguirlo. Esto te puede llegar a quitar bastante ancho de banda, pero bueno, supongo después de un rato el número de requests va disminuyendo hasta que finalmente pare.

Claro, yo quiero seguir haciendo pruebas con el wireshark, pero con tanto "ruido" no hay quién trabaje. Total, que me voy al router y borro la regla de redirección de puerto 61415 hacia mi máquina. A ver si ahora puedo trabajar tranquilo.

Recordemos que ya tenía otra regla en el router. La regla dice que redirija todo el tráfico al puerto 51413 a la IP 192.168.1.33 (otro host de mi red, ahora mismo apagado). No la he modificado porque quiero que la 192.168.1.33 siga pudiendo usar el Transmission sin cambiar la configuración.

[ARP-FLOOD]
Pongo enmarcha el wireshark otra vez. Fuck. Ahora hay alguien que me está inundando la puta red de paquetes ARP. Que majos todos.



Veamos, el router (192.168.1.1) pregunta quién tiene la IP 192.168.1.33, mediante paquetes ARP lanzados casi cada segundo. Pues vaya: NADIE TIENE ESA IP; es un host en mi red que ahora mismo está apagado, normal que nadie conteste. Pero ¿por qué el router intenta descubrir quién es 192.168.1.33? Quiero decir.. esta máquina ha estado parada durante días. ¿Qué tráfico tiene que ir a una máquina apagada hace días? ¿Quién quiere ponerse en contacto con una máquia apagada? WTF!

Pues alguien que esté usando BitTorrent y quiera un fichero que cree que yo tengo. Parece que algún hijo de delfín daltónico y chimpanzé fitofílico ha decidido hacer conexiones contra mi IP pública, al puerto 51413. Pero, ¿Por quéeee y para qué? Vale que este sea el puerto por defecto de Transmission, pero yo hoy no lo he usado para nada. Yo siempre he estado usando el 61415. ¿Con que derecho intenta acceder al puerto 51413? o sea.... ¿qué espera encontrar? Esto parece una mala implementación de un cliente de BitTorrent, o alguna comprovación que harán algunos servidores de torrents para comprobar si, además del puerto 61415, también tenemos abierto el 51413, digo yo. No lo sé, pero la verdad que no me mola mucho el tema.

Lo que está pasando, es que como tengo una regla en el router que dice "redirígeme todo el tráfico que venga al puerto 51413 a la IP 192.168.1.33", el router la palica siempre. Si o si. Y claro, para poder mandarle tráfico entrante al host 192.168.1.33 necesita saber primero quién es éste host (obtener la dirección MAC, para los menos entendidos en tema de ARP). Y es por esto que está mandando paquetes ARP a SACO en toda mi red. De echo, manda un paquete ARP por cada petición que le llega al puerto 51413. Una de las características de ARP es que son paquetes que se mandan a broadcast. O sea que lo reciben TODOS los hosts de mi red. Fuck. Obviamente como ninguno de ellos es 192.168.1.33, todo el mundo descarta el paquete y andando. Pero bueno, es un desperdicio de ancho de banda y no me mola el rollo.


[Cómo ver el tráfico que recibiría 192.168.1.33 en caso de estar encendido]
Pues como me da pereza infinita ir a encender el host 192.168.1.33, poner el wireshark y demás, vamos a ver el tráfico que recibiría este host ahora mismo des de mi portatil:

$ sudo ifconfig eth0:2 192.168.1.33

Ala. Hecho. Ahora mi portátil tiene la IP 192.168.1.35 y la 192.168.1.33 en una subinterfície (conocíais lo de las subinterfícies, verdad? ;) ). Mi host se indentifica como 192.168.1.33 y responde las peticiones ARP. Miro el wireshark y ala! Estamos como al principio: Hosts de Internet intentan establecer una conexión con mi equipo, y mi equipo contestando que "no, no tengo ningún servicio escuchando en el puerto donde me estás haciendo la petición. RST! RST! RST!".



[¿Cómo solucionar el problema?]
Bueno, no parece muy difícil llegar a la conclusión de que los puertos, si están cerrados, mejor. En caso de usar protocolos P2P, en necesario abrir los puertos para que el tema vaya flúido. Yo a partir de ahora voy a abrir/cerrar los puertos de mi router cada vez que me quiera descargar algo. No me mola que si a alguien le apetece enviarme un paquete al puerto por defecto de BitTorrent, esto se traduzca en chorrocientos paquetes ARP en mi red. Vale, tampoco hacen daño, pero no los quiero ahí.

[Notas finales]
En este post tampoco cuento nada extraño ni sofisticado. Todo funciona como es debido, y si se piensa bien, no hay problema de que las cosas funcionen así. Aún así para mi ha supuesto la primera prueba que tengo que respalde la afirmación que todo el mundo hace diciendo: "los puertos del router mejor cerrados!". Y tienen razón. Ahora veo que me estoy provocando ARP-Flooding en mi propia red, en el caso de que el host de destino esté apagado. O que en caso de que esté encendido, que el host tenga que responder a peticiones ( ni que sea para decir RST ) que provinenen de Internet. Mucho mejor que se encargue de hacer todo esto el router, y deje mis hosts de la LAN en paz.

También he vuelto a ver claro esto de que Internet es la selva, y que muchas veces el router nos hace de separación entre nuestra tranquila/estable/fiable red local, y la locura de Internet.

Un saludo, Jan.

viernes, 17 de febrero de 2012

TCP Sockets: TIME_WAIT y los puertos efímeros son poco amigos

Hoy vamos a explicar un poco qué es TIME_WAIT y cómo puede darte por culo un rato largo.

[INTRODUCCIÓN]
Todos sabemos que las conexiones TCP ( capa 4 en modelo OSI, también llamada capa de transmisió de datos ) tienen estados. Umm... bueno, igual no todos lo sabemos. Refresquemos un poco qué son esto de los estados TCP antes de empezar.

TCP establece la conexión a tres vías[1]. Cuando se intenta establecer la conexión del host A al host B, el host A manda un paquete tipo SYN al host B. La conexión pasa a estar en un estado SYN_SENT. Cuando el host B le contesta con un paquete ACK-SYN, la conexión para a un estado llamado SYN_RECV. Cuando la conexión por fin se establece pasa a estado ESTABLISHED. También hay el estado LISTEN, que es el estado que tienen servicios tales como apache, memcached o sshd, esperando nuevas conexiones. Total, con todo esto nos tenemos que quedar con la copla de que una conexión TCP pasa por diferentes estados desde que se establece hasta que se cierra.

La lista completa de estados se puede ver fácilmente haciendo un man netstat, y buscando el apartado State.

Bien, entonces tenemos que los dos estados mas comunes son: ESTABLISHED conexiones establecidas y LISTEN, en el caso de que estemos en un servidor con varios servicios activos. Para ver una lista de las conexiones abiertas en nuestra máquina podemos hacer un:

$ sudo netstat -pan --tcp | less


[SUPOSICIÓN]
Si ejecuto un script muy simple que haga peticiones HTTP contra mi servidor web local SUPONGO que no habrá ningún problema (jeje, los cojones). Tengo un servidor Apache escuchando en el puero 80 en localhost. Problemos a ejecutar el siguiente comando en 5 consolas diferentes.

$ while true; do curl localhost; done

El comando "curl" abre una conexión TCP, hace una petición HTTP, se le devuelve un resultado (que no nos importa lo mas mínimo, ahora mismo) y CIERRA LA CONEXIÓN TCP. O esto es lo que nosotros esperamos, vamos. Entiendo que tener 5 instancias del script haría que normalmente tuviese 5 conexiones en estado ESTABLISHED, pero esto, nunca debería ocasionar un problema a nivel de sistema.

Hagamos la prueba. Ejecutamos cinco veces el script en consolas separadas, y en otra terminal ejecutamos:

$ sudo watch -n 0.5 'netstat -pan --tcp | grep ESTABLISHED | wc -l'


Pues efectivamente, nunca pasamos de 5 conexiones al mismo tiempo en estado ESTABLISHED pero... Umm.... pero al cabo de un minuto de estar ejecutando los scripts, el comando "curl" empieza a dar un error:

curl: (7) Failed to connect to 127.0.0.1: Cannot assign requested address


[PROBLEMA]
WTF. A ver, tenemos tan solo 5 conexiones abiertas. El error del curl parece decirnos que no puede obtener un puerto de origen para establecer la conexión. Veamos porqué:
Ejecutemos los scripts anteriores y pongamos un filtro diferente en el netstat:

$ sudo netstat -pan --tcp | grep TIME_WAIT | wc -l
5329
$ sudo netstat -pan --tcp | grep TIME_WAIT | wc -l
13440
$ sudo netstat -pan --tcp | grep TIME_WAIT | wc -l
19348
$ sudo netstat -pan --tcp | grep TIME_WAIT | wc -l
21526
$ sudo netstat -pan --tcp | grep TIME_WAIT | wc -l
28214


COJONES! Por algún motivo estan quedando chorrocientos sockets abiertos en estado TIME_WAIT!

[QUÉ ES TIME WAIT]
Ahora que nos hemos puesto un poco en matéria vamos a ver para que se usa el estado TIME_WAIT, y como puede llegar a ser un problema. De la definición del man de nestat sacamos que:

TIME_WAIT: The socket is waiting after close to handle packets still in the network.

Umm... según esto parece que la conexión no se cierra hasta que pase un tiempo para poder capturar los paquetes que se habían "perdido" por la red debido a posibles problemas de enrutamiento. Jummm... explicación algo escueta. Sobre todo porque no dice cuanto vamos a tener que esperar. Vamos a investigar un poquito más sobre el tema...

El RFC 1122 en el apartado "Transport layer, TCP" [2] dice algo así como:
When a connection is closed actively, it MUST linger in TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).

Vaaaale. Ahora ya tenemos un poco mas de información. Resulta que tenemos que esperarnos 2xMSL antes de que una conexión pase de TIME_WAIT a CLOSED ( y se libere la conexión ). Genial. Y ahora... ¿Dónde coño puedo consultar el tamaño del Maximum Segment Lifetime? Pues ejecutando este comando:

$ cat /proc/sys/net/ipv4/tcp_fin_timeout
30

Que en mi máquina Debian me da un resultado de 30 segundos. En máquinas con Ubuntu el valor acostumbra a ser 60, en máquinas Solaris acostumbra a ser 120. Entonces parece ser que, en mi máquina, tardaré 2*MSL, o sea 2*30=60 segundos en liberar una conexión. El problema que hemos experimentado antes es que hay muchos sockets (conexiones) abiertas en estado TIME_WAIT. Cuando llegamos al límite de conexiones efímeras del sistema, el kernel nos dá un error diciendo "umm... me sabe mal, pero no me quedan puertos efímeros". Esto se traduce en el error que nos saca el "curl". O sea, no es problema del comando "curl" que vaya dejando conexiones abiertas, ya que si no tendríamos muchas conexiones en estado ESTABLISHED, y no es el caso. Tampoco es problema del kernel, ya que éste implementa el RFC 1122 como dios manda.

[PUERTOS EFÍMEROS]
"Ei. Ei, espera. Cuando has empezado a hablar de puertos efímeros y toda esta mierda me he perdido. A ver si te explicas un poquito más, macho."
Veamos. Cuando establecemos una conexión TCP con nuestro navegador a un servidor Web, necesitamos un puerto de origen [3]. Estos puertos, se conocen como puertos efímeros. El protocolo TCP necesita definir un puerto origen y un puerto destino. En nuestro ejemplo, el puerto destino será el 80 (servidor web), y el puerto origen será un puerto efímero. El Kernel nos asigna un puerto efímero automáticamente cuando establecemos una conexión nueva. Para ver el rango de puertos efímeros que tenemos definido podemos ejecutar:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000

Si hacemos 61000-32768 nos dá 28232. Si os fijais, es un número muy parecido al número de sockets en estado TIME_WAIT que teníamos cuando ha empezado a petar todo. Esto es debido a que un socket en estado TIME_WAIT todavía es un socket activo. Es lo mismo como si estuviese en estado ESTABLISHED, por lo que está ocupando un puerto efímero. Si acumulamos muchos sockets en estado TIME_WAIT, vamos agotando los puertos efímeros. Cuando llegamos al límite y tenemos reservados *todos* los puertos efímeros, al kernel no le queda otra que devolver error cada vez que se quiere crear un socket nuevo. Bonito, verdad?

[POSIBLES SOLUCIONES]
Bueno, una de ellas pasa por aumentar el número de puertos efímeros del sistema. Esto se puede conseguir simplemente ejecutando:
$ sudo su - root
$ echo "1025 61000" > /proc/sys/net/ipv4/ip_local_port_range

Hecho esto, ahora disponemos de 60K puertos efímeros y no solo 30K. En realidad esto no es una solución de nada. Simplemente tendremos que esperar 2 minutos y no 1 para que los procesos "curl" agoten el número de sockets. Estamos haciendo que el sistema aguante un poquito mas, pero ya está.


Otra solución parece que puede venir modificando el parámetro 2*MSL. Si disminuimos este valor del MSL, los sockets en estado TIME_WAIT deberían estar en este estado durante menos tiempo. El parámetro es ajustable mediante el comando comentado anteriormente:
$ sudo su -c 'echo 5 > /proc/sys/net/ipv4/tcp_fin_timeout'

Si probais de aplicar este cambio vereis que en realidad las conexiones en estado TIME_WAIT no se cierran a los 10 segundos como sería lo esperado (2*MSL; 2*5=10), sino que se siguien cerrando a los 60 segundos. Por qué ocurre esto? Simple. El valor "60 segundos" está hardcoded en el kernel de linux. Así de bonito. Si miramos el fichero /include/net/tcp.h línea 105 del kernel de línux veremos algo tal que así:

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT state, about 60 seconds */

A partir de línea 202 del fichero /net/ipv4/tcp_minisocks.c vereis que hace uso intensivo de la variable TCP_TIMEWAIT_LEN, justo en la sección donde define el estado TCP_TIME_WAIT al socket TCP. Por lo que modificar a través de las sysctls el parámetro "tcp_fin_timeout" no va a servir de un carajo. Ni 2*MSL ni pollas. Harcoded en el código. (Esto vulnera el RFC 1122 y la regla 2MSL? Si alguien lo sabe que por favor comente! Gracias )


La última solución, que dista mucho de ser algo perfecto pasa por activar el tcp_tw_recycle y tcp_tw_reuse. Ambas directivas son bastante peligrosas, y vulneran explícitamente el RFC 1122. No deberían usarse en entornos de producción o sin saber muy bien qué se está haciendo. La documentación que he encontrado al respecto es [4] y [5].

TCP_TW_RECYCLE: It enables fast recycling of TIME_WAIT sockets. The default value is 0 (disabled). The sysctl documentation incorrectly states the default as enabled. It can be changed to 1 (enabled) in many cases. Known to cause some issues with hoststated (load balancing and fail over) if enabled, should be used with caution.
$ echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

TCP_TW_REUSE: This allows reusing sockets in TIME_WAIT state for new connections when it is safe from protocol viewpoint. Default value is 0 (disabled). It is generally a safer alternative to tcp_tw_recycle
Note: The tcp_tw_reuse setting is particularly useful in environments where numerous short connections are open and left in TIME_WAIT state, such as web servers. Reusing the sockets can be very effective in reducing server load.
$ echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

O sea, usadlos, pero con mucho cuidado.


La solución definitiva viene en forma de pregunta: ¿Qué coño haceis creando 30K conexiones TCP en menos de un minuto, criaturas del Señor?
Si habeis llegado aquí porque os habeis encontrado con el problema del TIME_WAIT en un servidor de producción cuando recibía bastante tráfico os tengo que decir algo que no os va gustar: algo estáis haciendo mal. En este caso no es suficiente con cerrar las conexiones a la BBDD, caches, o lo que sea cada, vez que se hace una consulta. La solución pasa por hacer pooling de conexiones y demás. REAPROVECHAR conexiones. Pero bueno, esto es otra guerra que se sale del alcance de este post. Aún así para dudas, ruegos y preguntas teneis los comentarios. Intentaré ayudar hasta donde pueda/sepa.


[ÚLTIMAS NOTAS]
Nótese que este problema es provocado por la conjunción de crear muchas conexiones por parte de un CLIENTE (importante este punto) durante un periodo muy corto de tiempo. Esto hace que se acumulen muchos sockets abiertos (bueno, o no-cerrados, para ser mas exactos) en estado TIME_WAIT. Cuando se llega al punto que la suma de todos los sockets en dicho estado es igual al número de puertos efímeros de la máquina, el kernel no es capaz de crear sockets nuevos hasta que no se liberan recursos, devolviendo un error a cualquier proceso que intente crear una conexión nueva (nótese que las conexiones ya establecidas seguirán funcionando normalmente).

Espero que les haya gustado el post. La zona de comentarios está disponible para hacer preguntas, o proponer soluciones alternativas al problema.

Un saludo, Jan.

[1] http://danred.wordpress.com/2009/09/28/establecimiento-de-conexion-tcp-de-3-vias/
[2] http://www.rfc-editor.org/rfc/rfc1122.txt página 87
[3] Recordemos que un socket está formado por un IP Origen - Puerto Origen - IP Destino - Puerto Destino.
[4] http://www.speedguide.net/articles/linux-tweaking-121
[5] http://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

domingo, 16 de mayo de 2010

Instalando Apache2, para dummies [I]

[Disclaimer]
Hace nade que dije que dejaba el blog, porque no tenía cosas interesantes que contar y falta de tiempo. Dije que escribiría esporádicamente. Pues este fin de semana he tenido algo de tiempo libre y ha salido algo así:

[Introducción]
Esto quiere ser un pequeño manualillo, sobre la instalación Apache. Me gusta empezar con lo básico y después ir subiendo el nivel. (si tengo tiempo)
Bueno, como introducción diremos que Apache es un servidor web que se encarga de servir contenido web, ya sea estático o dinámico. Hay muchos servidores web, pero Apache es uno de los más usados en el mundo, ya sea para webs modestas o para webs con mucho tráfico. Al final el manualillo debes ser capaz de empezar a aprender HTML, PHP, JavaScript o CSS ( o todos a la vez! ).

[Instalación]

Para empezar tenemos que instalar Apache ( y PHP, ya que estamos ):

$ sudo aptitude install apache2 php5 libapache2-mod-php5

Para ver si la instalación ha ido bien abrimos nuestro navegador por defecto y entramos en:
http://localhost

Debería salir una de mis frases preferidas en informática: "It works"

[Configuración y gestión]

Bien, con apache instalado vamos a aprender unas comandas básicas para gestionarlo, antes de ponernos a jugar con el.
Si queremos [apagar/encender/reiniciar] el servicio Apache 2 podemos hacer:
$ sudo service apache2 stop
$ sudo service apache2 start
$ sudo service apache2 restart

Cuando iniciamos el servidor apache, éste carga todas las configuraciones a memória, lo que significa que si hacemos un cambio en los ficheros de configuración ( que se encuentran en /etc/apache2 ), los cambios no tendrán efecto hasta el próximo reinicio de Apache. Es importante acordarse de reiniciar el servicio después de cada modificación! Para no tener que hacer un restart ( que realmente hace un "stop" y para luego hacer un "start" ) tenemos el comando siguiente:
$ sudo service apache2 reload

Este nos cargará los nuevos ficheros de configuración a memória si todo ha ido bien.

Es bastante típico encontrarse con un error tal que así: Editamos el fichero "/etc/apache2/apache2.conf" ( podría ser cualquier otro ) y ponemos una línea nuevo con "ErrorrrLevel debug", que está mal escrito a propósito. Si ahora reiniciamos apache nos da un mensajito, nada amistoso a mi parecer, que reza algo así:

inedit@wally:/etc/apache2$ sudo service apache2 reload
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration
...fail!

Bueno, realmente el servicio sigue corriendo con la configuración antigua, no se ha roto nada. Para comprobar si todos los ficheros de configuración són correctos podemos ejecutar el comando:
$ apache2ctl configtest
El error sería exactamente el mismo que hemos visto antes haciendo un "reload":

inedit@wally:/etc/apache2$ apache2ctl configtest
Syntax error on line 110 of /etc/apache2/apache2.conf:
Invalid command 'ErrorrLevel', perhaps misspelled or defined by a module not included in the server configuration

Es una buena práctica ejecutar este comando para ver si todo se ha configurado correctamente.

Que pasa si hacemos un "sudo service apache2 restart" en un servidor que está en producción? Osea, en un servidor que puede estar teniendo conexiones en el mismo momento que reiniciamos? Pues facil, que los clientes van a recibir un precioso error en su navegador. Y claro, no queremos que esto ocurra. Para ello usa siempre que puedas (es la manera educada de decir que lo uses SIEMPRE) "reload". Pero aún así hay un comando que nos garantiza que no van a perderse las conexiones activas con el servidor. Este comando es:
$ sudo apache2ctl graceful

[Creación de contenido y URL's]
Visitante: "Si, pero yo he entrado en esta página esperando hacer cosas chulas con Apache, y tu solo me hablas de configuracioneees".
inEdit00: "Ya lo seee, impacienteee! Vamos a hacer un brake:"

En la carpeta "/var/www" es donde se almacena el contenido de tu página web. Esto significa que si haces un:
http://localhost/index.html estás accediendo a /var/www/index.html
del mismo modo que si pones:
http://localhost/foo.html estás accediendo a /var/www/foo.html
o que si pones:
http://127.0.0.1/imagenes/foo.jpg estás accediendo a /var/www/imagenes/foo.jpg

Pillas la idea? Es evidente que estos ejemplos no van a funcionar si no tienes los ficheros "index.html", "foo.html" o la carpeta "imágenes" con una foto dentro!

Visitante: "Por que has puesto "localhost" y después '127.0.0.1'? Me confunde."
inEdit00: "127.0.0.1" designa tu ordenador, esto se llama loopback ( prueba a hacer "ifconfig lo" ). Osea, es una IP que "apunta" al mismo equipo. Todos los equipos tienen esta configuración. Como tu tienes instalado el servidor web de Apache en tu equipo, necesitas conectarte a el. Si tienes Apache instalado en un PC fijo y quieres acceder al servidor desde un portátil de tu misma red puedes hacer algo tal que así: deberás buscar tu dirección IP ( ejecuta "ifconfig" para saber que IP local tienes ) que será algo así: 192.168.1.96 ( por ejemplo ). Entonces desde el portátil tienes que poner en el navegador "http://192.168.1.96" y deberías ver "IT WORKS", o lo que contenga el fichero "/var/www/index.html" . Capito?

Visitante: "...o sea, que si en mi portátil pongo la IP del PC fijo puedo ver lo que sirve Apache... interesante"
inEdit00: "Claro, siempre que Apache esté funcionando! A partir de ahora se va a ejecutar como demonio ( en segundo plano ) cada vez que inicies el PC fijo"
Visitante: "Ei! Esto no funciona! He hecho un 'http://localhost' en el portátil y no tira!"
inEdit00: "Claro, alma de cántaro. 'localhost' designa el mismo ordenador. Si pones esto en el portátil, él intenta conectarse a si mismo, y como no tienes ningún servidor web instalado, no funciona! Usa la IP del PC fijo, que para esto están"
Visitante: "..ah, si... tiene sentido."
Visitante: "entiendo. Entonces localhost es parecido a '127.0.0.1'?"
inEdit00: "Acertaste! De hecho quiero que veas esto. Ejecuta el siguiente comando:"
$ cat /etc/hosts
inedit@wally:~/hola$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 linuxjan.ib
127.0.0.1 js.com
192.168.1.36 ofelia

Bueno, a ti te deberían salir menos entradas que a mi. Qué es esto? Pues es una relación clave-valor (IP-nombre). A la izquierda se encuentran las IP's y a la derecha los nombres de dominio. Osea, si te fijas tengo asignados diferentes nombres para "127.0.0.1": "localhost, linuxjan.ib, js.com". Lo que significa que si pongo "linuxjan.ib" en mi navegador, se dirige a '127.0.0.1' igual que si pongo 'localhost'. Esto sirve para no tener que recordar IP's, sino nombres de dominio. Puedes ver que el último elemento de la lista es diferente del resto. Lo que yo hago aqui es decirle que la dirección IP "192.168.1.36" se llama "ofelia", para no tener que acordarme de su IP.

inEdit: "Que te parece?"
Visitante: "osea que si modifico localhost..."
inEdit: "yo no haría esto! Mucho programas usan localhost como referencia a la misma máquina, mejor deja la entrada donde está"
Visitante: "pero puedo añadir elementos a la lista? Como por ejemplo: '127.0.0.1 www.paginapersonaldeprueba.com' ?"
inEdit: "claro. Pruebalo. Cuando accedas a la URL que hayas elegido, deberías ver lo de 'It works!'"
Visitante: "y también puedo añadir '127.0.0.1 www.google.com'?"
inEdit: 'si pero...
Visitante: "Pues voy a probarlo! Mola. Pero... ostia! El google ha dejado de funcionar!!!!"
inEdit: "... pero si pones un nombre de dominio que ya exista, este se resolverá primero con las entradas de tu fichero "/etc/hosts" y si allí no se encuentra, se intentará resolver por DNS. Puedes arreglarlo quitando la línea del fichero."
Visitante: "No, la dejo! Y ahora voy a putear a mi hermana quitándole el google"
inEdit: ".... ¬¬"
(dos minutos después)
Visitante: "No lo entiendo, a mi no me funciona pero a ella si!"
inEdit: "claro, macho! Porque el fichero /etc/hosts está en tu PC, y no en el suyo. Esto solo son cambios locales, si tu pones una entrada así: '127.0.0.1 srv.com' esto solo funcionará en tu PC. Ok?"
Visitante: "Vale, lo entiendo. Los cambios solo son locales."
inEdit. "Exacto. Sigamos:"

A partir de ahora ya puedes empezar a crear tus páginas creando ficheros dentro de "/var/www". También puedes ( debes! ) crear carpetas para distinguir las imágenes de las hojas de estilos ( CSS ) del JavaScript! Si haces esto:
$ sudo mkdir /var/www/sub-folder
Y después creas el fichero "index.html" dentro así:
$ sudo gedit /var/www/sub-folder/index.html
Y pones como contenido algo así:
<>
<>
<>Estamos en sub folder!< /p>
< /body>
< /html>

Nota: he puesto dos espacios antes de cada "tag" para que blogger no lo interprete. Se debe escribir sin doble espaciado.
Para acceder a este contenido puedes hacerlo así ( en tu navegador ):
http://localhost/sub-folder
http://localhost/sub-folder/index.html

Apache se encarga de cargar el fichero "index.html" ( si existe! ) si como nombre de la ruta se le especifica una carpeta.

[Despedida]
Bueno, y esto es todo por hoy. Ahora puedes buscar por internet cualquier manual sobre:
  • HTML: para contenido estático.
  • CSS: para estilo ( colores, formatos, dimensiones, efectos, etc... )
  • JavaScript: para validaciones, para hacer peticiones asíncronas al servidor, modificación/creación de objetos del DOM en tiempo real..etc ( muy recomendado usar MooTools )
  • PHP: lenguaje de programación muy asequible para empezar ( por dificultad ) y muy fácil coger malas costumbres. Las birrias funcionan, aún siendo birrias. Pero bueno, por algo se tiene que empezar.

sábado, 26 de septiembre de 2009

SSLStrip+Ettercap

Conseguir passwords en una red local con, o sin cifrado. Ea!

Distribución candidata: BackTrack 4 Pre Release grabada en un DVD o virtualizada con su herramienta favorita ( VMWare, VirtualBox, Qemu... ) y ejecutada como LiveCD. Evidentemente si lo virtualizamos necesitamos que la tarjeta de red esté en Bridged ( Puenteada ) con nuestra tarjeta de red, léase que debe tener una dirección IP diferente a maquina anfitrión y acceso a la red local. Enlace

(Nota: Si esto les ha sonado a chino, busquen manuales por este orden IntroducciónInformática>CómoGrabarUnCd>CómoGrabarUnDvd>que es un LiveCD>Internet, el gran desconocido>Hacking ético>Consola, mas que una pantalla negra con letras blancas>y finalmente vengan aqui a completar el manual. Mas o menos estos son los pasos que he seguido yo para conseguir los passwords de mi red =)

Herramientas que vamos a utilizar?

  • Ettercap: Para realizar el ataque MITM ( Man in The Middle ) sobre uno o varios elementos de la red.
  • SSLStrip: Para poder capturar la mayoría de datos que naveguen ( supuestamente ) de forma segura.
  • Macchanger: como simple precaución, cambiaremos la MAC de nuestra maquina virtual.
Bueno, la versión de Ettercap que viene con BackTrack ya nos servirá. Descargaremos la última versión de SSLStrip de la pagina web oficial ( creador Moxxie Marlinspike ) actualmente v0.6
De mientras iremos instalando las dependencias del programita.
  • sudo aptitude install python2.4 -y
  • sudo aptitude install python-twisted-web -y
Ejecutamos el comando 'macchanger -r' para establecer una MAC aleatoria y así proteger un poquito nuestra identidad. Vale, al lío.
  • Ejecutamos Ettercap-GTK por el menú o a través de la consola con un 'sudo nohup ettercap -G &'
  • Pulsamos Mayus+U ( o Sniff>Unified Sniffing ) y seleccionamos nuestra interface de red ( normalmente eth0... como podemos saber que interface es? con un 'ifconfig' en la consola. La interface que tenga una IP será la que estemos usando en la red )
  • Pulsamos Control+S ( o Hosts>Scan for Hosts ) y a continuación la tecla H ( o Hosts>Hosts list ).
Vale, hasta aqui qué tenemos? Una lista de los hosts que se encuentran disponibles en la red ( a excepción de nosotros mismos, claro ). Vale, y ahora qué? Pues podemos hacer un ataque MIMT a toda la red o podemos seleccionar un host de la lista y después en "Add to Target 1" y a continuación seleccionar el router ( ya que los datos cifrados viajaran entre el ordenador seleccionado y el router ) que presumiblemente es 192.168.1.1 y pulsar "Add to Target 2". El orden de Target1 o Target2 no es importante. Si no tocamos nada de Target1 o Target2, TODO el trafico de la red pasara por nuestro ordenador. Ventajas: puedes pillar mas contraseñas o información "útil". Inconvenientes, es mas facil de detectar para alguien que vigile y si hay muchos ordenadores - ergo hay mucho tráfico en la red - la velocidad de la red se verá afectada reduciendose drásticamente. Anyway! Lo mas facil es no tocar nada y seguir adelante:
  • Vamos a Mitm>Arp Poisoning, marcamos la primera casilla de Sniff remote conections y Aceptar. Dejemos un momento Ettercap aparcado que mas tarde lo usaremos.
  • Nos hemos descargado la última versión de SSLStrip, verdad? Entonces con la consola nos situamos en el mismo directorio donde esté el fichero y hacemos lo siguiente:
  • 'tar zxvf sslstrip-0.6.tar.gz' para descomprimir. Después hacemos un 'cd sslstrip-0.6' para situarnos en el directorio.
  • Ejecutamos: 'echo "1" > /proc/sys/net/ipv4/ip_forward' para decir al PC que redireccione los paquetes.
  • Y creamos una regla en iptables: 'iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000' *nota: --to-port puede ser el puerto que os apetezca, a mi me gusta el 10.000
  • Activamos nuestro encantador programa SSLStrip con un: 'python sslstrip.py -l 10000'
  • Y como paso final vamos a Ettercap y pulsamos Control+W ( o Start>Start Sniffing )
  • Voilà! Ahora todo el trafico de la red pasa por nuestro ordenador y el programita SSLStrip se encarga de filtrar la información interesante. SSLStip va a escupir bastante información, pero los passwords se ven mejor en la parte inferior de Ettercap.
  • PRUEBA: Con otro PC de la red accede a www.google.com - o sucedáneo - y autentificate. El nombre de usuario&password deberían aparecer en Ettercap. Igual no puedes entrar dentro de la cuenta de correo porque google.com se da cuenta de que algo pasa, pero demasiado tarde ya que nosotros ya hemos capturado el user&password.
Conclusión. Las redes no son seguras ( já! ¿y para esta conclusión me he chupado todo este coñazo de HOW-TO? ). Podemos sacar información sensible de ellas sin dificultad. Esta información seguro que esta amparada por alguna ley, con lo que convierte nuestros actos de extracción de información en algo algo ilegal.
Uso del manual: entender que si tu eres capaz de capturar passwords, los demás también pueden ( desconfía de los cybers, puntos de acceso wifi, etc.... ) y el ejercicio ha sido por curiosidad académica, una demostración practica de que se puede hacer muy fácil.
Ala yo ya lo he dichooo, ahora a jugar! Que la cara de pillo que se te ha puesto no es por que si...