Configuración de firewall

Qué puertos usa HeroCtl, cuáles necesitan estar abiertos y cuáles nunca deberían exponerse a internet.

Red·9 min de lectura·última revisión 2026-04-26

Un cluster HeroCtl saludable tiene un conjunto pequeño y fijo de puertos. Este documento muestra cuáles son, qué hace cada uno y cómo configurar el firewall del sistema operativo para liberar exactamente lo necesario, ni más ni menos.

Puertos en uso

PuertoProtocoloFunciónQuién necesita acceder
80TCPRouter de ingress (HTTP)Internet entera
443TCPRouter de ingress (HTTPS)Internet entera
8080TCPAPI del plano de controlOperadores y CLI, vía VPN o allowlist
8443TCPPanel web TLSOperadores, vía VPN o allowlist
4646TCPCoordinación interna entre nodos (consenso)Solo otros nodos del cluster
4647TCPRPC entre coordinador y workersSolo otros nodos del cluster
4648TCP+UDPGossip entre nodosSolo otros nodos del cluster

La regla general es simple:

  • 80 y 443 abren al mundo. Es el punto de entrada de tus aplicaciones.
  • 8080 y 8443 nunca deberían estar abiertas a internet pública.
  • 4646, 4647 y 4648 quedan restringidas a los IPs internos del cluster.

Atención: Exponer 8080 sin allowlist es el error de configuración más común en clusters nuevos. Cualquier persona con el token admin puede enviar jobs. Trata ese puerto como SSH.

Topología recomendada

                     internet
                        │
                  ┌─────┴─────┐
                  │  80, 443  │   ← cualquier origen
                  └─────┬─────┘
                        │
                ┌───────┴───────┐
                │   nós do      │
                │   cluster     │
                └───────┬───────┘
                        │
                  ┌─────┴─────┐
                  │ 4646-4648 │   ← apenas IPs internos
                  └───────────┘
                        │
                  ┌─────┴─────┐
                  │ 8080,8443 │   ← apenas VPN ou allowlist
                  └───────────┘

Ubuntu y Debian (ufw)

Configuración mínima para un nodo servidor:

# regras default
sudo ufw default deny incoming
sudo ufw default allow outgoing

# acesso administrativo (ajuste o IP de origem)
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp comment 'SSH operador'
sudo ufw allow from 203.0.113.10 to any port 8080 proto tcp comment 'API'
sudo ufw allow from 203.0.113.10 to any port 8443 proto tcp comment 'Painel'

# tráfego público
sudo ufw allow 80/tcp comment 'Ingress HTTP'
sudo ufw allow 443/tcp comment 'Ingress HTTPS'

# comunicação interna entre nós (substitua pelos IPs reais)
for ip in 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4; do
  sudo ufw allow from $ip to any port 4646 proto tcp
  sudo ufw allow from $ip to any port 4647 proto tcp
  sudo ufw allow from $ip to any port 4648
done

sudo ufw enable
sudo ufw status numbered

En nodos que son solo worker (sin panel expuesto), salta las líneas 8080 y 8443.

RHEL, Fedora, AlmaLinux (firewalld)

# zonas separadas: pública para 80/443, interna para portas de cluster
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https

# zona internal recebe os IPs do cluster
sudo firewall-cmd --permanent --zone=internal --add-source=10.0.0.0/24
sudo firewall-cmd --permanent --zone=internal --add-port=4646/tcp
sudo firewall-cmd --permanent --zone=internal --add-port=4647/tcp
sudo firewall-cmd --permanent --zone=internal --add-port=4648/tcp
sudo firewall-cmd --permanent --zone=internal --add-port=4648/udp

# acesso admin: zone trusted com IP do operador
sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10
sudo firewall-cmd --permanent --zone=trusted --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=trusted --add-port=8443/tcp

sudo firewall-cmd --reload
sudo firewall-cmd --list-all-zones

iptables directo

Si prefieres reglas explícitas, o usas un sistema sin ufw/firewalld:

# tráfego estabelecido
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT

# ingress público
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# admin restrito
iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 203.0.113.10 --dport 8080 -j ACCEPT
iptables -A INPUT -p tcp -s 203.0.113.10 --dport 8443 -j ACCEPT

# cluster interno (repita para cada IP)
iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 4646 -j ACCEPT
iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 4647 -j ACCEPT
iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 4648 -j ACCEPT
iptables -A INPUT -p udp -s 10.0.0.0/24 --dport 4648 -j ACCEPT

# default deny
iptables -P INPUT DROP

# persistir
sudo netfilter-persistent save

Cloud firewall en capa superior

Aun con ufw correcto en cada nodo, vale activar el firewall del proveedor de nube como segunda capa. Si el ufw cae por un cambio mal hecho, el cloud firewall sigue protegiendo.

DigitalOcean Cloud Firewall

Crea un firewall y asígnalo a todas las droplets del cluster:

DirecciónTipoOrigenPuerto
InboundTCPAnywhere80, 443
InboundTCPIPs del operador22, 8080, 8443
InboundTCPTag heroctl-cluster4646, 4647, 4648
InboundUDPTag heroctl-cluster4648
OutboundAllAnywhereAll

Usa tags en vez de IPs para 4646-4648 — cuando agregas un nodo nuevo con la tag, ya entra en la regla.

AWS Security Groups

Crea dos security groups:

  • heroctl-public: 80 y 443 desde 0.0.0.0/0. Asígnalo a todos los nodos.
  • heroctl-cluster: 4646-4648 con origen en el propio security group (self-reference). Para 8080 y 8443, source en el security group del bastion.

Hetzner Cloud Firewall

Hetzner no tiene self-reference. Usa la red privada del proyecto y libera por CIDR:

allow tcp 80,443 from 0.0.0.0/0
allow tcp 4646,4647,4648 from 10.0.0.0/16
allow udp 4648 from 10.0.0.0/16
allow tcp 8080,8443 from <ip-do-operador>/32

Cloudflare al frente

Para protección contra ataques volumétricos, poner Cloudflare en modo proxy delante del cluster funciona bien. Puntos a tener en cuenta:

  • Para emisión de certificado, usa DNS-01 (no HTTP-01). El modo proxy rompe HTTP-01.
  • Restringe 80 y 443 de los nodos para que acepten solo los rangos de IP de Cloudflare. La lista oficial está en https://www.cloudflare.com/ips-v4. Actualiza vía cron mensual.
  • Habilita "Full (strict)" en Cloudflare. No uses "Flexible" — eso hace que Cloudflare hable HTTP con tu cluster aunque el usuario tenga HTTPS.

Bloqueando acceso administrativo

La regla más importante de este documento. El puerto 8080 no puede estar accesible desde internet pública. Tres caminos viables:

  1. VPN. WireGuard o Tailscale entre máquinas de los operadores y el cluster. Bloquea 8080 para cualquier origen fuera de la red de la VPN. Recomendado para equipos.
  2. Allowlist por IP fijo. Funciona para operador solo con IP residencial estable o VPS bastion.
  3. SSH tunnel. ssh -L 8080:localhost:8080 servidor cada vez que vayas a usar la CLI. Funciona, pero genera fricción.

La combinación que más aparece en producción es VPN + cloud firewall. El operador entra en la VPN, el cloud firewall solo libera 8080 para el rango de la VPN, y el ufw del nodo hace lo mismo por dentro.

Validación

Después de aplicar las reglas, valida desde fuera:

# da sua máquina, sem VPN, contra um IP do cluster
nmap -p 80,443,8080,8443,4646,4647,4648 <ip-do-no>

Resultado correcto: 80 y 443 abiertas, todas las demás cerradas (closed o filtered).

Próximos pasos

#firewall#ufw#iptables#red#seguridad