Poesía Binaria

Lanzando servidores TCP/IP en puertos libres aleatorios haciendo bind al puerto 0


¿Cómo? ¡Que los puertos TCP empiezan en el 1! Aunque algo sospechaba, porque en informática, el cero siempre ha valido para algo. Por eso se dice que los humanos empiezan a contar desde el uno y los informáticos desde el cero. Con esta cara me quedé cuando vi que puedes lanzar un servidor y que éste escuche en el puerto 0. Pero si el 0 no es un puerto válido, ¿para qué vale?

Cuando lanzamos un servidor y lo asociamos al puerto 0, el sistema escogerá un puerto aleatorio y libre con permiso para crear un servidor (por ejemplo los puertos menores al 1024 requieren de privilegios de administración o root). Así que nuestro servidor escuchará donde primero pille. Además, esto funciona tanto en sistemas Unix como en Windows, no tiene pérdida.
¿Y qué sentido tiene escuchar en un puerto aleatorio?¿Cómo sabrán nuestros usuarios en qué puerto acceder a los servicios? De primeras a mí se me ocurren ciertas cosas:

Aquí traigo un pequeño programa hecho en Python que nos devuelve un puerto libre y aleatorio, extraído de: The port 0 trick..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import socket;

def findFreePorts(howMany=1):
    """Return a list of n free port numbers on localhost"""
    results = []
    sockets = []
    for x in range(howMany):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('localhost', 0))
        # work out what the actual port number it's bound to is
        addr, port = s.getsockname()
        results.append(port)
        sockets.append(s)

    for s in sockets:
        s.close()

    return results

print (findFreePorts(10));

Y podemos montar una prueba rápida con netcat.

nc -l 0

Luego desde otro terminal podemos hacer:

netstat -tanp | grep nc
tcp        0      0 0.0.0.0:38321       0.0.0.0:*        ESCUCHAR    9042/nc

De todas formas, hay programas a los que no les gusta que le des el puerto 0, como Apache, que se niega a encenderse en ese puerto. Otros servidores como MySQL, te dejan especificar el puerto 0 y de hecho escuchan en un puerto aleatorio, aunque podrían decirte aunque sea en logs en qué puerto están escuchando (podemos averiguarlo con la línea de antes del netstat). Y servidores como redis que si les das el puerto 0, no escuchan en ningún puerto TCP.

Foto principal: Scott Walsh

También podría interesarte....