Qué es un puerto y cómo saber qué escucha en Linux
Entiende los puertos TCP y UDP, el rango 1-65535 y la diferencia entre puertos locales y públicos. Usa ss para ver qué servicios están escuchando en Linux.
Qué es realmente un puerto
Un puerto es un número que permite que un servidor ejecute varios servicios a la vez sin mezclar su tráfico. Su VPS tiene una dirección IP, pero puede ejecutar al mismo tiempo un servidor web, un servidor SSH y una base de datos. Cuando llega un paquete, el sistema operativo debe saber a cuál de ellos va dirigido. El número de puerto proporciona esa información. El tráfico web llega al puerto 443 y SSH al puerto 22. La dirección IP lleva el paquete hasta el servidor; el puerto lo entrega al programa correcto de ese servidor.
Un puerto es un número de 16 bits: 16 bits permiten los valores de 0 a 65535, y el 0 está reservado, por lo que en la práctica los puertos van del 1 al 65535. Los puertos inferiores a 1024 son los puertos «bien conocidos» y requieren root para abrirlos. Por eso los servicios estándar usan esos puertos: 22 para SSH, 80 para HTTP, 443 para HTTPS y 53 para DNS. Cualquier puerto superior a 1024 puede ser utilizado por programas normales.
Hay dos tipos: TCP y UDP. El número de puerto de uno es independiente del mismo número en el otro. TCP es el protocolo orientado a conexión que utilizan la mayoría de los servicios, como SSH, HTTP y las bases de datos. UDP no establece conexión y se utiliza para servicios como DNS y algunas VPN. Al abrir un firewall, normalmente debe especificar cuál de los dos utiliza, por ejemplo 22/tcp.
Escuchar significa que un programa espera conexiones en un puerto
Un programa que quiere recibir conexiones pide al kernel que «escuche» en un puerto. Desde ese momento, el puerto está abierto en la máquina y el programa responde a todo lo que llega allí, según las reglas del firewall. Un puerto en el que no escucha ningún programa simplemente rechaza las conexiones. Por eso, la primera pregunta de cualquier comprobación de seguridad es: qué está escuchando y dónde.
El comando para responder a esa pregunta es ss:
sudo ss -tlnpLas opciones indican TCP (t), sólo sockets en escucha (l), puertos numéricos (n, por lo que verá 22 en lugar de ssh) y el proceso propietario (p). Un resultado habitual:
State Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:80 nginxLa columna Process indica qué programa es el propietario de cada puerto. Así puede localizar algo que no tenía intención de dejar en ejecución.
La columna Local Address es la que importa
Lea detenidamente la dirección que aparece delante de cada puerto, porque determina quién puede acceder al servicio. Hay tres casos que verá constantemente.
0.0.0.0:22 significa «escuchar en todas las direcciones IPv4 que tiene esta máquina», incluida la dirección pública. El servicio es accesible desde Internet mediante IPv4, si el firewall lo permite.
[::]:80 significa lo mismo para IPv6: escuchar en todas las direcciones IPv6, incluida la pública. Muchos programas se enlazan aquí de forma predeterminada y, en Linux, un socket :: suele aceptar también IPv4.
127.0.0.1:5432 significa «escuchar sólo en loopback». 127.0.0.1 es la dirección que utiliza una máquina para comunicarse consigo misma y no se puede enrutar desde ningún otro lugar. Un servicio enlazado aquí sólo es accesible desde el mismo servidor, nunca desde Internet, independientemente de lo que indique el firewall. La línea de Postgres anterior es segura por diseño.
La regla práctica se deduce directamente de esto: una base de datos, una caché o un panel de administración que sólo utilizan sus propias aplicaciones debe enlazarse a 127.0.0.1, no a 0.0.0.0. Si nunca escucha en una dirección pública, no hay ningún punto al que pueda acceder un atacante.
La escucha no es lo mismo que la accesibilidad
Hay otra distinción que evita mucha confusión. Que un puerto esté abierto en la máquina, es decir, que un programa esté escuchando, no significa que se pueda acceder a él desde fuera, es decir, que el firewall permita el tráfico. Ambas condiciones deben cumplirse para que un cliente remoto pueda conectarse. Además, los dos fallos se ven de forma distinta desde el cliente: una conexión rechazada significa que no había ningún proceso escuchando, mientras que una conexión que queda esperando y termina agotando el tiempo de espera normalmente indica que un firewall descartó el paquete. Eso es exactamente lo que indican esos dos errores de SSH.
Por tanto, hay dos capas de control. Usted decide qué procesos escuchan mediante la dirección de enlace de cada servicio. También decide a qué puede acceder el exterior mediante un firewall. Un servidor bien administrado utiliza ambas: los servicios escuchan sólo donde lo necesitan y el firewall deniega todo lo que no se haya permitido explícitamente. Consultar qué está escuchando con ss es el primer paso; decidir qué permite el firewall es el segundo. Esto se explica en Introducción a los firewalls con UFW.
Aquí hay un detalle que suele causar problemas. IPv4 e IPv6 son independientes, y un firewall que sólo cubre IPv4 deja abiertos en IPv6 los servicios [::]. Este problema concreto tiene su propio artículo: el problema del firewall de IPv6.
FAQ
¿Cómo puedo ver qué puertos están abiertos en mi servidor Linux?
Ejecute sudo ss -tlnp para TCP o sudo ss -ulnp para UDP. El comando muestra todos los sockets en escucha, el puerto, la dirección local a la que están vinculados y el proceso propietario. Consulte la columna Local Address: 0.0.0.0 o [::] significa que el servicio está expuesto a la red, mientras que 127.0.0.1 significa que sólo escucha en la propia máquina.
¿Cuál es la diferencia entre 0.0.0.0 y 127.0.0.1?
0.0.0.0 significa «escuchar en todas las direcciones IPv4», incluida la pública, por lo que se puede acceder al servicio desde la red. 127.0.0.1 es la dirección de loopback que la máquina utiliza para comunicarse consigo misma. No es enrutable desde ningún otro lugar, por lo que un servicio vinculado a ella sólo está disponible localmente. Vincule los servicios internos a 127.0.0.1 para que nunca queden expuestos.
¿Tengo que abrir un puerto en el firewall para que funcione un servicio?
Sólo para los servicios a los que deban acceder otras máquinas. Un servicio vinculado a 127.0.0.1 no necesita una regla del firewall porque ningún sistema externo puede acceder a él. Un servicio en 0.0.0.0 o [::] necesita una regla del firewall que permita el tráfico y debe quedar denegado de forma predeterminada hasta que añada una regla.
¿Cuál es la diferencia entre un puerto TCP y un puerto UDP?
TCP está orientado a conexión y lo utilizan la mayoría de los servicios, como SSH, los servidores web y las bases de datos. UDP no utiliza conexión y lo usan DNS y algunas VPN. El mismo número en TCP y UDP corresponde a puertos independientes, por lo que 53/tcp y 53/udp son diferentes. Al escribir reglas del firewall, debe indicar el protocolo, por ejemplo 22/tcp.