security
264 TopicsThe Blind Spot in Cloud WAF Architectures: Shared IPs and the Origin Bypass Problem
Cloud WAFs are a widely adopted security control, but they carry a structural trust assumption that most operators never examine: whitelisting a vendor's IP ranges grants access not just to your WAF instance, but to every tenant on that platform. This article examines how that assumption can be exploited, why IP-based ownership validation cannot solve it, and what mitigations, including Zero Trust-aligned architectures like F5 Distributed Cloud Customer Edge, actually close the gap. When you deploy a Cloud WAF, whether it's F5, Imperva, Cloudflare or any similar service, you're trusting it to stand between the internet and your origin server. You configure your DNS to point to the WAF, tighten your firewall to only accept traffic from the WAF's published IP ranges, and consider yourself protected. The traffic gets inspected, filtered, and forwarded. Job done. Except there's a subtle but serious flaw baked into this architecture that is widely overlooked, and it stems from a property that is fundamental to how Cloud WAFs work: shared egress IPs. How Cloud WAF Proxying Actually Works When a Cloud WAF forwards traffic to your origin, it does so from a pool of IP addresses that the vendor owns and publishes. These ranges are shared across all customers of that vendor. In fact, every major Cloud WAF provider explicitly instructs you to whitelist their entire published IP range as part of the standard onboarding process. This is not a misconfiguration on your part, it is the vendor-recommended setup. Your firewall rule, "allow traffic from this vendor's IP ranges", doesn't mean "allow traffic from my WAF instance." It means "allow traffic from anyone who also happens to be a customer of that vendor." That distinction matters enormously. An attacker who is also a customer of the same WAF vendor can point their own WAF configuration at your origin IP. When they do, their traffic, potentially malicious and definitely uninspected by your WAF policy, arrives at your server from the very IP ranges you've whitelisted. Your firewall lets it through. Your WAF policy, which applies only to traffic routed through your tenant configuration, never sees it. Your server is now reachable by anyone, even with a $20/month account for some vendors, on the same WAF platform. Why This Matters More Than It Seems This isn't a theoretical edge case. The attack surface is: Broad: Every Cloud WAF customer on a given platform could potentially reach any other customer's origin. Silent: The origin server receives the traffic without any obvious indication it bypassed the WAF policy. Persistent: It doesn't require exploiting a vulnerability, it exploits an intentional architectural property. The classic goal of origin hardening, hiding your real IP and only allowing WAF traffic, is partially undermined the moment you realize that "WAF traffic" and "your WAF traffic" are not the same thing. The Missing Validation: Outbound Origin Ownership What makes this problem interesting is the asymmetry in how Cloud WAFs handle trust. On the inbound side, WAF vendors have robust validation. Before a vendor will proxy traffic for your domain, you must prove you own it, typically via a DNS TXT record or HTTP challenge, the same mechanisms used in TLS certificate issuance. No proof, no proxying. On the outbound side, the connection from the WAF to your origin, there is essentially no equivalent validation. Any tenant can point their configuration at any IP address. The WAF will dutifully forward traffic to it. The origin has no way, at the network layer, to distinguish "traffic from my WAF tenant" from "traffic from another tenant who decided to target my server." An obvious question is: why not apply the same ownership verification to origin IPs that vendors already apply to domains? The answer is that not all IP addresses can map cleanly to ownership the way domain names do. In practice, IPs are frequently shared, multiple services behind a load balancer or shared hosting infrastructure, and in cloud environments they rotate constantly as instances scale up and down or elastic IPs are reassigned. Unlike a domain name, an IP address is not a stable, exclusive identifier of a single operator. That said, the picture is not entirely bleak for enterprises. Organizations that own their own IPs do have a stable and exclusive relationship with their IPs. In these cases, ownership validation is technically feasible: a vendor could verify control via a well-known URL served at that IP, or via a PTR record in the reverse DNS zone, both of which require actual control of the address space. This would mirror the HTTP-01 and DNS-01 challenge models already used in certificate issuance. For the broader market, however, where IPs are leased from cloud providers and rotate frequently, this approach does not hold. The asymmetry therefore reflects a genuine structural limitation of IP-based identity for the general case, even if partial solutions exist for enterprises with dedicated address space. Mitigations Available Today Since origin IP ownership validation isn't yet a standard feature across Cloud WAF platforms, the burden falls on origin operators. There are several practical mitigations, ranging from straightforward to architecturally robust. Shared Secret Header Authentication The most common approach is having the WAF inject a secret header on all forwarded requests (for example, X-Origin-Token), which your origin validates on every request. Traffic missing the header, or presenting the wrong value, is rejected. Most Cloud WAF vendors support this through custom header injection rules. The weakness is operational: the secret must be kept out of logs, rotated periodically, and is only as strong as your header validation implementation. Mutual TLS Between WAF and Origin Several vendors support presenting a client certificate when connecting to your origin, allowing your server to cryptographically verify that the connection came from your WAF vendor's infrastructure, not just the right IP range. This is stronger than a shared secret because it's not a value that can be accidentally leaked in a log file. Private Tunneling (Eliminating the Public IP Entirely) The most architecturally sound solution is to remove your origin from the public internet entirely. An outbound-only encrypted tunnel from your origin to the WAF's edge means your server never needs a publicly routable IP. There is no firewall rule to configure, no IP range to whitelist, and the shared-IP problem becomes entirely irrelevant because there is no exposed surface to exploit. This approach is increasingly the recommended baseline for new deployments, not just a hardening option. Host Header Validation at the Origin Your origin should always reject requests where the Host header doesn't match your expected domain. However, this provides no real protection against the shared-IP bypass, as an attacker can trivially rewrite the Host header in their own WAF configuration to match your domain before forwarding traffic to your origin. It remains good hygiene, but should not be counted as a mitigation for this specific threat. A Note on F5 Distributed Cloud Customer Edge F5 Distributed Cloud takes a different architectural approach that sidesteps this problem structurally. Rather than relying on shared cloud-based egress IPs, F5 XC allows you to deploy a Customer Edge (CE) node(s), a dedicated piece of infrastructure that runs within your environment or network perimeter. Traffic flows from the F5 global network through an encrypted tunnel directly to your CE node, rather than from a shared IP pool to a publicly exposed origin. Because the CE node is yours, deployed in your environment and associated exclusively with your tenant, the concept of another tenant "reaching your origin from a shared IP" simply doesn't apply. The origin isn't exposed to a shared egress pool in the first place. This design is also a natural fit for Zero Trust architectures: the origin never implicitly trusts any network-level connection, and access is gated by tenant identity rather than IP address. It's an architectural answer to an architectural problem, rather than a mitigation layered on top of a fundamentally shared infrastructure model. Conclusion The Cloud WAF shared-IP bypass is a genuine blind spot that deserves more attention than it typically receives. The root cause is an asymmetry in how trust is established: vendors carefully validate that you own your domain before proxying it, but apply no equivalent validation to origin IP ownership. Any tenant on the same platform can route traffic to your origin. The good news is that practical mitigations exist, mTLS, secret headers, and private tunneling cover most production scenarios. The better news is that some architectures, like F5 XC with Customer Edge, eliminate the exposure at the design level rather than patching around it. If your current posture is "I've whitelisted the WAF vendor's IP ranges," it's worth asking: which WAF customers, exactly, have you let in? This article was written by the author and formatted with the assistance of AI.30Views0likes0CommentsComplete MFA solution with GA stored in Active Directory
Problem this snippet solves: All modern business applications require Multi-Factor Authentication (MFA) to be used for remote access by employees. There are many vendors on market selling enterprise MFA solutions that may be utilised with F5 BIG-IP Access Policy Manager (APM). Those solutions are complex and allow customers to create flexible policies which allow them to decide when and whom will be authorised to access protected applications. But what about those customers which have no needs for using complex enterprise solutions or does not have adequate budget for such spendings? How to use this snippet: For those customers I would like to present my One-Time Password (OTP) application which requires BIG-IP LTM/APM/iRulesLX. Shared secret value is stored in Active Directory and QR code is generated in user's browser. All you need after implementing this application on your BIG-IP is. to ask your users to get any OTP-compatible mobile application, like Google Authenticator or Microsoft Authenticator Please see https://github.com/akhmarov/f5_otp/ for instructions UPDATE 1: New version now support APM 15.1+ Modern Customization UPDATE 2: Added trusted device support UPDATE 3: Added multi-tenancy support Tested this on version: 15.11.7KViews1like9CommentsDNS: El protocolo que nadie ve...hasta que se convierte en el problema más grande de la arquitectura
En el día a día de operación, el DNS rara vez está en el centro de la conversación. No suele ser el protagonista de los roadmaps, ni el primer punto que se revisa en un diseño nuevo. Muchas veces se asume que "ya está ahí", funcionando, resolviendo nombres sin mayor fricción. Y eso es precisamente lo peligroso. Después de años trabajando con arquitecturas empresariales y de Service Providers, hay una constante difícil de ignorar: el DNS es uno de los componentes más críticos de la infraestructura moderna y, al mismo tiempo, uno de los más subestimados. Cuando todo funciona, nadie pregunta por él. Cuando algo falla, todo lo demás deja de importar. He visto aplicaciones "arriba", enlaces estables, firewalls en verde... pero usuarios incapaces de acceder a un servicio. El problema no estaba en la aplicación ni en la red, sino en ese primer paso que todos damos por sentado: resolver un nombre. DNS en la vida real: cuando la teoría se encuentra con la operación En el papel, el DNS parece simple, pero en producción, no lo es. En arquitecturas reales, el DNS participa activamente en decisiones críticas como: A qué sitio o región se dirige un usuario Qué backend recibe una solicitud Cómo se distribuye la carga entre múltiples data centers Qué tan rápido se recupera un servicio ante una degradación o caída En Service Providers y grandes organizaciones, esto se vuelve evidente durante eventos inesperados. Un sismo, una noticia de alto impacto, un evento deportivo global, una actualización urgente de una aplicación, una app que se vuelve tendencia, un anuncio gubernamental o una contingencia sanitaria pueden disparar el tráfico digital en cuestión de minutos. En estos escenarios, el primer crecimiento significativo no ocurre en HTTP ni en TLS, sino en las consultas DNS. Millones de usuarios abren aplicaciones, refrescan portales y generan resoluciones simultáneas hacia los mismos dominios. Si el DNS no está preparado para absorber ese pico: La aplicación nunca recibe tráfico Los balanceadores no alcanzan a participar La experiencia del usuario se degrada de inmediato Aquí es donde soluciones como F5 BIG-IP DNS dejan de ser un "servicio de nombres" y se convierten en un componente activo de control de tráfico, capaz de tomar decisiones basadas en: Estado real de los servicios Salud de los backends Políticas de disponibilidad y continuidad El boom de la inteligencia artificial y su impacto directo en DNS La llegada masiva de la Inteligencia Artificial no solo ha cambiado cómo se consumen aplicaciones; ha cambiado radicalmente el patrón del tráfico. Las arquitecturas modernas de IA introducen: Más microservicios desacoplados Más APIs internas y externas Endpoints efímeros que aparecen y desaparecen Resoluciones dinámicas y frecuentes Cada llamada a un modelo, cada inferencia distribuida y cada backend que escala automáticamente comienza con una consulta DNS. Pero el impacto va mucho más allá de la teoría. Los datos de 2025 lo confirman de forma contundente: Según Humansecurity, el tráfico generado por sistemas de inteligencia artificial casi se triplicó en un solo año, con un crecimiento mensual del 187% entre enero y diciembre. Y dentro de ese universo, el segmento que más creció fue el de agentes autónomos de IA — bots que ya no solo leen la web, sino que interactúan con ella: navegan, consultan APIs, completan transacciones. Ese tipo de tráfico creció más de un 7,800% interanual. ¿Qué significa esto para el DNS? Cada vez que un agente de IA resuelve una consulta, busca un endpoint o escala un servicio, hay una resolución DNS detrás. Y no estamos hablando de patrones predecibles. El tráfico de IA se comporta de forma diferente al tráfico humano: es más agresivo en ráfagas, menos predecible en horarios, y crece a un ritmo ocho veces mayor que el tráfico generado por personas. A esto se suma que los crawlers de IA — los sistemas que rastrean contenido para entrenamiento, búsqueda y acciones en tiempo real — se han convertido en una de las fuentes más grandes de tráfico automatizado en internet. Durante 2025, solo el crawler de Google generó aproximadamente el 4.5% de todas las solicitudes HTML hacia sitios protegidos por las principales plataformas de seguridad. Y el crawling por "acción de usuario" (cuando un usuario le pide algo a un chatbot y este sale a buscar información en la web) creció más de 15 veces en el mismo periodo. Desde una perspectiva técnica, esto tiene implicaciones claras: Crecimiento sostenido y acelerado del volumen de consultas DNS Mayor sensibilidad a latencia y jitter en la resolución Mayor impacto de fallas parciales o intermitentes Patrones de tráfico menos predecibles y más difíciles de planificar El DNS deja de ser infraestructura "estática" y se convierte en un componente dinámico del plano de datos, íntimamente ligado al desempeño de los modelos y servicios de IA. Y quien no esté dimensionando su infraestructura DNS con esta variable en mente, va a sentir el impacto más temprano que tarde. El DNS como punto crítico en eventos globales A lo largo de los años, múltiples eventos han demostrado el impacto del DNS a escala global. Desde interrupciones masivas de servicios digitales hasta ataques de amplificación, el patrón es consistente: cuando el DNS se ve afectado, el impacto se multiplica. Y no hay que ir lejos para encontrar ejemplos. Solo en octubre de 2025, dos incidentes dejaron muy claro lo que pasa cuando el DNS falla en entornos de producción reales. En el primero, un error en el sistema automatizado de gestión DNS de una de las principales plataformas de nube pública dejó inaccesibles servicios críticos en la región más grande de su infraestructura. Los servidores estaban operativos, las bases de datos intactas... pero el DNS los hacía invisibles. La falla se propagó en cascada a más de cien servicios, afectó a miles de empresas en más de 60 países y generó millones de reportes de caída en cuestión de horas. Plataformas de mensajería, gaming, streaming, servicios financieros y hasta aplicaciones gubernamentales quedaron fuera de línea. No fue un ataque. Fue un error de automatización en DNS. Días después, un proveedor de telecomunicaciones europeo con millones de clientes de red fija experimentó una falla de resolución DNS que dejó sin acceso a internet a gran parte de su base de usuarios durante varias horas. El tráfico observado cayó más del 75%. Y la causa raíz fue, nuevamente, un problema de resolución DNS — no un corte de fibra, no un ataque DDoS, no una caída de energía. F5 Labs ha documentado ampliamente cómo: Ataques volumétricos utilizan DNS como vector principal La amplificación DNS sigue siendo una técnica efectiva Eventos globales generan patrones de tráfico anómalos que exponen debilidades de diseño Estos escenarios no distinguen industria ni tamaño. Afectan por igual a proveedores de servicios, plataformas digitales, infraestructura crítica y aplicaciones empresariales. La diferencia no está en si ocurren, sino en qué tan preparada está la arquitectura para absorberlos sin colapsar. Primero la observabilidad: entender antes de reaccionar Durante mucho tiempo, el DNS fue una caja negra. Funcionaba... o no. Hoy, la conversación cambia por completo cuando incorporamos observabilidad real a la ecuación. F5 Insight, componente clave dentro de la plataforma F5 ADSP, permite: Analizar patrones reales de consultas Identificar picos atípicos y comportamientos anómalos Correlacionar eventos externos con tráfico DNS Entender el porqué detrás del comportamiento del sistema Pero F5 Insight va más allá de dashboards y métricas. Incorpora inteligencia artificial para ofrecer guía proactiva, detección de anomalías y algo que cambia la forma de operar: la capacidad de interactuar con tus datos operacionales en lenguaje natural, usando integración con LLMs y el Model Context Protocol (MCP). En la práctica, esto significa pasar de revisar dashboards buscando qué pasó, a recibir narrativas operacionales que te dicen qué está pasando, por qué, y qué deberías priorizar. Para entornos con alta densidad de consultas DNS, donde los patrones cambian en minutos y los picos pueden ser impredecibles,especialmente con el crecimiento del tráfico de IA, ese salto de reactivo a proactivo no es un lujo, es una necesidad operativa. En escenarios de alto QPS, el problema no siempre es la capacidad, sino cómo se comporta el tráfico. Ver el DNS como datos, no solo como servicio, marca una diferencia enorme en operación y planeación.Plataforma y arquitectura: cuando el DNS ya no es "básico" Plataforma y arquitectura: cuando el DNS ya no es "básico" Cuando el DNS se vuelve crítico, la plataforma importa. Arquitecturas basadas en VELOS permiten separar capacidad, resiliencia y crecimiento del ciclo de vida de la aplicación, soportando cargas DNS masivas con aislamiento, alta disponibilidad y escalamiento ordenado. Por su parte, rSeries ofrece un modelo más compacto y eficiente, ideal para despliegues donde el rendimiento por unidad, la latencia y la eficiencia operativa son clave. Y cuando la aplicación ya no vive en un solo data center, F5 Distributed Cloud Services extiende las capacidades del DNS a arquitecturas híbridas y multicloud, manteniendo: Políticas consistentes Visibilidad unificada Control desde el edge hasta el backend El punto no es dónde corre el DNS, sino que acompañe a la aplicación sin perder control, resiliencia ni observabilidad. Seguridad integrada desde el primer paquete El DNS también es una superficie de ataque. Lo hemos comprobado una y otra vez durante eventos de seguridad globales. Y el panorama no se está simplificando: durante 2025, se identificaron más de 100 millones de dominios nuevos, de los cuales una cuarta parte fue clasificada como maliciosos o sospechosos. Los atacantes están registrando volúmenes sin precedentes de dominios, usando automatización para montar campañas masivas que evaden defensas tradicionales. Ignorar al DNS desde el punto de vista de seguridad es dejar una puerta abierta. Integrar protección dentro de la misma plataforma de entrega permite: Mitigar ataques sin introducir latencia adicional Aplicar políticas de forma consistente Mantener visibilidad unificada del tráfico Seguridad, rendimiento y disponibilidad no son capas separadas; son partes del mismo flujo. En ocasiones olvidamos Que el DNS no suele fallar de forma dramática. Falla de forma silenciosa... y por eso es tan peligroso. Invertir en su diseño, observabilidad y seguridad no es sobreingeniería. Es entender que todo empieza ahí. En un mundo donde la IA está triplicando el volumen de tráfico automatizado año con año, donde los agentes autónomos generan resoluciones DNS a un ritmo que no existía hace 18 meses, y donde un solo error de automatización en DNS puede dejar fuera a miles de empresas en más de 60 países... el DNS vuelve a ocupar el lugar que siempre tuvo en la arquitectura, aunque muchos lo hayan olvidado. La pregunta no es si el DNS es crítico. La pregunta es si tu arquitectura está lista para tratarlo como tal.108Views1like0CommentsUpdate an ASM Policy Template via REST-API - the reverse engineering way
I always want to automate as many tasks as possible. I have already a pipeline to import ASM policy templates. Today I had the demand to update this base policies. Simply overwriting the template with the import tasks does not work. I got the error message "The policy template ax-f5-waf-jump-start-template already exists.". Ok, I need an overwrite tasks. Searching around does not provide me a solution, not even a solution that does not work. Simply nothing, my google-foo have deserted me. Quick chat with an AI, gives me a solution that was hallucinated. The AI answer would be funny if it weren't so sad. I had no hope that AI could solve this problem for me and it was confirmed, again. I was configuring Linux systems before the internet was widely available. Let's dig us in the internals of the F5 REST API implementation and solve the problem on my own. I took a valid payload and removed a required parameter, "name" in this case. The error response changes, this is always a good signal in this stage of experimenting. The error response was "Failed Required Fields: Must have at least 1 of (title, name, policyTemplate)". There is also a valid field named "policyTemplate". My first thought: This could be a reference for an existing template to update. I added the "policyTemplate" parameter and assigned it an existing template id. The error message has changed again. It now throws "Can't use string (\"ox91NUGR6mFXBDG4FnQSpQ\") as a HASH ref while \"strict refs\" in use at /usr/local/share/perl5/F5/ASMConfig/Entity/Base.pm line 888.". An perl error that is readable and the perl file is in plain text available. Looking at the file at line 888: The Perl code looks for an "id" field as property of the "policyTemplate" parameter. Changing the payload again and added the id property. And wow that was easy, it works and the template was updated. Final the payload for people who do not want to do reverse engineering. Update POST following payload to /mgmt/tm/asm/tasks/import-policy-template to update an ASM policy template: { "filename": "<username>~<filename>", "policyTemplate": { "id": "ox91NUGR6mFXBDG4FnQSpQ" } } Create POST following payload /mgmt/tm/asm/tasks/import-policy-template to create an ASM policy template: { "name": "<name>", "filename": "<username>~<filename>" } Hint: You must upload the template before to /var/config/rest/downloads/<username>~<filename>". Conclusion Documentation is sometimes overrated if you can read Perl. Missed I the API documentation for this endpoint and it was just a exercise for me?365Views2likes8CommentsContext Cloak: Hiding PII from LLMs with F5 BIG-IP
The Story As I dove deeper into the world of AI -- MCP servers, LLM orchestration, tool-calling models, agentic workflows -- one question kept nagging me: how do you use the power of LLMs to process sensitive data without actually exposing that data to the model? Banks, healthcare providers, government agencies -- they all want to leverage AI for report generation, customer analysis, and workflow automation. But the data they need to process is full of PII: Social Security Numbers, account numbers, names, phone numbers. Sending that to an LLM (whether cloud-hosted or self-hosted) creates a security and compliance risk that most organizations can't accept. I've spent years working with F5 technology, and when I learned that BIG-IP TMOS v21 added native support for the MCP protocol, the lightbulb went on. BIG-IP already sits in the data path between clients and servers. It already inspects, transforms, and enforces policy on HTTP traffic. What if it could transparently cloak PII before it reaches the LLM, and de-cloak it on the way back? That's Context Cloak. The Problem An analyst asks an LLM: "Generate a financial report for John Doe, SSN 078-05-1120, account 4532-1189-0042." The LLM now has real PII. Whether it's logged, cached, fine-tuned on, or exfiltrated -- that data is exposed. Traditional approaches fall short: Approach What Happens The Issue Masking (****) LLM can't see the data Can't reason about what it can't see Tokenization (<<SSN:001>>) LLM sees placeholders Works with larger models (14B+); smaller models may hallucinate Do nothing LLM sees real PII Security and compliance violation The Solution: Value Substitution Context Cloak takes a different approach -- substitute real PII with realistic fake values: John Doe --> Maria Garcia 078-05-1120 --> 523-50-6675 4532-1189-0042 --> 7865-4412-3375 The LLM sees what looks like real data and reasons about it naturally. It generates a perfect financial report for "Maria Garcia." On the way back, BIG-IP swaps the fakes back to the real values. The user sees a report about John Doe. The LLM never knew John Doe existed. This is conceptually a substitution cipher -- every real value maps to a consistent fake within the session, and the mapping is reversed transparently. When I was thinking about this concept, my mind kept coming back to James Veitch's TED talk about messing with email scammers. Veitch tells the scammer they need to use a code for security: Lawyer --> Gummy Bear Bank --> Cream Egg Documents --> Jelly Beans Western Union --> A Giant Gummy Lizard The scammer actually uses the code. He writes back: "I am trying to raise the balance for the Gummy Bear so he can submit all the needed Fizzy Cola Bottle Jelly Beans to the Creme Egg... Send 1,500 pounds via a Giant Gummy Lizard." The real transaction details -- the amounts, the urgency, the process -- all stayed intact. Only the sensitive terms were swapped. The scammer didn't even question it. That idea stuck with me -- what if we could do the same thing to protect PII from LLMs? But rotate the candy -- so it's not a static code book, but a fresh set of substitutions every session. Watch the talk: https://www.ted.com/talks/james_veitch_this_is_what_happens_when_you_reply_to_spam_email?t=280 Why BIG-IP? F5 BIG-IP was the natural candidate: Already in the data path -- BIG-IP is a reverse proxy that organizations already deploy MCP protocol support -- TMOS v21 added native MCP awareness via iRules iRules -- Tcl-based traffic manipulation for real-time HTTP payload inspection and rewriting Subtables -- in-memory key-value storage perfect for session-scoped cloaking maps iAppLX -- deployable application packages with REST APIs and web UIs Trust boundary -- BIG-IP is already the enforcement point for SSL, WAF, and access control How Context Cloak Works An analyst asks a question in Open WebUI Open WebUI calls MCP tools through the BIG-IP MCP Virtual Server The MCP server queries Postgres and returns real customer data (name, SSN, accounts, transactions) BIG-IP's MCP iRule scans the structured JSON response, extracts PII from known field names, generates deterministic fakes, and stores bidirectional mappings in a session-keyed subtable. The response passes through unmodified so tool chaining works. Open WebUI receives real data and composes a prompt When the prompt goes to the LLM through the BIG-IP Inference VS, the iRule uses [string map] to swap every real PII value with its fake counterpart The LLM generates its response using fake data BIG-IP intercepts the response and swaps fakes back to reals. The analyst sees a report about John Doe with his real SSN and account numbers. Two Cloaking Modes Context Cloak supports two modes, configurable per PII field: Substitute Mode Replaces PII with realistic fake values. Names come from a deterministic pool, numbers are digit-shifted, emails are derived. The LLM reasons about the data naturally because it looks real. John Doe --> Maria Garcia (name pool) 078-05-1120 --> 523-50-6675 (digit shift +5) 4532-1189-0042 --> 7865-4412-3375 (digit shift +3) john@email.com --> maria.g@example.net (derived) Best for: fields the LLM needs to reason about naturally -- names in reports, account numbers in summaries. Tokenize Mode Replaces PII with structured placeholders: 078-05-1120 --> <<SSN:32.192.169.232:001>> John Doe --> <<name:32.192.169.232:001>> 4532-1189-0042 --> <<digit_shift:32.192.169.232:001>> A guidance prompt is automatically injected into the LLM request, instructing it to reproduce the tokens exactly as-is. Larger models (14B+ parameters) handle this reliably; smaller models (7B) may struggle. Best for: defense-in-depth with F5 AI Guardrails. The tokens are intentionally distinctive -- if one leaks through de-cloaking, a guardrails policy can catch it. Both modes can be mixed per-field in the same request. The iAppLX Package Context Cloak is packaged as an iAppLX extension -- a deployable application on BIG-IP with a REST API and web-based configuration UI. When deployed, it creates all required BIG-IP objects: data groups, iRules, HTTP profiles, SSL profiles, pools, monitors, and virtual servers. The PII Field Configuration is the core of Context Cloak. The admin selects which JSON fields in MCP responses contain PII and chooses the cloaking mode per field: Field Aliases Mode Type / Label full_name customer_name Substitute Name Pool ssn Tokenize SSN account_number Substitute Digit Shift phone Substitute Phone email Substitute Email The iRules are data-group-driven -- no PII field names are hardcoded. Change the data group via the GUI, and the cloaking behavior changes instantly. This means Context Cloak works with any MCP server, not just the financial demo. Live Demo Enough theory -- here's what it looks like in practice. Step 1: Install the RPM Installing Context Cloak via BIG-IP Package Management LX Step 2: Configure and Deploy Context Cloak GUI -- MCP server, LLM endpoint, PII fields, one-click deploy Deployment output showing session config and saved configuration Step 3: Verify Virtual Servers BIG-IP Local Traffic showing MCP VS and Inference VS created by Context Cloak Step 4: Baseline -- No Cloaking Without Context Cloak: real PII flows directly to the LLM in cleartext This is the "before" picture. The LLM sees everything: real names, real SSNs, real account numbers. Demo 1: Substitute Mode -- SSN Lookup Prompt: "Show me the SSN number for John Doe. Just display the number." Substitute mode -- Open WebUI + Context Cloak GUI showing all fields as Substitute Result: User sees real SSN 078-05-1120. LLM saw a digit-shifted fake. Demo 2: Substitute Mode -- Account Lookup Prompt: "What accounts are associated to John Doe?" Left: Open WebUI with real data. Right: vLLM logs showing "Maria Garcia" with fake account numbers What the LLM saw: "customer_name": "Maria Garcia" "account_number": "7865-4412-3375" (checking) "account_number": "7865-4412-3322" (investment) "account_number": "7865-4412-3376" (savings) What the user saw: Customer: John Doe Checking: 4532-1189-0042 -- $45,230.18 Investment: 4532-1189-0099 -- $312,500.00 Savings: 4532-1189-0043 -- $128,750.00 Switching to Tokenize Mode Changing PII fields from Substitute to Tokenize in the GUI Demo 3: Mixed Mode -- Tokenized SSN SSN set to Tokenize, name set to Substitute. Prompt: "Show me the SSN number for Jane Smith. Just display the number." Mixed mode -- real SSN de-cloaked on left, <<SSN:...>> token visible in vLLM logs on right What the LLM saw: "customer_name": "Maria Thompson" "ssn": "<<SSN:32.192.169.232:001>>" What the user saw: Jane Smith, SSN 219-09-9999 Both modes operating on the same customer record, in the same request. Demo 4: Full Tokenize -- The Punchline ALL fields set to Tokenize mode. Prompt: "Show me the SSN and account information for Carlos Rivera. Display all the numbers." Full tokenize -- every PII field as a token, all de-cloaked on return What the LLM saw -- every PII field was a token: "full_name": "<<name:32.192.169.232:001>>" "ssn": "<<SSN:32.192.169.232:002>>" "phone": "<<phone:32.192.169.232:002>>" "email": "<<email:32.192.169.232:001>>" "account_number": "<<digit_shift:32.192.169.232:002>>" (checking) "account_number": "<<digit_shift:32.192.169.232:003>>" (investment) "account_number": "<<digit_shift:32.192.169.232:004>>" (savings) What the user saw -- all real data restored: Name: Carlos Rivera SSN: 323-45-6789 Checking: 6789-3345-0022 -- $89,120.45 Investment: 6789-3345-0024 -- $890,000.00 Savings: 6789-3345-0023 -- $245,000.00 And here's the best part. Qwen's last line in the response: "Please note that the actual numerical values for the SSN and account numbers are masked due to privacy concerns." The LLM genuinely believed it showed the user masked data. It apologized for the "privacy masking" -- not knowing that BIG-IP had already de-cloaked every token back to the real values. The user saw the full, real, unmasked report. What's Next: F5 AI Guardrails Integration Context Cloak's tokenize mode is designed to complement F5 AI Guardrails. The <<TYPE:ID:SEQ>> format is intentionally distinctive -- if any token leaks through de-cloaking, a guardrails policy can catch it as a pattern match violation. The vision: Context Cloak as the first layer of defense (PII never reaches the LLM), AI Guardrails as the safety net (catches anything that slips through). Defense in depth for AI data protection. Other areas I'm exploring: Hostname-based LLM routing -- BIG-IP as a model gateway with per-route cloaking policies JSON profile integration -- native BIG-IP JSON DOM parsing instead of regex Auto-discovery of MCP tool schemas for PII field detection Centralized cloaking policy management across multiple BIG-IP instances Try It Yourself The complete project is open source: https://github.com/j2rsolutions/f5_mcp_context_cloak The repository includes Terraform for AWS infrastructure, Kubernetes manifests, the iAppLX package (RPM available in Releases), iRules, sample financial data, a test script, comprehensive documentation, and a full demo walkthrough with GIFs (see docs/demo-evidence.md). A Note on Production Readiness I want to be clear: this is a lab proof-of-concept. I have not tested this in a production environment. The cloaking subtable stores PII in BIG-IP memory, the fake name pool is small (100 combinations), the SSL certificates are self-signed, and there's no authentication on the MCP server. There are edge cases around streaming responses, subtable TTL expiry, and LLM-derived values that need more work. But the core concept is proven: BIG-IP can transparently cloak PII in LLM workflows using value substitution and tokenization, and the iAppLX packaging makes it deployable and configurable without touching iRule code. I'd love to hear what the community thinks. Is this approach viable for your use cases? What PII types would you need to support? How would you handle the edge cases? What would it take to make this production-ready for your environment? Let me know in the comments -- and if you want to contribute, PRs are welcome! Demo Environment F5 BIG-IP VE v21.0.0.1 on AWS (m5.xlarge) Qwen 2.5 14B Instruct AWQ on vLLM 0.8.5 (NVIDIA L4, 24GB VRAM) MCP Server: FastMCP 1.26 + PostgreSQL 16 on Kubernetes (RKE2) Open WebUI v0.8.10 Context Cloak iAppLX v0.2.0 References Managing MCP in iRules -- Part 1 Managing MCP in iRules -- Part 2 Managing MCP in iRules -- Part 3 Model Context Protocol Specification James Veitch: This is what happens when you reply to spam email (TED, skip to 4:40)152Views1like0CommentsEmbedding APM Protected Resources into Third-Party Sites
This is the story of a fight with CORS (Cross-Origin Resource Sharing) and the process of understanding how it actually works. APM is a powerful tool that provides solutions for both simple and complex use cases. However, I have historically struggled with one specific scenario: embedding an APM-protected application into a third-party site. Unfortunately APM doesn't provide any mechanism to make this easy. Everything works when accessing the APM application directly. But when the same application was embedded in another site, it failed silently—nothing rendered, and the browser console filled with errors. Since I never had the opportunity to fully investigate the issue, alternative solutions were usually chosen. Recently, I worked with a customer who needed protection for a web application, and APM seemed like the right fit. The application was divided into public and private components, where only the private resources required authentication. This appeared straightforward, and I initially assumed that some iRule logic would be sufficient. But unbeknownst to me the site was not always the entry point to the application which meant that I now had the same old problem with serving content to a 3. party site. Now I was forced to look into CORS for real and how to handle this beast. I used a fair amount of time to get a better understanding and to my surprise it wasn't really all that difficult to fix, it looked like I just needed to inject a couple of headers in the response and then it would all be dandy. This is where the complexity began - specifically around iRules on a virtual server with APM enabled; I just couldn't get it to insert the headers the way I wanted. While there are multiple ways to solve this, I chose a layered virtual server design to keep the logic clean and predictable. This weird construct has been my goto solution for some time now and proven quite reliable. With a layered VS you have two virtual servers which are glued together via an iRule command "virtual". This gives you the option to run modules, iRules, policies etc. independently of each other. One of the VS' is the entry point and based on the logic you then forward traffic to the second one. In this setup the frontend virtual server - the one exposed to the users - has a single iRule responsible for: Handling CORS preflight requests by returning the appropriate headers Injecting CORS headers into responses when the origin is allowed Forwarding all non-preflight requests to the APM virtual server This separation ensures full control over HTTP processing without being constrained by APM behavior. On the inner APM virtual server, an access profile is attached which handles authentication. I usually set a non-reachable IP address on the inner VS to ensure that it can only be reached via the frontend VS. Initially, I planned to use a per-request policy on the inner APM VS with a URL branch agent to determine whether a request should be authenticated or not. While this looked correct on paper, it failed in practice. The third-party site was requesting embedded resources (such as images), and its logic could not handle APM redirects (e.g., '/my.policy'). One possible workaround was to use "clientless mode" by inserting the special header: HTTP::header insert "clientless-mode" 1 However, this introduces additional logic without providing real benefits and I wasn't sure if the application would handle the session cookie correctly or just create a million new APM sessions. Instead, I implemented an iRule that performs a datagroup lookup. If a match is found, APM is bypassed entirely for that request. This approach is simpler to maintain and reduces load by not utilizing the APM module. Below is a diagram illustrating the request flow and decision logic: A user browses the 3. party site which has links to our site. The Origin site. The browser retrieves the resources on our site. Should the browser decided to make a preflight request, the iRule will verify the Origin header from a datagroup and if allowed return the CORS headers. Forward the traffic to the inner APM VS. The iRule on the inner APM VS looks up in a datagroup and find no match and the authentication process is executed. The iRule on the inner APM VS looks up in a datagroup and find a match and disables APM. On the response from the backend we check if the origin was on the approved list. and if so we inject the CORS headers which will allow for the browser to show the content. A user browses the site directly which will bypass any CORS logic. Here is the iRule for the frontend VS: # ============================================================================= # iRule: Outer virtual for redirect + CORS before APM # ----------------------------------------------------------------------------- # Purpose: # - Redirect "/" on portal.example.com to /portal/home/ # - Handle CORS preflight locally before APM # - Forward all other traffic to the inner APM virtual # - Inject CORS headers into normal responses # # Dependencies: # - Attached to outer/public virtual server # - Inner virtual server exists and is called via "virtual" # - Internal string datagroup for allowed CORS origin hostnames # # Datagroups: # - portal_example_com_allowed_cors_origins_dg # # Notes: # - Datagroup must contain lowercase hostnames only # - Empty datagroup = allow all origins # # ============================================================================= when RULE_INIT { set static::portal_example_com_outer_cors_debug_enabled 1 } when HTTP_REQUEST { # Initialize request-scoped state explicitly. set cors_origin "" set cors_origin_host "" set cors_is_allowed 0 if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: HTTP_REQUEST start - host=[HTTP::host] uri=[HTTP::uri] method=[HTTP::method]" } # ------------------------------------------------------------------------- # Root redirect # ------------------------------------------------------------------------- if { ([string tolower [getfield [HTTP::host] ":" 1]] eq "portal.example.com") && ([HTTP::uri] eq "/") } { if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: root redirect matched" } HTTP::redirect "https://portal.example.com/portal/home/" return } # ------------------------------------------------------------------------- # Origin evaluation (empty DG = allow all) # ------------------------------------------------------------------------- if { [HTTP::header exists "Origin"] } { set cors_origin [HTTP::header "Origin"] set cors_origin_host [string tolower [URI::host $cors_origin]] if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: origin='$cors_origin' parsed_host='$cors_origin_host'" } if { ([class size portal_example_com_allowed_cors_origins_dg] == 0) || ($cors_origin_host ne "" && [class match -- $cors_origin_host equals portal_example_com_allowed_cors_origins_dg]) } { set cors_is_allowed 1 if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: origin allowed" } } else { if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: origin NOT allowed" } } } else { if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: no Origin header" } } # ------------------------------------------------------------------------- # Preflight handling # ------------------------------------------------------------------------- if { $cors_is_allowed } { if { ([HTTP::method] eq "OPTIONS") && ([HTTP::header exists "Access-Control-Request-Method"]) } { if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: handling preflight locally" } HTTP::respond 200 noserver \ "Access-Control-Allow-Origin" $cors_origin \ "Access-Control-Allow-Methods" "GET, POST, OPTIONS" \ "Access-Control-Allow-Headers" [HTTP::header "Access-Control-Request-Headers"] \ "Access-Control-Max-Age" "86400" \ "Vary" "Origin" return } } if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: forwarding to inner virtual" } # ------------------------------------------------------------------------- # Forward to inner APM virtual # ------------------------------------------------------------------------- virtual portal.example.com_https_vs } when HTTP_RESPONSE { if { $cors_is_allowed && $cors_origin ne "" } { if { $static::portal_example_com_outer_cors_debug_enabled } { log local0. "debug: injecting CORS headers" } HTTP::header replace "Access-Control-Allow-Origin" $cors_origin HTTP::header replace "Vary" "Origin" } } Here is the iRule for the inner APM VS: # ============================================================================= # iRule: Selective APM bypass for portal.example.com using datagroups # ----------------------------------------------------------------------------- # Purpose: # Disable APM only for explicitly public endpoint prefixes while preserving # APM protection for everything else. # # Dependencies: # - BIG-IP LTM # - BIG-IP APM # - Internal string datagroup for public path prefixes # # Datagroups: # - gisportal_public_path_prefixes_dg # # Notes: # - Matching is done against the raw request path derived from HTTP::uri. # - Only the query string is stripped. # - Datagroup entries are matched using starts_with behavior. # - APM is disabled only when a request matches an explicit public prefix. # - All other requests remain protected by APM. # - Debug logging can be enabled in RULE_INIT by setting: # static::portal_example_com_apm_bypass_debug 1 # # ============================================================================= when RULE_INIT { set static::portal_example_com_apm_bypass_debug 1 } when HTTP_REQUEST { set normalized_host [string tolower [getfield [HTTP::host] ":" 1]] set normalized_uri [string tolower [HTTP::uri]] # ------------------------------------------------------------------------- # Extract request path from raw URI # ------------------------------------------------------------------------- set query_delimiter_index [string first "?" $normalized_uri] if { $query_delimiter_index >= 0 } { set normalized_path [string range $normalized_uri 0 [expr {$query_delimiter_index - 1}]] } else { set normalized_path $normalized_uri } if { $static::portal_example_com_apm_bypass_debug } { log local0. "debug: host='$normalized_host' uri='$normalized_uri' path='$normalized_path'" } if { $normalized_host ne "portal.example.com" } { if { $static::portal_example_com_apm_bypass_debug } { log local0. "debug: host did not match target host, skipping rule" } return } # ------------------------------------------------------------------------- # PUBLIC # ------------------------------------------------------------------------- set matched_public_prefix [class match -name -- $normalized_path starts_with gisportal_public_path_prefixes_dg] if { $static::portal_example_com_apm_bypass_debug } { if { $matched_public_prefix ne "" } { log local0. "debug: matched PUBLIC prefix '$matched_public_prefix' -> disabling APM" } else { log local0. "debug: no public prefix matched -> APM remains enabled" } } if { $matched_public_prefix ne "" } { ACCESS::disable return } } I can recommend spending time on YouTube to get a better feeling about what CORS is about and why it is being used. You might run into another problem with APM if you try to embed the entire application, with APM authentication logic, into a frame in a 3. party app. I have not addressed it in this example, but you could extend the iRule logic to inject CSP headers to make this possible. I might address this in another article. I hope this example can help you fast-track pass all the headaches I struggled with. If you have any feedback just let me know. I don't know everything about CORS and I'm sure there are areas which requires special attention that I haven't addressed. Tell me so we can enrich the solution by sharing knowledge.291Views2likes1CommentCIS F5 Benchmark Reporter
Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’. The CIS_F5_Benchmark_Reporter.py is a Python script that can be run on a F5 BIG-IP. This script will check if the configuration of the F5 BIG-IP is compliant with the CIS Benchmark for F5. The script will generate a report that can be saved to a file, send by e-mail or send its output to the screen. Just use the appropriate arguments when running the script. [root@bigipa:Active:Standalone] # ./CIS_F5_Benchmark_Reporter.py Usage: CIS_F5_Benchmark_Reporter.py [OPTION]... Mandatory arguments to long options are mandatory for short options too. -f, --file=FILE output report to file. -m, --mail output report to mail. -s, --screen output report to screen. Report bugs to nvansluis@gmail.com [root@bigipa:Active:Standalone] # To receive a daily or weekly report from your F5 BIG-IP, you can create a cron job. Below is a screenshot that shows what the report will look like. Settings In the script, there is a section named 'User Options'. These options should be modified to reflect your setup. #----------------------------------------------------------------------- # User Options - Configure as desired #----------------------------------------------------------------------- E-mail settings Here the e-mail setting can be configured, so the script will be able to send a report by e-mail. # e-mail settings port = 587 smtp_server = "smtp.example.com" sender_email = "johndoe@example.com" receiver_email = "johndoe@example.com" login = "johndoe" password = "mySecret" SNMP settings Here you can add additional SNMP clients. These are necessary to be compliant with control 6.1. # list containing trusted IP addresses and networks that have access to SNMP (control 6.1) snmp_client_allow_list = [ "127.0.0.0/8", ] Exceptions Sometimes there are valid circumstances, why a specific requirement of a security control can't be met. In this case you can add an exception. See the example below. # set exceptions (add your own exceptions) exceptions = { '2.1' : "Exception in place, because TACACS is used instead of RADIUS.", '2.2' : "Exception in place, because TACACS is used and there are two TACACS-servers present." } Recommendations Store the script somewhere in the /shared partition. The data stored on this partition will still be available after an upgrade. Feedback This script has been tested on F5 BIG-IP version 17.x. If you have any questions, remarks or feedback, just let me know. Download The script can be downloaded from github.com. https://github.com/nvansluis/CIS_F5_Benchmark_Reporter597Views8likes8Comments- 807Views3likes7Comments
iRule based RADIUS Server Stack
Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’. Short Description The iRule based RADIUS Server Stack can be used to turn a UDP-based Virtual Server into a flexible and fully featured RADIUS Server, including regular REQUEST/RESPONSE as well as CHALLENGE/RESPONSE based RADIUS authentication. Problem solved by this Code Snippet The RADIUS Server Stack covers the RADIUS protocol core-mechanics outlined in RFC 2865 and RFC 5080 and can easily be extended to support every other RADIUS related RFC built on top of these specifications. The RADIUS Server Stack can be used as an extension for LTMs missing RADIUS Server functionalities, as well as iRule command functionalities to support Self-Hosted RADIUS Server scenarios. How to use this Code Snippet Visit my GitHub Repository for further explanations how the RADIUS Server Stack can be used to perform RADIUS Server operations within an iRule. Code Snippet Meta Information Version: 1.1 Coding Language: TCL Full Code Snippet Visit: https://github.com/KaiWilke/F5-iRule-RADIUS-Server-Stack868Views1like1CommentiRule based RADIUS Client Stack
Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’. Short Description The iRule based RADIUS Client Stack can be used to perform RADIUS based user authentication via SIDEBAND UDP connections. Problem solved by this Code Snippet The RADIUS Client Stack covers the RADIUS protocol core-mechanics outlined in RFC 2865 and RFC 5080 and can be utilized for a Password Authentication Protocol (PAP) authentication within an iRule. How to use this Code Snippet Visit my GitHub Repository for further explanations how the RADIUS Client Stack can be used to perform RADIUS Client operations within an iRule. Code Snippet Meta Information Version: 1.1 Coding Language: TCL Full Code Snippet Visit: https://github.com/KaiWilke/F5-iRule-RADIUS-Client-Stack1.4KViews2likes1Comment