Seguridad de Red
Tabla de Contenidos
- Vision General — Modelo de 4 Capas
- Capa 1: Cloudflare Edge
- Capa 2: Cloudflare Worker (API Proxy)
- Capa 3: Cloudflare Access (Zero Trust)
- Capa 4: Autenticacion Aplicativa
- Headers de Seguridad por Proyecto
- Ataques Mitigados
1. Vision General — Modelo de 4 Capas
Nvito implementa un modelo de seguridad en profundidad (defense-in-depth) con 4 capas independientes. Cada capa actua como un filtro: si una falla, las siguientes continuan protegiendo el sistema.
| Capa | Que protege | Aplica a |
|---|---|---|
| 1. Cloudflare Edge | Trafico de red (DDoS, bots, exploits conocidos) | Todos los subdominios |
| 2. Worker Proxy | IP del origin, autenticacion API-a-API | Solo api.nvito.mx en produccion |
| 3. Zero Trust Access | Acceso no autorizado al panel y docs | Solo admin.nvito.mx y docs.nvito.mx |
| 4. Auth Aplicativa | Acceso a datos, RBAC, token theft, CSRF, XSS | Cada aplicacion con su mecanismo |
2. Capa 1: Cloudflare Edge
Todo el trafico hacia nvito.mx y sus subdominios pasa por la red edge de Cloudflare antes de llegar a cualquier origin server. Esta capa es transparente para la aplicacion y opera a nivel de red/transporte.
2.1 DDoS Mitigation
Cloudflare provee mitigacion automatica de DDoS en 3 niveles:
| Nivel | Tipo de ataque | Mitigacion |
|---|---|---|
| L3/L4 | SYN flood, UDP flood, amplification | Filtrado automatico en el edge, sin configuracion |
| L7 | HTTP flood, slowloris, request bursts | Analisis de patrones + challenge automatico |
| DNS | DNS amplification, query flood | Anycast absorbe el volumen |
La mitigacion L3/L4 esta siempre activa en todos los planes de Cloudflare (incluido Free). La mitigacion L7 se beneficia del plan Pro para reglas WAF gestionadas adicionales.
2.2 WAF (Web Application Firewall)
| Funcionalidad | Plan Free | Plan Pro |
|---|---|---|
| Managed Rules (OWASP) | No | Si (SQLi, XSS, RCE, etc.) |
| Custom Rules | 5 reglas | 20+ reglas |
| Rate Limiting Rules | 1 regla | 5+ reglas |
| Security Level | Configurable | Configurable |
Nvito actualmente opera en el plan Free. Las managed rules de OWASP (inyeccion SQL, XSS reflejado, RCE) requieren el plan Pro ($20/mes). La proteccion actual se complementa con:
- Custom rules para bloquear User-Agents sospechosos
- Rate limiting en endpoints de API
- Bot Fight Mode
Plan Pro para produccion
Se recomienda activar el plan Pro de Cloudflare ($20/mes) al lanzar a produccion para obtener las managed rules WAF. Mientras tanto, la aplicacion implementa sus propias validaciones contra SQLi y XSS a nivel de codigo (Zod validation, DOMPurify, CSP).
2.3 SSL/TLS
| Configuracion | Valor |
|---|---|
| Modo | Full (Strict) |
| TLS minimo | 1.2 |
| HSTS | max-age=31536000; includeSubDomains |
| HTTPS Redirect | Automatico (Always Use HTTPS) |
| Certificate Transparency | Habilitado |
El modo Full (Strict) significa que Cloudflare verifica que el certificado del origin sea valido y no este expirado. Esto previene ataques man-in-the-middle entre Cloudflare y el origin.
2.4 Rate Limiting
| Regla | Aplica a | Threshold | Accion |
|---|---|---|---|
| API Rate Limit | api.nvito.mx/v1/* | 100 req / 10s por IP | Block (429) |
| Auth Rate Limit | */api/auth/* | 10 req / 60s por IP | Block (429) |
| Login Brute Force | */sign-in* | 5 req / 15min por IP | JS Challenge |
2.5 Bot Fight Mode
Bot Fight Mode esta habilitado en Cloudflare. Analiza patrones de comportamiento (fingerprinting JS, headless browser detection, TLS fingerprint) y desafia automaticamente a bots sospechosos sin afectar a usuarios legitimos.
3. Capa 2: Cloudflare Worker (API Proxy)
En produccion, api.nvito.mx no apunta directamente a Railway. En su lugar, un Cloudflare Worker intercepta todas las requests y las redirige al origin despues de inyectar un token de autenticacion API-a-API.
3.1 Arquitectura del Worker
3.2 Beneficios del Worker Proxy
| Beneficio | Detalle |
|---|---|
| IP del origin oculta | La URL publica de Railway (*.up.railway.app) nunca se expone. El trafico solo llega via Cloudflare. |
| Autenticacion API-a-API | El header X-CF-API-Token garantiza que solo requests que pasen por Cloudflare llegan al backend. Requests directas a Railway son rechazadas con 403. |
| Edge computing | El Worker corre en 300+ data centers de Cloudflare. La latencia de inyeccion del header es de menos de 1ms. |
| Rate limiting doble | Cloudflare rate-limita en el edge; el backend puede aplicar su propio rate limiting adicional. |
3.3 Limites del Free Tier
| Recurso | Limite Free |
|---|---|
| Requests/dia | 100,000 |
| CPU time/request | 10ms |
| Script size | 1 MB |
| Subrequests/request | 50 |
Con el trafico esperado en las primeras fases de Nvito, el free tier es mas que suficiente. El Worker es extremadamente ligero (solo inyecta un header y hace un fetch al origin).
Solo en produccion
El Worker proxy solo se usa en produccion (api.nvito.mx). En DEV y TEST, los subdominios dev-api.nvito.mx y test-api.nvito.mx apuntan directamente al VPS via registro A. El VPS no requiere el header X-CF-API-Token.
4. Capa 3: Cloudflare Access (Zero Trust)
Cloudflare Access protege subdominios seleccionados con autenticacion Zero Trust antes de que el request llegue al origin. Actua como un reverse proxy de identidad.
4.1 Subdominios Protegidos
| Subdominio | Protegido por CF Access | Razon |
|---|---|---|
admin.nvito.mx | Si | Panel administrativo con datos sensibles |
dev-admin.nvito.mx | Si | Mismo contenido que produccion, datos de desarrollo |
test-admin.nvito.mx | Si | Mismo contenido que produccion, datos de QA |
docs.nvito.mx | Si | Documentacion tecnica confidencial |
api.nvito.mx | No | API publica consumida por clientes programaticos |
app.nvito.mx | No | PWA publica para invitados (auth propia via BFF) |
inv.nvito.mx | No | Invitaciones publicas para invitados finales |
4.2 Flujo de Autenticacion
4.3 Configuracion de Access
| Parametro | Valor |
|---|---|
| Metodo de autenticacion | Email OTP (One-Time Pin) |
| Emails permitidos | Lista explicita de emails autorizados |
| Duracion de session | 24 horas |
| Reautenticacion | Cada 24 horas o al cerrar el browser |
| Usuarios incluidos en Free | Hasta 50 usuarios |
Doble autenticacion en admin
Para acceder a admin.nvito.mx, un usuario debe pasar dos capas de autenticacion independientes: primero Cloudflare Access (email OTP) y luego Clerk (email + password). Esto es intencional: CF Access protege a nivel de red, Clerk protege a nivel de aplicacion con RBAC granular.
4.4 Politicas de Access
Las politicas definen quien puede acceder a cada aplicacion protegida:
Aplicacion: nvito-admin
├── Policy: Allow Team Members
│ ├── Include: Emails ending in @nvito.mx
│ └── Include: Specific emails (founders, devs)
└── Policy: Deny Everyone Else
└── Default deny all
Aplicacion: nvito-docs
├── Policy: Allow Development Team
│ ├── Include: Emails ending in @nvito.mx
│ └── Include: Specific emails (stakeholders)
└── Policy: Deny Everyone Else
└── Default deny all
5. Capa 4: Autenticacion Aplicativa
Cada aplicacion de Nvito implementa su propio mecanismo de autenticacion adaptado a su caso de uso.
5.1 nvito-admin — Clerk SSO + RBAC
| Aspecto | Detalle |
|---|---|
| Provider | Clerk 6 (Next.js SDK) |
| Metodo | Email + password, con opcion de OTP |
| Token | JWT firmado por Clerk, verificado en backend |
| RBAC | 8 roles, 40+ permisos granulares |
| Guards (backend) | ClerkAuthGuard + RoleGuard + AdminPanelGuard |
| Multi-org | Header X-Organization-Id para Super/Platform Admin |
Cadena de guards para cada request del admin:
5.2 nvito-pwa — BFF con Cookies HttpOnly
| Aspecto | Detalle |
|---|---|
| Patron | Backend-For-Frontend (BFF) |
| Tokens | JWT almacenados en cookies HttpOnly encriptadas (AES-256-GCM) |
| Cookies | __Host-nvito-at (access, 15min), __Host-nvito-rt (refresh, 30d) |
| CSRF | Double-submit: cookie __Host-nvito-csrf + firma HMAC-SHA256 en __Host-nvito-csrf-sig |
| Proxy | Todo pasa por /api/proxy/* → descifra JWT → forward a nvito-api |
| CSP | connect-src 'self' bloquea llamadas directas al API desde JS |
5.3 nvito-client — JWT Independiente
| Aspecto | Detalle |
|---|---|
| Auth | JWT propio (independiente de Clerk) |
| Storage | expo-secure-store (encriptado en dispositivo) |
| Guard (backend) | MobileAuthGuard (verifica JWT mobile) |
| Login Host | Codigo de evento + PIN |
| Login Guest | Access token via deep link / QR |
| Auto-refresh | Proactivo antes de expiracion |
5.4 nvito-invitations — Sin Autenticacion
| Aspecto | Detalle |
|---|---|
| Auth | Ninguna (contenido publico) |
| Proteccion | Validacion de slug (regex + longitud), DOMPurify, CSP strict |
| SSRF prevention | validateCdnUrl() contra whitelist de hosts CDN |
| XSS prevention | escapeJsString() + escapeHtmlAttr() context-aware |
| Frame protection | X-Frame-Options: DENY en rutas publicas |
5.5 Tabla Comparativa
| Feature | nvito-admin | nvito-pwa | nvito-client | nvito-invitations |
|---|---|---|---|---|
| Autenticacion externa | Clerk SSO | JWT via BFF | JWT propio | Ninguna |
| Tokens en browser JS | Si | No | No | No |
| CSRF protection | Clerk built-in | Double-submit HMAC | N/A (nativo) | N/A (read-only) |
| Rate limiting | UserThrottlerGuard | BFF + API | API guard | Cloudflare edge |
| RBAC | 8 roles, 40+ perms | HOST/GUEST | HOST/GUEST | N/A |
| Multi-org | Si | No | No | No |
| CF Access | Si | No | No | No |
| CSP headers | Si | Si | No | Si |
6. Headers de Seguridad por Proyecto
Cada proyecto configura sus propios headers de seguridad HTTP, adaptados a su caso de uso.
6.1 Headers Comunes
| Header | Valor | Proposito |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains | Forzar HTTPS durante 1 ano |
X-Content-Type-Options | nosniff | Prevenir MIME type sniffing |
Referrer-Policy | strict-origin-when-cross-origin | Limitar info en header Referer |
Permissions-Policy | camera=(), microphone=(), geolocation=() | Deshabilitar APIs sensibles |
6.2 Content-Security-Policy por Proyecto
nvito-admin (next.config.ts):
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.clerk.accounts.dev;
connect-src 'self' https://api.nvito.mx https://*.clerk.accounts.dev;
img-src 'self' https://cdn.nvito.mx https://img.clerk.com data:;
frame-src https://*.clerk.accounts.dev;
nvito-pwa (next.config.ts):
default-src 'self';
script-src 'self' 'unsafe-inline';
connect-src 'self'; /* Solo BFF local, bloquea API directa */
img-src 'self' https://cdn.nvito.mx data:;
nvito-invitations (next.config.mjs):
/* Rutas publicas /i/* */
default-src 'self';
script-src 'self' 'unsafe-inline';
frame-ancestors 'none'; /* No permitir embeds */
/* Rutas preview /preview/* */
frame-ancestors 'self' https://admin.nvito.mx https://dev-admin.nvito.mx;
6.3 X-Frame-Options
| Proyecto | Valor | Razon |
|---|---|---|
| nvito-admin | SAMEORIGIN | Permite iframes internos (preview de invitaciones) |
| nvito-invitations (publico) | DENY | Las invitaciones no deben embeberse en sitios externos |
| nvito-invitations (preview) | SAMEORIGIN | Permite preview iframe desde el admin |
| nvito-pwa | DENY | La PWA no debe embeberse |
7. Ataques Mitigados
La siguiente tabla resume los vectores de ataque mas relevantes y como cada capa los mitiga.
| Vector de Ataque | Capa | Mecanismo de Mitigacion |
|---|---|---|
| DDoS volumetrico (L3/L4) | 1 - CF Edge | Anycast absorbe volumen, filtrado automatico |
| DDoS aplicativo (L7) | 1 - CF Edge | Rate limiting, JS Challenge, Bot Fight Mode |
| Brute force login | 1 + 3 + 4 | Rate limiting CF + CF Access OTP + Clerk lockout |
| SQL Injection | 4 - App | Prisma ORM (parametrizado), Zod validation |
| XSS reflejado | 1 + 4 | WAF (Pro), CSP headers, React auto-escape, DOMPurify |
| XSS almacenado | 4 - App | DOMPurify en invitaciones, escapeJsString(), CSP |
| CSRF | 4 - App | Clerk built-in (admin), double-submit HMAC (PWA) |
| Token theft (XSS) | 4 - App | Cookies HttpOnly AES-256-GCM (PWA), SecureStore (mobile) |
| SSRF | 4 - App | validateCdnUrl() whitelist en invitaciones |
| Direct origin access | 2 - Worker | Header X-CF-API-Token requerido en produccion |
| Man-in-the-middle | 1 - CF Edge | TLS 1.2+, HSTS, Full (Strict) SSL |
| Session hijacking | 3 + 4 | CF Access session 24h, Clerk session management |
| Credential stuffing | 1 + 3 | Rate limiting + CF Access email whitelist |
| Clickjacking | 4 - App | X-Frame-Options: DENY, frame-ancestors 'none' |
| MIME confusion | 4 - App | X-Content-Type-Options: nosniff |
| Timing attacks | 4 - App | crypto.timingSafeEqual() en invitaciones |
Defense in depth
Ningun mecanismo individual es infalible. La fortaleza del modelo radica en que cada capa compensa las debilidades de las otras. Un atacante debe evadir todas las capas simultaneamente para comprometer el sistema.