Situación actual: PHP2Shell. Dos vulnerabilidades críticas de PHP (CVSS 9.2) permiten ejecutar código malicioso sin autenticación. Parches desde el 21/10/2026.Qué hacer ahora →

Cortafuegos para servidores web: abrir solo los puertos necesarios

Un servidor web suele necesitar hacia fuera solo dos puertos. Aun así, en muchos servidores escuchan en internet bases de datos, PHP-FPM o interfaces de administración. Cómo encontrar los servicios abiertos y cerrar lo que no se necesita.

Actualizado 6 min de lecturaRefuerzo y configuración

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.

¿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.

Paso 1: averiguar qué escucha

Antes de escribir reglas, hágase una idea general. Los comandos siguientes solo leen:

# 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.

#!/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.

Quien prefiera algo más sencillo usa ufw en Ubuntu. Es importante el orden: primero la liberación de SSH y luego activarlo.

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; qué otros rastros apuntan a una intrusión figura en ¿Ya estoy comprometido?.

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.

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

Contacto inmediato

Cada hora cuenta. Escríbanos ahora.

Describa brevemente el sistema, la versión de PHP y lo que ha observado. Nos pondremos en contacto, aclararemos la situación y trabajaremos en remoto hasta que el incidente quede cerrado y documentado.

Ayuda inmediata