1 votos

El puerto de origen de TCP se incrementa en 2, siempre es par para curl / wget

Cuando se utiliza curl y wget, si el puerto fuente no se establece manualmente (como con --local-port en curl), el puerto TCP fuente siempre es par, y se incrementará en 2 en lugar de 1.

Ejemplo: en tcpdump cuando realizo una conexión veo que se utiliza el puerto fuente 45080, y luego la siguiente conexión utilizará 45082, en lugar de 45801. Usando local-port puedo forzar a que se utilicen puertos impares, y tcpdump confirma que se están utilizando correctamente.

Esto me está causando problemas en un entorno de prueba de red, y no puedo averiguar qué controla la selección implícita del puerto TCP. Puedo cambiar el rango, pero no puedo cambiar la "incrementación".

Estoy utilizando centos7 y el kernel "3.10.0-514.el7.x86_64".

En tcpdump veo el mismo comportamiento al usar wget y curl, lo que me lleva a creer que este no es un problema específico de curl, sino más bien del mecanismo interno utilizado para seleccionar los puertos.

Además, si veo que curl está utilizando el puerto 45080, por ejemplo, sé que el siguiente puerto que usará será 45082. Si fuerzo un --local-port de 50000, entonces curl una vez más sin el --local-port, será 45082, como si hubiera un contador separado que lo incrementa, y que no se ve afectado por el puerto "último" utilizado.

Alternativamente, si hago lo mismo que en el paso anterior, pero en lugar de forzar el puerto 50000, lo fuerzo a utilizar 45082, el puerto que presumiblemente iba a elegir, luego uso curl nuevamente sin forzar un puerto local, elegirá 45083, luego si nuevamente elegirá 45084, luego 45086...

La única otra forma en la que pude lograr que elija naturalmente uno impar fue si limitaba el rango a un número impar de puertos.

¿Hay una llamada al sistema, o algún tipo de operación de kernel para seleccionar puertos fuente, y hay alguna forma de cambiarlo?

¡Gracias!

1voto

coffeebreaks Puntos 1482

Creo que pude demostrar que el kernel en sí mismo incrementa los puertos de esta manera.

Strace mostró que tanto wget como curl llamaban a connect() sin llamar a bind() para establecer explícitamente el puerto fuente.

Escribí un script en python para simular lo mismo, y parece que el kernel 3.1 incrementa en 2, y el kernel 2.6 no lo hace.

Curiosamente, esto solo es cierto cuando se usa connect(), si te enlazas en el puerto 0, dejando que el kernel elija el siguiente puerto disponible, es más o menos aleatorio.

Mi script:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.28.0.2', 80))
addr = s.getsockname()
print addr[1]
s.close()

output:

$ python port_test.py
45008
$ python port_test.py
45010
$ python port_test.py
45012

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X