Servidores Linux

Red, puertos y firewall

Lección 7 de 8 · 15 min

Un puerto es una puerta numerada

Un servidor tiene una dirección, y en esa dirección hay miles de puertos numerados. Cada programa que atiende peticiones se pone a escuchar en uno: el web en el 80 y el 443, el SSH en el 22, PostgreSQL en el 5432.

La pregunta de seguridad no es cuántos puertos existen, sino cuáles están escuchando y quién puede llegar a ellos.

Ver qué está escuchando en tu servidor
sudo ss -tulpn
Resultado
Netid  State   Local Address:Port   Process
tcp    LISTEN  0.0.0.0:22          sshd
tcp    LISTEN  0.0.0.0:80          nginx
tcp    LISTEN  0.0.0.0:443         nginx
tcp    LISTEN  127.0.0.1:5432      postgres
tcp    LISTEN  0.0.0.0:3306        mysqld

Compara las dos últimas líneas: ahí está la lección entera.

127.0.0.1:5432 significa que PostgreSQL solo escucha desde dentro de la propia máquina. Nadie de fuera puede alcanzarlo, aunque el firewall estuviera abierto.

0.0.0.0:3306 significa que MySQL escucha por todas las interfaces, incluida internet. Casi nadie lo decidió a propósito: es la configuración que venía. Es el hallazgo más frecuente en una revisión de seguridad.

Las dos direcciones que hay que saber leer

127.0.0.1 - solo aquí dentro

Es la propia máquina hablando consigo misma. Ningún equipo externo puede conectarse, pase lo que pase con el firewall.

Es donde debe escuchar toda base de datos que solo use una aplicación de la misma máquina.

0.0.0.0 - por todas partes

Escucha en todas las interfaces de red. Si la máquina está en internet, está en internet.

Correcto para un servidor web; casi nunca correcto para una base de datos.

Dos capas, no una

Que un servicio escuche en 0.0.0.0 y que el firewall lo deje pasar son cosas distintas.

Lo sólido es cerrar las dos: que escuche solo donde debe y que el firewall no abra ese puerto.

El firewall: UFW

Ubuntu trae UFW -firewall sencillo-, que es una capa amable sobre el sistema de filtrado del núcleo. Con cinco comandos se cubre lo que necesita el 95% de los servidores.

La idea es simple: se cierra todo lo que entra, y se abre solo lo que tiene que estar abierto. Lo que sale se deja pasar.

Antes de tocar nada: el orden importa y no es negociable. Si activas el firewall con la política de bloquear la entrada y no has permitido antes el SSH, se corta tu propia sesión y te quedas fuera del servidor.

La regla de SSH va primero, y el enable después. Si estás en un VPS, comprueba antes que tu proveedor te ofrece una consola de emergencia por si acaso.

Configurar el firewall, en este orden exacto

  1. 1. Fijar la política por defecto

    sudo ufw default deny incoming
    sudo ufw default allow outgoing

    Todo lo que entra se bloquea salvo lo que abras; todo lo que sale, pasa. Todavía no está activo: esto solo define el criterio.

  2. 2. Permitir SSH - este paso NO se salta

    sudo ufw allow OpenSSH

    Si cambiaste el puerto del SSH, aquí va el número: sudo ufw allow 2222/tcp.

    Es literalmente el paso que decide si vas a poder volver a entrar.

  3. 3. Abrir lo que el servidor tenga que servir

    sudo ufw allow 80/tcp y sudo ufw allow 443/tcp para un servidor web.

    Y nada más. Cada puerto abierto es una puerta que hay que defender: si no sabes por qué está abierto, no lo abras.

  4. 4. Activar y comprobar

    sudo ufw enable y luego sudo ufw status verbose.

    Lee la lista y confirma que SSH aparece. Sin cerrar esta sesión, abre otra desde tu equipo para verificar que sigues entrando.

Cómo queda, y cómo se afina
sudo ufw status numbered

# Abrir un puerto SOLO para una direccion concreta (lo ideal para una BD)
sudo ufw allow from 190.85.10.20 to any port 5432

# Quitar una regla por su numero
sudo ufw delete 3
Resultado
Status: active

     To                    Action      From
[ 1] OpenSSH               ALLOW IN    Anywhere
[ 2] 80/tcp                ALLOW IN    Anywhere
[ 3] 443/tcp               ALLOW IN    Anywhere

La forma allow from es la que conviene interiorizar: en vez de abrir un puerto al mundo, se abre a una dirección concreta. Es la diferencia entre una base de datos accesible desde internet y una accesible desde tu oficina.

Endurecer el acceso por SSH

Un servidor recién puesto en internet empieza a recibir intentos de acceso en minutos. No hace falta que nadie te haya elegido: son programas recorriendo direcciones y probando usuarios y contraseñas comunes.

Con la llave ya funcionando -lección 2-, tres cambios en la configuración del SSH cierran esa vía casi por completo.

Los tres ajustes, en /etc/ssh/sshd_config
# No permitir entrar directamente como root
PermitRootLogin no

# No aceptar contrasenas: solo llaves
PasswordAuthentication no

# Y si solo entran dos personas, decirlo
AllowUsers ana carlos

Este es el momento de mayor riesgo del curso, y tiene una forma segura de hacerse. Si desactivas las contraseñas sin que tu llave funcione, te quedas fuera.

Procedimiento: haz una copia (sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak), edita, valida con sudo sshd -t -que revisa la sintaxis sin aplicar nada-, recarga con sudo systemctl reload ssh, y sin cerrar esta sesión abre otra terminal y comprueba que entras. Solo entonces cierra la primera.

fail2ban: el portero que se cansa

Aun con llaves, el registro se llena de intentos. fail2ban lee esos registros y bloquea temporalmente la dirección que falla demasiadas veces seguidas.

No sustituye a nada de lo anterior -es una capa más-, pero reduce muchísimo el ruido y frena los intentos automáticos.

Instalarlo y ver qué está bloqueando
sudo apt install fail2ban
sudo systemctl enable --now fail2ban

# Ver el estado de la vigilancia sobre SSH
sudo fail2ban-client status sshd
Resultado
Status for the jail: sshd
|- Currently failed: 2
|- Total failed:     18443
`- Currently banned: 7

Ese Total failed: 18443 es de un servidor normal, sin nada especial. Es el mejor argumento de esta lección: los intentos no son una hipótesis. Fíjate en el --now del comando: hace enable y start a la vez, que es el descuido de la lección 5.

Problemas típicos de esta lección

Me quedé fuera del servidor

Casi siempre por activar el firewall sin permitir SSH, o por desactivar las contraseñas sin llave.

La salida es la consola del proveedor -VNC o consola serie del panel-, que no pasa por la red. Si es una máquina virtual local, se entra por su ventana. Por eso conviene saber que existe antes.

Abrí el puerto y sigue sin responder desde fuera

Hay tres capas y hay que revisarlas en orden: que el servicio esté escuchando (ss -tulpn), que UFW lo permita (ufw status), y que el firewall del proveedor -grupo de seguridad, panel del VPS- también lo permita.

La tercera es la que más se olvida, porque no está en la máquina.

¿Sirve cambiar el SSH a otro puerto?

Reduce el ruido de los escaneos automáticos, y poco más: quien escanee en serio encuentra el puerto igual.

Es cosmética útil, no una medida de seguridad. Las que cuentan son la llave y desactivar las contraseñas. Y si lo cambias, acuérdate de la regla de UFW.

Direcciones IPv6

Si el servidor tiene IPv6, las reglas hay que tenerlas en las dos familias. UFW lo hace solo cuando IPV6=yes está en /etc/default/ufw.

Un servicio puede quedar cerrado en IPv4 y abierto en IPv6, y pasa desapercibido: en ss -tulpn las líneas IPv6 se ven como [::].

Compruébalo tú mismo

En ss -tulpn ves tu base de datos escuchando en 0.0.0.0:5432. ¿Qué significa?

Vas a activar UFW en un servidor al que solo llegas por SSH. ¿Cuál es el orden correcto?

Vas a desactivar la autenticación por contraseña en SSH. ¿Cómo lo compruebas?

Lo que sigue

Ya tienes el servidor cerrado por fuera. La última lección es lo que lo hace recuperable: copias que de verdad restauran, tareas programadas -con la trampa de la zona horaria, que muerde a todo el mundo- y qué hacer cuando la máquina deja de responder.

Siguiente: Copias, tareas programadas y emergencias

Continuar ← Disco, memoria y procesos