# Cortafuegos para servidores web: abrir solo los puertos necesarios

> Cortafuegos para servidores web: revisar puertos abiertos, liberar solo el 80 y el 443, restringir SSH y acotar conexiones salientes. Con nftables y ufw.

Fuente: https://phpsos.de/es/blog/firewall-fuer-webserver/  
Actualizado: 25/10/2026  
Proveedor: PHP SOS, Ayuda de emergencia para PHP y seguridad de servidores. Ayuda inmediata por WhatsApp: https://wa.me/491736494914?text=Hola%20PHP%20SOS%2C%20necesitamos%20ayuda%20con%20nuestro%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Sitio%20web%3A%20%E2%80%A6

**En resumen:** un cortafuegos para servidores web permite en entrada solo TCP 80 y 443, con HTTP/3 además UDP 443, y SSH únicamente desde redes conocidas. Todo lo demás se descarta: las bases de datos, cachés, PHP-FPM y las interfaces de administración no pertenecen a internet. Compruebe primero con `ss -tulpn` qué escucha, monte después un conjunto de reglas con la política por defecto «descartar» y pruebe el resultado desde fuera. Restringir las conexiones salientes limita además las consecuencias de una intrusión.

## Las puertas olvidadas junto a la puerta principal

En PHP2Shell la atención se dirigió al propio servidor web, a los puertos 80 y 443. Esos deben estar abiertos, o no habría sitio web. Pero en los inventarios posteriores a vulnerabilidades así suele llamar la atención otra cosa: junto a la puerta principal hay otras puertas abiertas. Una base de datos escucha en todas las interfaces de red, un pool de PHP-FPM en el puerto 9000, un servicio de caché sin contraseña, una interfaz de administración de la fase de instalación.

Cada una de estas puertas es una superficie de ataque propia con vulnerabilidades propias. Un cortafuegos que solo permite lo necesario las cierra con pocas reglas. Es una de las medidas más eficaces al asegurar un servidor propio, como describe también la página [Proteger por sí mismo servidores root y vServers](https://phpsos.de/es/server/root-server-vserver/).

## ¿Qué debe estar abierto y qué no?

El principio es una lista de permitidos: todo está cerrado y solo son accesibles los servicios liberados de forma consciente. El resumen siguiente ayuda a clasificar.

| Servicio | Puerto típico | ¿Accesible desde fuera? |
|---|---|---|
| HTTP y HTTPS | TCP 80, TCP 443 | sí |
| HTTP/3 (QUIC) | UDP 443 | solo si se usa |
| SSH | TCP 22 | solo desde redes conocidas o por VPN |
| Panel de hosting | según el producto | solo desde redes conocidas |
| MySQL/MariaDB, PostgreSQL | TCP 3306, TCP 5432 | no |
| Redis, Memcached | TCP 6379, TCP 11211 | no |
| PHP-FPM | TCP 9000 o socket Unix | no, mejor solo socket |
| Servidor de correo | TCP 25, 465, 587, 993 | solo si el servidor recibe o presta correo |

Un servicio que no tiene que ser accesible desde fuera debería además escuchar solo en `127.0.0.1` o en un socket Unix. Así sigue siendo inaccesible incluso si falla el cortafuegos. Para los accesos de administración sirven las liberaciones por IP o una VPN; los detalles figuran en el artículo [Aislar las áreas de administración mediante IP, VPN o protección adicional](https://phpsos.de/es/blog/admin-bereiche-abschirmen/).

## Paso 1: averiguar qué escucha

Antes de escribir reglas, hágase una idea general. Los comandos siguientes solo leen:

```bash
# Todos los puertos TCP y UDP en escucha con su proceso
sudo ss -tulpn
# Conjunto de reglas actual de nftables
sudo nft list ruleset
# Estado de ufw, si se usa
sudo ufw status verbose
```

En la salida de `ss`, fíjese en la dirección anterior al puerto. `0.0.0.0` o `[::]` significa: el servicio escucha en todas las interfaces. `127.0.0.1` significa: solo local. Anote para cada servicio si debe ser accesible desde fuera. Esta lista es a la vez una parte de su inventario de servidores.

## Cortafuegos para servidores web con nftables

nftables es el filtro de paquetes actual de Linux. El conjunto de reglas siguiente se orienta al ejemplo de la wiki oficial de nftables y añade una liberación de SSH solo desde una red de administración. Las direcciones son ejemplos de documentación y deben sustituirse.

```nft
#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    set verwaltung_v4 {
        type ipv4_addr
        flags interval
        elements = { 203.0.113.0/28 }
    }

    chain input {
        type filter hook input priority 0; policy drop;

        ct state vmap { established : accept, related : accept, invalid : drop }
        iifname lo accept

        # IPv6 necesita descubrimiento de vecinos
        icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
        icmp type echo-request limit rate 5/second accept
        icmpv6 type echo-request limit rate 5/second accept

        # Sitio web
        tcp dport { 80, 443 } accept
        # solo con HTTP/3:
        # udp dport 443 accept

        # SSH solo desde la red de administración
        ip saddr @verwaltung_v4 tcp dport 22 accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }
}
```

Compruebe el conjunto de reglas antes de cargarlo con `nft -c -f /etc/nftables.conf`. La primera línea, `flush ruleset`, borra todas las reglas existentes, también las que hayan registrado Docker o Fail2ban. En servidores con Docker u otros servicios que fijan reglas propias, adapte por eso el conjunto de reglas en lugar de sustituirlo en bloque. Cómo colabora Fail2ban con el cortafuegos figura en [Configurar Fail2ban para servidores web](https://phpsos.de/es/blog/fail2ban-fuer-webserver/).

Quien prefiera algo más sencillo usa `ufw` en Ubuntu. Es importante el orden: primero la liberación de SSH y luego activarlo.

```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow proto tcp from 203.0.113.0/28 to any port 22
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
```

> **Importante:**
> Cambie las reglas del cortafuegos en servidores remotos solo con una segunda vía de acceso, por ejemplo la consola de su proveedor. De lo contrario, una regla SSH errónea le dejará fuera a usted mismo.

## Conexiones salientes: la mitad infravalorada

La mayoría de los cortafuegos permiten todo en salida. Para un servidor web es demasiado generoso. Tras una intrusión, los atacantes usan las conexiones salientes para descargar herramientas, extraer datos o recibir órdenes. Por eso, los procesos del servidor web o de PHP que establecen conexiones inesperadas se consideran una señal de alerta.

Limitar las conexiones salientes es más laborioso, porque hay que conocer cada conexión legítima: orígenes de paquetes para actualizaciones, servicios de pago, interfaces, envío de correo, servidores de hora. Un camino pragmático es registrar primero las conexiones salientes, formar después una lista de permitidos y solo entonces bloquear. Cómo revisar las conexiones existentes lo describe [Revisar las conexiones salientes de un servidor](https://phpsos.de/es/blog/ausgehende-verbindungen-pruefen/); qué otros rastros apuntan a una intrusión figura en [¿Ya estoy comprometido?](https://phpsos.de/es/php2shell/bin-ich-gehackt-anzeichen/).

Para terminar, compruebe desde fuera, desde otro ordenador y solo contra sus propios sistemas, qué puertos son realmente accesibles. Solo esta prueba muestra si Docker, el cortafuegos del proveedor y las reglas del servidor dan juntos la imagen deseada.

## Conclusión: pocas reglas, gran efecto

Un cortafuegos de servidor web no tiene por qué ser complicado. Puertos web abiertos, administración solo desde redes conocidas, todo lo demás descartado: con estas reglas básicas desaparecen de internet las bases de datos, cachés y servicios olvidados. Es una de las medidas con mejor relación entre esfuerzo y beneficio.

Contra vulnerabilidades del servidor web o del propio PHP el cortafuegos no ayuda, porque precisamente esos puertos deben seguir abiertos. Su fuerza reside en mantener pequeña el resto de la superficie de ataque y, con una limitación de conexiones salientes, contener las consecuencias de una intrusión.

Lo decisivo es el mantenimiento. Cada servicio nuevo, cada contenedor y cada cambio en el proveedor pueden alterar el panorama. Por eso repita la comprobación desde fuera tras cada cambio importante y a intervalos fijos, por ejemplo una vez por trimestre.

## ¿Cómo ayuda PHP SOS en concreto?

- **Inventariar:** registramos todos los servicios en escucha y comprobamos desde fuera qué es realmente accesible.
- **Montar el conjunto de reglas:** elaboramos una lista de permitidos para conexiones entrantes y, donde tenga sentido, salientes, coordinada con Docker, Fail2ban y el cortafuegos del proveedor.
- **Cambiar con seguridad:** aplicamos los cambios con una segunda vía de acceso y un plan de retorno.
- **Documentar:** dejamos constancia de puertos, liberaciones y motivos en el marco del [refuerzo de servidores](https://phpsos.de/es/leistungen/server-haertung/).


## Preguntas frecuentes

**¿Qué puertos necesita un servidor web?**  
Para los visitantes, por lo general solo TCP 80 y 443 y, con HTTP/3, además UDP 443. SSH y las interfaces de administración solo deberían ser accesibles desde redes conocidas o mediante VPN. Los puertos de bases de datos, caché y PHP-FPM no pertenecen a internet.

**¿Protege un cortafuegos frente a PHP2Shell?**  
No. PHP2Shell se explota a través del servidor web, es decir, precisamente por los puertos que deben estar abiertos. Pero el cortafuegos reduce el resto de la superficie de ataque, y una limitación de las conexiones salientes puede contener las consecuencias de una intrusión.

**¿Por qué muestra ufw como cerrados puertos que sin embargo son accesibles?**  
Un caso conocido son los contenedores Docker: Docker registra los puertos publicados directamente en las reglas del filtro de paquetes, esquivando ufw. Por eso compruebe siempre además los puertos abiertos desde fuera.

**¿Basta el cortafuegos de mi proveedor de alojamiento?**  
Un cortafuegos del proveedor situado por delante es una buena segunda capa. Pero no sustituye al cortafuegos del servidor, porque no actúa ante un error en la configuración del proveedor ni ante conexiones internas. Lo mejor es usar ambos con las mismas reglas básicas.

## Fuentes

- [Wiki de nftables: conjunto de reglas sencillo para un servidor](https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server)
- [Ubuntu Server: cortafuegos (ufw)](https://ubuntu.com/server/docs/how-to/security/firewalls/)
- [BSI IT-Grundschutz (protección básica de TI de la Oficina Federal alemana de Seguridad de la Información)](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks)
