# Firewall y puertos

Redirecciones de puerto del VPS, SSH con vencimiento y listas de IP permitidas o excluidas en el firewall del host.

Fuente: https://ardumaker.com/docs/firewall-y-puertos/

- Categoría: Servidores e infraestructura
- Estado: Disponible
- Requisitos: Un VPS de la empresa con host asignado; Para ver y crear redirecciones: ser miembro de la empresa con acceso al VPS; Para cambiar la política de IP: ser admin de la empresa
- Herramientas MCP (Solo leen): `listar_redirecciones_vps`, `ver_politica_ip_puertos_vps`
- Herramientas MCP (Escriben o modifican): `crear_redireccion_vps`, `cambiar_politica_ip_puertos_vps`, `cambiar_lista_ip_app`
- Herramientas MCP (Destructivas): `eliminar_redireccion_vps`

## ¿Qué permite hacer?

- Exponer un puerto TCP o UDP de adentro del VPS en un puerto público del host, que se asigna solo.
- Abrir SSH (puerto 22) por una cantidad de horas, con cierre automático al vencer.
- Decidir qué IP llegan a los puertos redirigidos: a todos, solo a una lista o a todos menos una lista; para todo el VPS o para un puerto puntual.
- Ver qué redirecciones son de la plataforma (no se tocan) y cuáles son tuyas.

## ¿Cuándo conviene usarlo?

- Un servicio que no es HTTP (un juego, un broker MQTT, un servidor VPN) y necesita un puerto propio.
- Entrar por SSH desde tu equipo durante una ventana de trabajo.
- Dejar un puerto accesible solo desde la oficina o desde la IP de un cliente.

> **INFO:** Para una web no hace falta abrir puertos: los dominios entran por el 443 del host y llegan al nginx del VPS. Ver [Nginx](https://ardumaker.com/docs/nginx).

## ¿Cómo funciona en ArduMaker?

### Redirecciones de puerto

1. Se indica el puerto de adentro del VPS (`container_port`) y el protocolo (`tcp` por defecto, o `udp`).
2. Si ya existe una redirección a ese puerto y protocolo, se devuelve la misma: no se duplica.
3. El host elige un puerto libre (`host_port`) y crea la redirección hacia el VPS.
4. En el firewall del host (`ufw`) se abre ese puerto a todo internet, salvo que el puerto esté restringido o haya una política de IP global, que la redirección nueva hereda.
5. Desde afuera se llega con `<dnsip del VPS>:<host_port>`.

### Puertos que nunca quedan públicos

- PostgreSQL (5432), MySQL/MariaDB (3306) y Redis (6379, o el puerto en que se instaló, y su puerto TLS): la redirección se crea, pero solo es alcanzable por la red interna de la plataforma. Para abrir una base al exterior se usa el acceso externo de Apps, con su lista de IP.
- El puerto del agente de ArduMaker está reservado: la creación lo rechaza.
- La redirección al 443 del VPS es del nginx del VPS: nunca se abre a internet ni a otros VPS.

### SSH con vencimiento

Una redirección al puerto 22 acepta `closed_in_hs`: pasadas esas horas, la plataforma la borra sola y lo anota en el registro del VPS. El listado muestra `is_ssh: true` y las horas que faltan. Sin `closed_in_hs`, el SSH queda abierto hasta que se borre.

### Política de IP

| Modo | Regla en el firewall del host | Uso |
| --- | --- | --- |
| `todos` | `allow <puerto>` | Abierto a cualquiera (lo de siempre) |
| `solo` | Un `allow from <ip>` por IP; el resto cae en el `deny` por defecto | Lista blanca; además se cierra el acceso desde otros VPS del host |
| `excluir` | `deny from <ip>` antepuesto y el `allow` general | Bloquear IP puntuales |

- `alcance: "global"` aplica a todas las redirecciones del VPS; `alcance: "puerto"` a un `host_port` y gana sobre la global.
- Las listas aceptan IPv4 e IPv6, con o sin prefijo. Por defecto, hasta 20 entradas y prefijos no más amplios que /24 (IPv4) o /48 (IPv6). Nunca `0.0.0.0/0` ni `::/0`, ni loopback, multicast o link-local.
- Se aplica en el momento: primero se agregan las reglas nuevas y después se borran las viejas, para no dejar un hueco abierto ni cortar a todos de golpe.
- Los puertos de la plataforma no se tocan. El puerto de una app de Apps se cambia por el camino de Apps (misma lista; `excluir` no está disponible ahí).

## ¿Qué cambia realmente?

- En el host: la redirección (un dispositivo de proxy hacia el VPS) y sus reglas de `ufw`. Nada cambia dentro del VPS.
- Al borrar una redirección, primero se restauran sus reglas de IP y se olvidan sus políticas, y después se quita la regla general.
- La política queda guardada con su estado (`aplicada`, `pendiente` o `fallida`) y se ve en `ver_politica_ip_puertos_vps`.
- Cada alta, baja o cambio de política queda en el registro de actividad del VPS.

## IP real y puertos de la plataforma

El filtro por IP vive en el host, **antes** de la redirección: ahí se ve la IP real del cliente. El servicio dentro del VPS, en cambio, ve las conexiones de una redirección TCP como si vinieran de `127.0.0.1`. Si tu app necesita la IP del cliente, conviene publicarla como web (por nginx), donde llega en `X-Real-IP`.

| Clasificación (`motivo_plataforma`) | Qué es | ¿Editable? |
| --- | --- | --- |
| `agente` | Agente de ArduMaker | No (no se lista) |
| `nginx_del_vps` | Entrada web al 443 del VPS | No |
| `tailnet` | Bases de datos y Redis, solo red interna | No |
| `apps` | Creada por Apps (acceso externo o URL de una app) | Desde Apps |
| (vacío) | Tuya | Sí |

## Esquema

**Una conexión TCP a un puerto redirigido**

```text
Cliente (<dnsip>:<host_port>)
  ↓
Firewall del host (ufw) (todos / solo / excluir; ve la IP real)
  ↓
Redirección (host_port → container_port)
  ↓
Servicio en el VPS (ve la conexión desde 127.0.0.1)
```

## Resultado esperado

- `crear_redireccion_vps` devuelve `name` (el `device_name` para borrarla), `host_port`, `container_port`, `protocol`, `is_public_for_ip` y `solo_tailscale` (true si el puerto quedó solo en la red interna).
- `listar_redirecciones_vps` agrega a cada una `de_plataforma`, `editable`, `gestionado_por` y `motivo_plataforma`, y el `ip_host` (el `dnsip`) para conectarse.
- `ver_politica_ip_puertos_vps` devuelve la política global y, por puerto, la propia y la `efectiva`.

```bash
nc -vz <dnsip> <host_port>
ssh -p <host_port> usuario@<dnsip>
```

## Errores y resolución

| Respuesta | Causa | Qué hacer |
| --- | --- | --- |
| `container_port <n> is reserved` | Puerto reservado del agente | Usar otro puerto |
| 400 al crear | Puerto no positivo, protocolo distinto de tcp/udp, `closed_in_hs` no positivo, o el host sin puertos libres | Corregir el argumento |
| 409 `redireccion_de_plataforma` | La redirección la creó Apps | Quitarla desde la app |
| 404 `redirect_not_found` | Ese `host_port` o `device_name` no es de este VPS | Listar primero |
| 400 `ips_requeridas` | `solo` o `excluir` sin IP | Agregar al menos una |
| 400 `lista_ip_invalida` / `lista_ip_demasiado_amplia` | Entrada que no es IP o rango demasiado amplio; `data.invalid` dice cuáles | Corregir la lista |
| 409 `modo_no_soportado` | `excluir` sobre el puerto de una app | Usar `solo` o `todos` |
| 424 `regla_no_aplicada` | El firewall del host falló; la política quedó `fallida` | Reintentar la misma llamada |
| 403 | Un miembro intentó cambiar la política | Pedirlo a un admin |

Crear una redirección es seguro de repetir: si ya existe para ese puerto y protocolo, se devuelve la misma. Cambiar la política también lo es (aplicar la misma lista no cambia nada). Borrar una redirección corta en el acto las conexiones que la usan.

## Relación con MCP

Sí, en los perfiles `/mcp` y `/mcp/vps`.

| Herramienta | Tipo | Permiso |
| --- | --- | --- |
| `listar_redirecciones_vps` | Lectura | Miembro |
| `ver_politica_ip_puertos_vps` | Lectura | Miembro |
| `crear_redireccion_vps` | Escritura (acepta `idempotency_key`) | Miembro |
| `cambiar_politica_ip_puertos_vps` | Escritura | Admin de la empresa |
| `eliminar_redireccion_vps` | Destructiva | Miembro |
| `cambiar_lista_ip_app` | Escritura | Lista de IP del acceso externo de una app; exige las IP escritas |

Referencia en [/mcp/docs](https://ardumaker.com/mcp/docs) y ejemplos en [/mcp/vps](https://ardumaker.com/mcp/vps).

## Funciones relacionadas

- [Nginx](https://ardumaker.com/docs/nginx/)
- [Túneles SSH](https://ardumaker.com/docs/tuneles-ssh/)
- [Usuarios Linux](https://ardumaker.com/docs/usuarios-linux/)
- [PostgreSQL](https://ardumaker.com/docs/postgresql/)
- [Servidores VPS](https://ardumaker.com/docs/vps/)
