SSD Nodes Learn
Guías Matt ConnorPor Matt Connor · Actualizado 2026-07-24

configurar ufw para ipv6 en vps ubuntu

Evite que sus servicios queden expuestos por error. Aprenda por qué el firewall de su VPS puede estar bloqueando IPv4 pero dejando abierto todo el tráfico IPv6.

La trampa del firewall IPv6 en una frase

Su firewall protege IPv4. Su VPS casi con seguridad también tiene una dirección IPv6 pública, y muchos servicios escuchan en ella por defecto. Si su firewall solo cubre IPv4, o si utiliza un firewall de nube que solo filtra IPv4, cada uno de esos servicios es accesible desde todo internet vía IPv6, mientras que su lado IPv4 parece estar bloqueado. Usted prueba un puerto con curl, ve una conexión rechazada y se siente seguro. Un atacante se conecta al mismo puerto vía IPv6 y accede.

Esta guía muestra el origen de ese vacío en un VPS normal con Ubuntu 24.04, cómo ver exactamente qué está exponiendo y cómo cerrarlo. UFW no es el culpable aquí. En una instalación moderna de Ubuntu, UFW ya gestiona IPv6. La exposición proviene de las capas que lo rodean y de servicios que no sabía que estaban escuchando.

Por qué su VPS tiene IPv6 desde el inicio

Casi todos los VPS actuales incluyen una dirección IPv6 pública, a menudo un bloque /64 completo, junto con su dirección IPv4. Verifique la suya:

ip -6 addr show scope global
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
    inet6 2001:db8:2a::1/64 scope global

Ese 2001:db8:2a::1 es enrutable desde cualquier punto de internet, exactamente igual que su dirección IPv4. Ahora observe qué servicios están escuchando:

sudo ss -tlnp
State   Recv-Q  Local Address:Port   Process
LISTEN  0       0.0.0.0:22           sshd
LISTEN  0       [::]:22              sshd
LISTEN  0       127.0.0.1:5432       postgres
LISTEN  0       [::]:8080            docker-proxy

Lea detenidamente la columna Local Address. 0.0.0.0:22 significa "escuchar en todas las direcciones IPv4". [::]:22 significa "escuchar en todas las direcciones IPv6". 127.0.0.1:5432 está vinculado al loopback y no es público, por lo que la línea de Postgres es segura. Las dos líneas [::] responden a todo internet vía IPv6, y la línea docker-proxy es el tipo de configuración que se olvida tras iniciar el servicio.

La mayoría de los demonios se vinculan a :: por defecto, porque en Linux un socket :: suele aceptar también IPv4. Por tanto, la configuración predeterminada de un servidor nuevo es "responder en ambos protocolos, en todas partes". Su firewall es lo único que bloquea esto; por ello, un firewall que solo inspecciona un protocolo es un problema crítico.

El origen real de la brecha de IPv6

Existen cuatro fuentes comunes. Un servidor puede tener una o varias de ellas a la vez.

1. Un firewall de la nube que solo filtra IPv4. Muchos firewalls de proveedores y productos de security-groups se desarrollaron para IPv4; estos ignoran IPv6 o requieren reglas IPv6 adicionales que deben añadirse manualmente. Si su único firewall es el del panel del proveedor y este no cubre IPv6, sus servicios [::] están abiertos, independientemente de lo que indique la configuración del puerto 22 en IPv4. Revise la documentación de firewall de su proveedor y busque específicamente el término IPv6.

2. iptables configurado manualmente sin ip6tables. El comando iptables solo afecta a las tablas de IPv4. IPv6 tiene un comando completamente distinto, ip6tables, con sus propias reglas independientes. Si escribió un script de firewall con líneas iptables -A INPUT ... pero nunca escribió las reglas ip6tables correspondientes, su firewall IPv6 estará vacío. Una cadena INPUT vacía con una política predeterminada ACCEPT permite todo el tráfico:

sudo ip6tables -L INPUT -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Esa salida muestra el problema completo en una sola pantalla. IPv4 está filtrado, pero IPv6 acepta todo el tráfico.

3. Docker publicando puertos saltando el firewall. Al ejecutar docker run -p 8080:80, Docker inserta sus propias reglas antes que las de UFW. Por tanto, un puerto publicado es accesible incluso si ufw status indica que el puerto está denegado; en Docker moderno, esto también ocurre en IPv6. Por qué Docker omite UFW y cómo filtrar puertos de contenedores correctamente explica el mecanismo y las soluciones. Consulte los conceptos básicos de Docker Compose en un VPS para ver cómo se declaran estos puertos publicados.

4. UFW con IPv6 desactivado. UFW admite IPv6, pero solo si se le indica. Verifique el interruptor:

grep IPV6 /etc/default/ufw

Las versiones modernas de Ubuntu incluyen IPV6=yes, por lo que UFW aplica cada regla a ambos protocolos. Si ve IPV6=no, proveniente de una imagen antigua o una guía obsoleta, todas las reglas de UFW que haya escrito son solo para IPv4, dejando IPv6 sin gestionar.

Identifique exactamente qué está exponiendo

No haga suposiciones. Mida la exposición desde el exterior. Primero, liste sus listeners y anote cada uno vinculado a :::

sudo ss -tlnp | grep '::'

Luego, desde una máquina distinta, conéctese a la dirección IPv6 pública del servidor e intente acceder a un puerto que crea que está cerrado:

curl -6 -v http://[2001:db8:2a::1]:8080/

Si esto devuelve una página o un banner, el puerto está abierto en IPv6. Un puerto cerrado devuelve Connection refused o un timeout. Para obtener una visión completa, escanee la dirección IPv6 con nmap desde fuera del servidor:

nmap -6 2001:db8:2a::1

Cada puerto que nmap reporte como abierto en IPv6 es un puerto al que todo internet puede acceder, independientemente de lo que muestre su escaneo de IPv4. Comparar los escaneos de IPv4 e IPv6 simultáneamente es la forma más rápida de encontrar la brecha: cualquier cosa abierta en -6 pero cerrada en IPv4 es un servicio que su firewall no está cubriendo.

Cerrar la brecha

Configure UFW para cubrir ambos stacks y establecer denegar por defecto. Confirme el cambio, establezca una política de denegación por defecto para tráfico entrante y permita únicamente lo necesario:

sudo sed -i 's/^IPV6=no/IPV6=yes/' /etc/default/ufw
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verbose

Si UFW ya estaba activo al cambiar IPV6=yes, el cambio no surtirá efecto hasta que ejecute sudo ufw reload.

ufw status muestra cada regla dos veces: una vez de forma simple y otra con un sufijo (v6). Cuando vea las líneas (v6), UFW está filtrando IPv6:

22/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)

Si gestiona iptables manualmente, replique cada regla en ip6tables, o migre a nftables, cuyas tablas inet cubren IPv4 e IPv6 en un mismo lugar y eliminan este tipo de errores. Una única tabla de filtrado nftables inet es la solución más limpia cuando escribe sus propias reglas.

Vincule los servicios que no deban ser públicos a loopback. Una base de datos, un panel de administración o un endpoint de métricas rara vez requieren una dirección pública. Vincúlelos a 127.0.0.1 y ::1 para que no escuchen en una dirección enrutable. Para Postgres, configure listen_addresses = 'localhost'. Para un servidor de aplicaciones, vincúlelo a 127.0.0.1 y coloque un proxy inverso delante. Cerrar el listener es más efectivo que usar un firewall, ya que así no hay nada a lo que conectarse.

No confíe en UFW para proteger los puertos publicados de Docker. Publique los puertos de los contenedores en una dirección específica en lugar de en todas las interfaces, por ejemplo -p 127.0.0.1:8080:80, para que el puerto solo sea accesible desde el host y desde lo que usted decida mediante proxy. Cuando un contenedor deba ser público, colóquelo detrás de un proxy inverso Traefik y publique únicamente el proxy, no cada aplicación.

Añada reglas IPv6 en el firewall de su proveedor, o acepte que ese no es su firewall para IPv6 y deje que UFW o nftables en el host realicen esa tarea.

Verifique que realmente ha cerrado el acceso

Ejecute nuevamente la misma prueba externa tras realizar los cambios:

curl -6 -v http://[2001:db8:2a::1]:8080/
nmap -6 2001:db8:2a::1

El puerto que respondió anteriormente ahora debe rechazar la conexión o agotar el tiempo de espera, y nmap debe reportarlo como filtered o closed. Si un puerto sigue abierto, revise los cuatro puntos anteriores: un servicio aún vinculado a :: sin una regla delante, una regla de Docker situada antes de UFW, o un firewall del proveedor que no detectó IPv6.

Mantener los servicios sensibles fuera de internet por completo es una medida más robusta. Coloque SSH y paneles de administración tras una VPN WireGuard y aplique firewall a sus puertos para que respondan solo a través del túnel; así, la exposición de IPv6 dejará de ser un problema para ellos. Para mitigar los escaneos de fuerza bruta contra los servicios que permanezcan públicos, implemente Fail2ban delante de SSH sobre un firewall con política de denegación por defecto.

Si no está familiarizado con los puertos, qué son los puertos y cómo escuchan los servicios es la guía básica para leer primero.

FAQ

¿UFW bloquea IPv6 por defecto?

En una instalación moderna de Ubuntu 24.04, sí. UFW lee IPV6=yes desde /etc/default/ufw y aplica cada regla tanto a IPv4 como a IPv6, y ufw status muestra las reglas de IPv6 con un sufijo (v6). El problema ocurre cuando IPV6=no (de una imagen antigua o un tutorial viejo), cuando se depende de un firewall de proveedor que solo filtra IPv4, o cuando Docker publica un puerto saltándose UFW. Verifique la configuración con grep IPV6 /etc/default/ufw.

¿Cómo puedo verificar qué está exponiendo mi VPS en IPv6?

Ejecute sudo ss -tlnp y observe cada listener cuya dirección local comience con [::], lo que significa que responde en todas las interfaces IPv6. Luego, desde otra máquina, pruebe la dirección IPv6 pública del servidor directamente con curl -6 -v http://[YOUR:IPV6::ADDR]:PORT/, o realice un escaneo con nmap -6 YOUR:IPV6::ADDR. Cualquier puerto abierto en el escaneo de IPv6 pero cerrado en IPv4 representa una vulnerabilidad.

¿Por qué puedo acceder al puerto de mi contenedor Docker si UFW dice que está bloqueado?

Docker inserta sus propias reglas de firewall antes que las de UFW cuando se publica un puerto con -p, por lo que el puerto publicado es accesible aunque ufw status lo liste como denegado. Esto ocurre en IPv4, y también en IPv6 cuando el soporte de IPv6 de Docker está activo. Publique en una dirección específica como -p 127.0.0.1:8080:80, o coloque el contenedor detrás de un reverse proxy y publique únicamente el proxy.

¿Sigue siendo necesario un firewall IPv6 si mi firewall IPv4 es sólido?

Sí. IPv4 e IPv6 son pilas de red distintas con reglas de firewall independientes. Un conjunto perfecto de reglas IPv4 no afecta al tráfico IPv6. Si su VPS tiene una dirección IPv6 pública, como ocurre en casi todos los casos, cualquier servicio que escuche en :: seguirá siendo accesible vía IPv6 hasta que una regla de firewall IPv6 o un binding de loopback lo detenga.

¿Cómo hago que un servicio escuche solo en IPv4, o solo en localhost?

Configure la dirección de bind del servicio en su propia configuración. Use 127.0.0.1 para loopback de IPv4 únicamente, o 0.0.0.0 para todas las direcciones IPv4 sin listener de IPv6. Postgres usa listen_addresses, SSH usa ListenAddress, y la mayoría de los servidores de aplicaciones exponen un flag de host o bind. Confirme el resultado con sudo ss -tlnp y verifique que Local Address ya no muestre [::].