Varnish Configuration Language (VCL) es el lenguaje que utiliza Transparent Edge para definir el comportamiento del CDN. Esta referencia recoge los ejemplos más habituales organizados por subrutina y caso de uso, listos para copiar y adaptar.
Cuando tienes varios dominios o sitios web detrás del mismo CDN, necesitas indicarle a Transparent Edge a qué servidor debe enviar cada petición. Un backend es simplemente el servidor de origen donde vive tu aplicación o web.
Con este fragmento de VCL le dices al CDN: "cuando alguien pida algo en este dominio concreto, envía la petición al backend que le corresponde". Sin esta configuración, el CDN no sabría distinguir qué servidor debe responder a cada dominio.
El código comprueba la cabecera Host de cada petición entrante y, si coincide con el dominio configurado, asigna el backend correcto para enrutar el tráfico.
sub vcl_recv {
if (req.http.host == "miweb.test.es") {
set req.backend_hint = c622_web.backend();
}
}
Por defecto el WAF está desactivado. Para proteger tu sitio solo tienes que indicárselo al CDN añadiendo una cabecera especial en la fase de entrada. A partir de ese momento, todas las peticiones que lleguen a tu dominio pasarán por el motor de reglas antes de llegar a tu servidor.
El código siguiente activa el WAF para la totalidad del tráfico de tu sitio con una sola línea.
sub vcl_recv {
set req.http.TCDN-WAF-Enabled = "true";
}
Activar el WAF directamente en modo bloqueo puede ser arriesgado si no lo has probado antes: algunas peticiones legítimas de tus propios usuarios podrían ser bloqueadas por error (lo que se conoce como falso positivo).
El modo DetectionOnly es la solución: el WAF analiza todo el tráfico y registra las amenazas que detecta, pero no bloquea nada. Esto te permite revisar los registros durante unos días, identificar si hay falsos positivos, ajustar las excepciones necesarias y, solo entonces, activar el bloqueo real con total confianza.
Con el código siguiente el motor de reglas entra en modo observación. Puedes combinarlo con el ejemplo de activación global del WAF.
sub vcl_recv {
set req.http.TCDN-WAF-Set-SecRuleEngine = "#DetectionOnly";
}
El WAF aplica cientos de reglas predefinidas para detectar amenazas. En ocasiones, alguna de esas reglas puede identificar como sospechoso el tráfico normal de tu aplicación: por ejemplo, un formulario que envía código HTML, una API que recibe parámetros con caracteres especiales, o un panel de administración con operaciones avanzadas.
Cuando identificas que una regla concreta está bloqueando tráfico legítimo, puedes excluirla por su ID de regla en lugar de desactivar el WAF entero. Así mantienes toda la protección salvo esa regla específica.
El código siguiente permite indicar uno o varios IDs de reglas separados por espacio. Puedes obtener el ID de la regla que está causando el problema en los logs del WAF.
sub vcl_recv {
set req.http.TCDN-WAF-Allow-Rule-Exceptions = "12345 67890";
}
Puede que quieras tener el WAF activo en todo tu sitio pero necesites desactivarlo en una ruta específica: un endpoint interno que solo usan tus sistemas, una herramienta de administración con tráfico muy particular, o una ruta de API que envía datos en un formato que el WAF interpreta como amenaza.
La solución es activar el WAF globalmente y luego crear una excepción para esa ruta concreta. El CDN aplicará la protección a todo el sitio excepto en la ruta que tú indiques.
En el código siguiente puedes ver cómo se combina la activación global con la desactivación selectiva usando una condición sobre la URL.
sub vcl_recv {
if (req.http.host == "www.my-domain.com") {
set req.http.TCDN-WAF-Enabled = "true";
if (req.url ~ "^/path/without/waf/") {
set req.http.TCDN-WAF-Set-SecRuleEngine = "#Off";
}
}
}
HTTP es el protocolo sin cifrado: cualquier dato que viaja entre el navegador del usuario y el servidor puede ser interceptado. HTTPS cifra esa comunicación y es hoy el estándar mínimo de seguridad en cualquier web.
Si tu sitio acepta peticiones HTTP, lo correcto es redirigir automáticamente a los usuarios a la versión segura HTTPS en lugar de servirles contenido sin cifrar. El CDN puede encargarse de esta redirección antes de que la petición llegue siquiera a tu servidor.
El código detecta si la petición llega por HTTP comprobando la cabecera X-Forwarded-Proto y, en ese caso, ejecuta la redirección a HTTPS de forma transparente para el usuario.
sub vcl_recv {
if (req.http.X-Forwarded-Proto != "https" && req.http.host == "web.test-transparent.airenetowks.es") {
call redirect_https;
}
}
Cuando reestructuras tu web, cambias la URL de una página o migras contenido a una nueva ubicación, es fundamental redirigir las URLs antiguas. De lo contrario los usuarios que tengan guardada la URL antigua, o los buscadores que la tengan indexada, llegarán a una página de error.
Una redirección 301 le indica tanto al navegador como a los buscadores que el contenido se ha movido de forma permanente a la nueva URL. El CDN puede gestionar esta redirección directamente, sin que la petición llegue a tu servidor.
El código siguiente comprueba si la URL solicitada coincide con la ruta antigua y, en ese caso, devuelve la redirección al cliente con la nueva dirección.
sub vcl_recv {
if (req.url == "/old-path") {
set req.http.tcdn-location = "301, https://web.test-transparent.airenetowks.es/new-path";
call redirect_request;
}
}
Si detectas que una IP concreta está realizando actividad maliciosa, abusando de tus recursos o accediendo a zonas que no debería, puedes bloquearla directamente en el CDN. Esto significa que las peticiones de esa IP serán rechazadas antes de llegar a tu servidor, sin consumir recursos de tu infraestructura.
El bloqueo devuelve un error 403 Forbidden, que le indica al cliente que el acceso está denegado. Puedes ampliar este ejemplo con listas de IPs o rangos de red si necesitas bloquear más de una dirección.
El código comprueba la IP de origen de cada petición y, si coincide con la bloqueada, ejecuta el rechazo inmediato.
sub vcl_recv {
if (client.ip == "192.168.1.1") {
call deny_request;
}
}
Las APIs públicas son especialmente vulnerables al abuso: un bot o un cliente mal programado puede lanzar miles de peticiones en segundos, saturando tu servidor y dejando sin servicio al resto de usuarios.
El rate limiting o limitación de tasa resuelve esto estableciendo un máximo de peticiones permitidas por cliente en un periodo de tiempo. Si un cliente supera ese límite, el CDN le bloquea temporalmente sin que las peticiones extras lleguen a tu servidor.
En el código siguiente se aplica un límite de 100 peticiones por minuto por IP para todas las rutas bajo /api/. Si se supera ese umbral, el cliente queda bloqueado durante 5 minutos.
sub vcl_recv {
if (req.url ~ "^/api/") {
set req.http.tcdn-ratelimit = "100/1m, 5m, True-Client-IP";
call rate_limit;
}
}
Durante un ataque activo —como un DDoS o un intento masivo de fuerza bruta— cada segundo cuenta. Necesitas una respuesta inmediata que proteja tu servidor sin tener que configurar reglas complejas en ese momento.
El modo under attack activa una protección reforzada para la ruta que indiques: el CDN añade desafíos de verificación adicionales a todas las peticiones entrantes, filtrando el tráfico automatizado malicioso antes de que llegue a tu servidor. Es especialmente útil para proteger páginas de login, formularios de pago o cualquier endpoint crítico bajo presión.
El código siguiente activa este modo para una ruta concreta. Puedes aplicarlo también a todo el sitio si la situación lo requiere.
sub vcl_recv {
if (req.url == "/critical-page") {
call under_attack;
}
}
En ocasiones el tráfico malicioso o automatizado proviene de forma concentrada desde una región geográfica concreta. En lugar de bloquear ese tráfico de forma tajante —lo que también afectaría a usuarios legítimos de esa zona— puedes añadir una verificación CAPTCHA que solo los humanos sean capaces de superar.
El CDN conoce el país de origen de cada petición a través de su información de geolocalización. Con esa información puedes aplicar el CAPTCHA de forma selectiva, dejando pasar sin fricción al resto de usuarios del mundo.
El código siguiente muestra el CAPTCHA únicamente a las peticiones que provienen del país indicado mediante su código ISO de dos letras.
sub vcl_recv {
if (req.http.geo_country_code == "CN") {
call show_captcha;
}
}
Los bots y crawlers maliciosos suelen identificarse a través de su User-Agent, la cadena de texto que cualquier cliente HTTP envía para presentarse al servidor. Aunque un bot sofisticado puede falsificarla, muchos utilizan identificadores genéricos o conocidos que delatan su naturaleza automatizada.
El desafío JavaScript es una verificación invisible para los usuarios reales: el navegador lo resuelve automáticamente en milisegundos. Sin embargo, los bots simples que no ejecutan JavaScript no pueden superarlo y son rechazados antes de consumir recursos de tu servidor.
El código siguiente detecta patrones comunes en el User-Agent y lanza el desafío a quienes los presenten.
sub vcl_recv {
if (req.http.User-Agent ~ "(bot|spider|crawler)") {
call show_jschallenge;
}
}
Transparent Edge incluye un motor de análisis de comportamiento llamado BOTM que evalúa cada petición y le asigna una puntuación de riesgo de 0 a 100. Esta puntuación tiene en cuenta decenas de señales: patrones de navegación, velocidad de las peticiones, características del cliente, reputación de la IP y muchas más.
Con esta puntuación puedes tomar decisiones automáticas: dejar pasar el tráfico de bajo riesgo, aplicar desafíos al tráfico dudoso y bloquear directamente el tráfico de alto riesgo, todo sin intervención manual.
El código siguiente ejecuta el análisis BOTM y bloquea automáticamente las peticiones cuya puntuación de riesgo supere 70 o que hayan sido marcadas como abuso confirmado.
sub vcl_recv {
call botm_assessment;
if (var.get_int("botm-risk") > 70 || var.get("botm-is-abuse") == "1") {
call deny_request;
}
}
No todos los dominios requieren el mismo nivel de protección frente a bots. Un sitio de contenido público puede tolerar crawlers legítimos, mientras que una tienda online o un portal de clientes querrá ser más restrictivo. Por eso puedes configurar la acción de mitigación de forma independiente para cada dominio.
Las tres acciones disponibles son: bypass (deja pasar el tráfico sin mitigación), block (bloquea directamente el tráfico identificado como bot) y challenge (lanza un desafío de verificación antes de permitir el acceso).
El código siguiente muestra cómo asignar una acción específica a un dominio concreto. Cambia el valor de TCDN-BM-Action según el nivel de protección que necesites.
sub vcl_recv {
if (req.http.host == "www.mydomain.com") {
# bypass, block, or challenge
set req.http.TCDN-BM-Action = "bypass";
}
}
El login es una de las rutas más atacadas de cualquier aplicación web: ataques de fuerza bruta, credential stuffing y relleno de credenciales son amenazas constantes. Melange es una capa de verificación adicional que Transparent Edge puede aplicar sobre rutas sensibles para detectar y frenar este tipo de ataques.
A diferencia de un CAPTCHA visible, el chequeo Melange trabaja de forma transparente analizando el comportamiento de la petición. Solo cuando detecta actividad sospechosa interviene activamente.
El código siguiente aplica el chequeo Melange a todas las peticiones que lleguen a rutas que comiencen por /login.
sub vcl_recv {
if (req.url ~ "^/login") {
call melange_check;
}
}
WebP es un formato de imagen moderno desarrollado por Google que consigue el mismo nivel de calidad visual que JPEG o PNG pero con un tamaño de archivo significativamente menor, normalmente entre un 25% y un 35% más ligero. Imágenes más ligeras significan páginas que cargan más rápido y menos ancho de banda consumido.
El CDN puede convertir tus imágenes a WebP de forma automática y transparente: detecta si el navegador del usuario soporta WebP (la gran mayoría de los actuales sí lo hacen) y, en ese caso, sirve la versión convertida. Si el navegador no lo soporta, sirve el formato original. Todo sin que tengas que cambiar nada en tu servidor ni en el código de tu web.
El código siguiente activa esta conversión automática para tu dominio con una sola línea.
sub vcl_recv {
if (req.http.host == "www.my-domain.com") {
set req.http.TCDN-i3-transform = "auto_webp";
}
}
Servir imágenes más grandes de lo necesario es uno de los errores más habituales que penalizan el rendimiento de una web. Si tu servidor almacena imágenes en alta resolución pero en muchas partes de la web solo necesitas miniaturas o versiones reducidas, estás transfiriendo datos innecesarios en cada visita.
Con el motor de transformación de imágenes i3 de Transparent Edge puedes redimensionar las imágenes al vuelo, sin modificar los originales en tu servidor. El CDN intercepta la petición, aplica el redimensionado y sirve la imagen con las nuevas dimensiones, almacenando además el resultado en caché para peticiones posteriores.
El código siguiente aplica un redimensionado a 300×300 píxeles a todas las imágenes de una ruta concreta.
sub vcl_recv {
if (req.http.host == "www.mi-dominio.es") {
if (req.url ~ "^/estaticos/imagenes/") {
set req.http.TCDN-i3-transform = "resize:300x300";
}
}
}
El ojo humano no distingue la diferencia entre un JPEG al 100% de calidad y uno al 75-80%. Sin embargo, la diferencia en tamaño de archivo puede ser enorme: una imagen guardada al 75% puede pesar hasta la mitad que la misma al 100%, cargando mucho más rápido sin que el usuario note ningún cambio visual.
En lugar de recomprimir manualmente todas las imágenes de tu servidor, el CDN puede aplicar este ajuste de calidad de forma automática en tiempo real. Las imágenes originales en tu servidor no se modifican; el CDN sirve la versión recomprimida y la almacena en caché.
El código siguiente aplica una calidad del 75% solo a los archivos JPEG dentro de la ruta indicada, comprobando la extensión del archivo antes de actuar.
sub vcl_recv {
if (req.http.host == "www.mi-dominio.es") {
if (req.url ~ "^/estaticos/imagenes/") {
if (urlplus.get_extension() ~ "(?i)(jpe?g)") {
set req.http.TCDN-i3-transform = "quality:75%";
}
}
}
}
La caché es el mecanismo por el que el CDN guarda una copia de los recursos de tu web para servirlos directamente sin tener que pedírselos a tu servidor en cada visita. Esto reduce drásticamente los tiempos de carga y el tráfico hacia tu servidor.
Los recursos estáticos como imágenes o archivos CSS prácticamente no cambian, por lo que cachearlos durante periodos largos tiene todo el sentido. Sin embargo, si tu servidor no envía las cabeceras de caché correctas, el CDN no sabe cuánto tiempo puede guardarlos.
Este fragmento resuelve ese problema desde el propio CDN: cuando el backend no especifica una política de caché, el CDN aplica la suya propia. En este caso, 24 horas (86400 segundos) tanto en el CDN como en el navegador del usuario.
sub vcl_backend_response {
if (bereq.http.host == "www.example.com") {
if (urlplus.get_extension() ~ "(?i)(jpg|jpeg|png|gif|css)") {
set beresp.http.Cache-Control = "max-age=86400";
set beresp.ttl = 86400s;
}
}
}
Existen dos niveles de caché que puedes aprovechar: la del CDN (que guarda el recurso cerca del usuario, en los servidores de Transparent Edge) y la del navegador (que guarda el recurso directamente en el dispositivo del usuario). Cuando ambas están activas, la segunda visita a tu web es prácticamente instantánea.
La cabecera Cache-Control con max-age controla ambos niveles a la vez: le dice tanto al CDN como al navegador durante cuánto tiempo pueden usar su copia antes de volver a pedir el recurso al origen.
El código siguiente establece 24 horas de caché en los dos niveles para los tipos de archivo más habituales.
sub vcl_backend_response {
if (bereq.http.host == "www.example.com") {
if (urlplus.get_extension() ~ "(?i)(jpg|jpeg|png|gif|css)") {
set beresp.http.Cache-Control = "max-age=86400";
set beresp.ttl = 86400s;
}
}
}
A veces quieres aprovechar la caché del CDN para reducir la carga de tu servidor, pero no quieres que el navegador del usuario guarde una copia local. Esto es útil cuando necesitas poder invalidar el recurso desde el CDN en cualquier momento y asegurarte de que todos los usuarios reciben la versión actualizada inmediatamente, sin esperar a que expire la caché de sus navegadores.
La clave está en separar las instrucciones para cada nivel: max-age=0 le dice al navegador que no guarde nada, mientras que s-maxage=86400 le indica al CDN (y a cualquier caché intermedia) que puede guardar el recurso durante 24 horas.
El código siguiente aplica exactamente esta combinación para los recursos estáticos del dominio configurado.
sub vcl_backend_response {
if (bereq.http.host == "www.example.com") {
if (urlplus.get_extension() ~ "(?i)(jpg|jpeg|png|gif|css)") {
set beresp.http.Cache-Control = "max-age=0, s-maxage=86400";
set beresp.ttl = 86400s;
}
}
}
Una política de caché realista no es uniforme: los recursos estáticos pueden cachearse durante horas o días, las páginas HTML cambian con más frecuencia y merecen un TTL más corto, y ciertas rutas —como las de área privada de usuario o los endpoints de API dinámica— no deben cachearse nunca.
Este ejemplo implementa una política completa y diferenciada en una sola subrutina. Además, elimina las cookies de los recursos estáticos, lo que es importante porque el CDN no cachea por defecto recursos que lleven cookies, y los estáticos no las necesitan.
El código gestiona tres casos: estáticos con TTL largo, HTML con TTL corto, y una ruta concreta marcada como sin caché.
sub vcl_backend_response {
if (beresp.status == 200) {
if (urlplus.get_extension() ~ "(?i)(css|eot|gif|ico|jpe?g|js|png|svg|ttf|woff)" ||
beresp.http.Content-Type ~ "image/" ||
beresp.http.Content-Type ~ "text/(css|plain)" ||
beresp.http.Content-Type ~ "(application|text)/(x-)?javascript" ||
beresp.http.Content-Type ~ "font/") {
if (!beresp.http.Cache-Control) {
set beresp.http.Cache-Control = "max-age=3600, s-maxage=86400";
set beresp.ttl = 86400s;
}
cookieplus.setcookie_delete_regex(".*");
cookieplus.setcookie_write();
}
if (urlplus.get_extension() ~ "(?i)(html?)" ||
beresp.http.Content-Type ~ "text/html") {
set beresp.http.Cache-Control = "max-age=300, s-maxage=3600";
set beresp.ttl = 300s;
}
}
if (bereq.url ~ "^/path/no-cache") {
set beresp.http.Cache-Control = "no-cache";
set beresp.ttl = 0s;
set beresp.uncacheable = true;
}
}
Durante el desarrollo, las pruebas o el diagnóstico de problemas, a veces necesitas obtener una respuesta fresca directamente desde el servidor de origen, sin que el CDN devuelva su copia en caché. Hacerlo invalidando la caché entera sería demasiado agresivo; necesitas una forma de omitirla solo para esa petición concreta.
La solución es usar una cabecera personalizada como señal. Quien incluya X-No-Cache: true en su petición obtendrá siempre la respuesta del origen. El resto del tráfico seguirá usando la caché con normalidad.
Ten en cuenta que esta cabecera debe protegerse o usarse solo en entornos de confianza, ya que cualquiera que la conozca puede aumentar la carga de tu servidor con peticiones sin caché.
sub vcl_fetch {
if (req.http.X-No-Cache == "true") {
call bypass_cache;
}
}
Si tu web muestra contenido diferente según el país del usuario —precios en moneda local, idioma adaptado, productos disponibles por región— el CDN necesita saberlo. De lo contrario, podría servir la versión cacheada para España a un usuario de México, o viceversa.
La solución es indicarle al CDN que el contenido varía según el país, de forma que guarde y sirva una copia diferente de cada URL para cada región geográfica. Esto se hace con la cabecera X-Vary-TCDN, que extiende el mecanismo estándar de variación de caché.
El código siguiente añade esta instrucción en la fase de entrega, cuando ya conocemos el tipo de contenido de la respuesta.
sub vcl_deliver {
if (resp.http.Content-Type ~ "text/html") {
set resp.http.X-Vary-TCDN = "geo_country_code";
}
}
Si tu web sirve una versión diferente para móvil y para escritorio —ya sea un diseño completamente distinto, imágenes adaptadas o incluso una respuesta HTML diferente— el CDN también necesita cachear ambas versiones por separado. De lo contrario, podría servir la versión de escritorio a usuarios de móvil o viceversa.
Este ejemplo extiende la variación de caché añadiendo el tipo de dispositivo como criterio adicional. Si ya tienes configurada la variación por país, este código la complementa concatenando el nuevo criterio a la cabecera existente.
El código comprueba el User-Agent de la petición y, si corresponde a un dispositivo móvil, añade user_agent_mobile como dimensión extra de variación en la caché.
sub vcl_deliver {
if (req.http.User-Agent ~ "Mobile") {
set resp.http.X-Vary-TCDN = resp.http.X-Vary-TCDN + ", user_agent_mobile";
}
}