¿Entonces el puerto no es único por máquina?

5
$ lsof

memcached 15844 root   28u  IPv6     113604       TCP *:11051 (LISTEN)
memcached 15844 root   29u  IPv4     113605       TCP *:11051 (LISTEN)
memcached 15844 root   30u  IPv6     113609       UDP *:11051 
memcached 15844 root   31u  IPv4     113610       UDP *:11051 

¿Es por IP, por protocolo o por cualquier otra dimensión?

Arjan
fuente
44
Puede tener IPv6 e IPv4 escuchando en el mismo puerto. Puede tener tanto UDP como TCP escuchando en el mismo puerto. Y combinaciones de los mismos.
Rafał Dowgird
@ Rafal Dowgird, ¿están completas las 4 combinaciones?
2
Umm, también está la interfaz de red (por ejemplo, dos aplicaciones diferentes pueden escuchar en el puerto IPv4 TCP 9000 en dos interfaces de red diferentes).
Rafał Dowgird
@ Rafal Dowgird, ¿están todos los protocolos incluidos en la TCP/UDPfamilia? ¿Por qué la salida anterior lsofno muestra qué interfaz de red está usando?
1
@ Rafal Dowgird: Aparte de TCP y UDP, podría ser SCTP. en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol
Mikel

Respuestas:

4

Se puede usar el mismo número de puerto una vez para TCP y una vez para UDP, y cada uno de estos existe en IPv4 e IPv6.

Los números de puerto TCP y UDP son espacios de números completamente diferentes, simplemente se asignan en pares y las aplicaciones que generalmente necesitan usar el mismo número en cada uno.

IPv4 e IPv6 son protocolos algo distintos; en principio, una aplicación IPv6 puede aceptar conexiones IPv4, pero generalmente se considera un buen estilo tener dos zócalos separados.

Simon Richter
fuente
¿Estás seguro de que el puerto no tiene otras dimensiones / coordinaciones?
Como Rafał mencionó, puede vincular sockets a interfaces específicas; si se permiten múltiples sockets con el mismo protocolo y puerto en diferentes interfaces depende de la implementación de la pila IP. Además, creo que hay implementaciones de IPsec que permiten vincular un puerto para que solo se acepte tráfico autenticado; nuevamente, dependiendo de la implementación, esto puede, pero no necesariamente, entrar en conflicto con un enlace que acepta solo tráfico no autenticado. En resumen, no hay una lista exhaustiva, ya que siempre puedes inventar alguna excepción a la regla.
Simon Richter
1
¿Es por interfaz o por dirección local? Pensé que era por dirección.
Mikel
1
Para TCP (cuando se usa bind()en sockets BSD) es por dirección local.
Grawity
Nuevamente, la implementación definida. Grawity es correcto acerca de la implementación de BSD.
Simon Richter
3

Cada entrada en la salida netstato lsof -ise llama socket .

Cada toma se hace única por una combinación de:

  • familia de protocolos (por ejemplo, IPv4 o IPv6)
  • protocolo (por ejemplo, TCP o UDP)
  • dirección local
  • puerto local
  • dirección remota
  • Puerto remoto

Esta combinación de variables se llama tupla de conexión .

Considere ssh.

Si su máquina está funcionando sshd, verá una entrada en la netstatsalida del servidor que se está ejecutando en el puerto 22, escuchando y esperando nuevas conexiones.

# netstat -tnl | grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

Pero también verá entradas para cada conexión activa.

# netstat -tn
tcp        0      0 192.168.x.y:22          192.168.x.a:ppppp       ESTABLISHED
tcp        0      0 192.168.x.y:22          192.168.x.b:qqqqq       ESTABLISHED

Entonces, la salida anterior muestra que el puerto 22se está utilizando 3 veces en la misma máquina.

En este caso, cada conexión es única porque cada una tiene una dirección remota o puerto diferente. Tenga en cuenta que incluso si solo uno de ellos es diferente, todavía hace que el socket sea único.

Pero también puede ser único por dirección local o puerto.

Por ejemplo, podría estar utilizando hosts virtuales basados ​​en IP de Apache para mostrar un sitio diferente según el nombre de host o la dirección IP:

# netstat -tnlp | grep 80
tcp        0      0 1.2.3.4:80              0.0.0.0:*               LISTEN      9876/apache2
tcp        0      0 1.2.3.5:80              0.0.0.0:*               LISTEN      9876/apache2

Aquí, hay dos sockets escuchando en el puerto 80.

En este ejemplo, si el tráfico entra con una dirección de destino de 1.2.3.4, se entregará al primer socket; si el destino es 1.2.3.5, va al segundo.

Sin embargo, el servidor tiene que hacer esto explícitamente. El valor predeterminado para un servidor es establecer la dirección local en 0.0.0.0, también escrita *, lo que significa que solo habrá un socket de escucha en ese puerto y aceptará todo el tráfico entrante en ese puerto.

Como has descubierto, también es único por protocolo.

Por ejemplo, el servidor DNS BIND usa TCP y UDP:

# netstat -nlp | grep named
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      567/named
tcp        0      0 192.168.x.y:53          0.0.0.0:*               LISTEN      567/named
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      567/named
udp        0      0 127.0.0.1:53            0.0.0.0:*                           567/named
udp        0      0 192.168.x.y:53          0.0.0.0:*                           567/named

Cada conexión también es única por familia de protocolos, lo que significa que IPv4 e IPv6 pueden ser distintos.

Esto depende de si el programador solicitó un zócalo solo IPv4, un zócalo solo IPv6 o un zócalo combinado IPv4 / IPv6.

En Linux, un socket IPv6 también acepta tráfico IPv4 a menos que el programador se lo indique y, por lo tanto, solo aparece una vez en la netstatsalida.

$ port=55555
$ nc -6 -l $port || echo "Error listening on port $port" &
$ netstat -tnl | grep $port
tcp6       0      0 :::55555                :::*                    LISTEN     
$ nc -z 127.0.0.1 $port && echo "Port $port is accepting IPv4 connections"
Port 55555 is accepting IPv4 connections

Pero el código fuente de Memcached muestra que está pidiendo explícitamente un socket solo IPv6, por lo que IPv4 e IPv6 aparecen por separado en su ejemplo.

error = setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));
Mikel
fuente