Un formulario de contacto o una API pública sin control es como un edificio sin portero: cualquiera entra, deja basura o intenta forzar la puerta. El spam, la fuerza bruta y el scraping no son “ruido menor”: saturan bandejas, consumen cuota de email y pueden tumbar un endpoint un viernes por la tarde.
Este artículo explica un enfoque en capas — el mismo patrón que usa este portafolio en producción con Astro, y aplicable a Laravel y Node — para que una persona no técnica entienda el porqué, y un técnico tenga checklist, orden de checks y errores a evitar.
Por qué importa para el negocio
Cada lead falso cuesta tiempo de ventas. Cada intento de login sin límite es una lotería contra credenciales filtradas. Cada webhook o endpoint “abierto” es superficie de abuso. Proteger no es paranoia: es mantener el canal útil para humanos reales y caro para bots.
- Bandeja usable: menos spam = más respuestas a clientes reales.
- Disponibilidad: rate limit evita que un script tumbe el servidor.
- Confianza: validar en servidor reduce basura en CRM y tickets inventados.
- Cumplimiento práctico: menos PII de atacantes en logs y bases.
Conceptos clave (simple + técnico)
El portero en capas
Ninguna capa sola basta. El honeypot atrapa bots torpes; el rate limit frena el volumen; el timing detecta envíos inhumanos; la validación y sanitización cuidan lo que entra; Turnstile añade fricción solo cuando hace falta. Como un edificio: recepción, cámara, llave y alarma — no solo un cartel de “prohibido”.
| Capa | Qué bloquea | Respuesta típica |
|---|---|---|
| Rate limiting | Volumen / fuerza bruta | 429 + Retry-After |
| Honeypot | Bots que rellenan todo | 200 silencioso (sin procesar) |
| Form timing | Envíos < ~3.5s | 400 |
| Origin check | Scripts cross-origin básicos | 403 |
| Turnstile | Bots más sofisticados | 400 si token inválido |
| Zod + sanitizar | Basura y payloads raros | 400 con errores de campo |
Rate limiting
Limita requests por IP (y, si aplica, por usuario) en una ventana de tiempo. En un solo proceso basta memoria; con varias réplicas hace falta Redis u otro store compartido. Ejemplos orientativos: login 5/min, reset password 3/hora, contacto 5/min.
Honeypot y timing
El honeypot es un campo oculto (display: none o fuera de pantalla) que los humanos no ven. Si llega lleno, rechaza en silencio (200 sin procesar) para no educar al bot. El timing guarda un timestamp al renderizar y rechaza envíos más rápidos que un humano razonable.
Validación, sanitización y origen
La validación del frontend mejora UX; la del servidor es la que importa. Esquemas (Zod u equivalente), strip de HTML en texto plano, longitudes máximas, y en producción comprobar Origin/Referer. No es infalible, pero filtra mucho ruido barato.
Guía práctica: flujo en un endpoint
- Rate limit check →
429si excede. - Honeypot check →
200silencioso si el campo oculto tiene valor. - Form timing check →
400si es demasiado rápido. - Origin check →
403si el origen no es el del sitio. - Turnstile (si está configurado) →
400si el token falla. - Validación con esquema →
400con errores de campo. - Sanitización → procesar (email, CRM, cola).
Honeypot bien hecho
- Oculto con CSS, no con
type="hidden"obvio si puedes evitarlo. - Nombre engañoso (
website,company_url) — nohoneypot. tabindex="-1"yautocomplete="off"; no debe ser accesible para lectores de pantalla de forma accidental.- Si está lleno: responder éxito falso, no
403explícito.
Cloudflare Turnstile
Cuando el volumen de spam justifica fricción extra, Turnstile es ligero y respeta privacidad frente a alternativas más agresivas. TURNSTILE_SITE_KEY en el cliente; TURNSTILE_SECRET_KEY solo en servidor. El servidor verifica el token antes de procesar.
Errores frecuentes
- Confiar solo en validación del frontend.
- Rate limit solo en login, no en contacto ni endpoints públicos.
- Honeypot visible, con label real, o enfocable por teclado/lectores.
- Responder
403al honeypot (el bot aprende y adapta). - Loguear payloads completos con emails y teléfonos (PII en logs).
- Rate limit en memoria con 3 réplicas (cada una tiene su contador).
- Mensajes de error que revelan si un email “existe” en el sistema.
Checklist de protección
- Lista de endpoints públicos sensibles (login, contacto, reset, webhooks).
- Rate limit con límites documentados y
Retry-After. - Honeypot + timing en formularios HTML.
- Origin/Referer check en producción.
- Esquema de validación en servidor + sanitización.
- Turnstile opcional cuando el spam lo justifica.
- Store compartido (Redis) si hay más de una réplica.
- Logs sin PII innecesaria; métricas de 429/400 para detectar ataques.
Conecta con auditoría de seguridad, ciberseguridad y APIs REST .