<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>Community Articles articles</title>
    <link>https://community.f5.com/t5/community-articles/tkb-p/communityarticles</link>
    <description>Community Articles articles</description>
    <pubDate>Wed, 27 May 2026 20:05:44 GMT</pubDate>
    <dc:creator>communityarticles</dc:creator>
    <dc:date>2026-05-27T20:05:44Z</dc:date>
    <item>
      <title>Automating TLS Certificates in Kubernetes with cert-manager and F5 Distributed Cloud DNS</title>
      <link>https://community.f5.com/t5/community-articles/automating-tls-certificates-in-kubernetes-with-cert-manager-and/ta-p/346541</link>
      <description>&lt;H2&gt;Introduction&lt;/H2&gt;
&lt;P&gt;If you run workloads in Kubernetes or Open Shift, you've almost certainly dealt with TLS certificates. You need them everywhere — Ingress controllers, internal services, mutual TLS between microservices, and API gateways. Managing them by hand is error-prone and doesn't scale: certificates expire silently, rotation is forgotten, and the person who originally created the wildcard cert is now working somewhere else.&lt;/P&gt;
&lt;P&gt;&lt;A href="https://cert-manager.io/" target="_blank" rel="noopener"&gt;cert-manager&lt;/A&gt; solves this elegantly. It's a Kubernetes-native certificate controller that automates the issuance, renewal, and management of TLS certificates. It speaks ACME — the same protocol Let's Encrypt uses — but ACME is a standard, not a Let's Encrypt exclusive. You can point cert-manager at:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Let's Encrypt&lt;/STRONG&gt; (free, public, widely trusted)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;ZeroSSL, Buypass, Google Trust Services&lt;/STRONG&gt; — other public CAs supporting ACME&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Step CA / HashiCorp Vault / Smallstep&lt;/STRONG&gt; — for private PKI running inside your infrastructure&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Any commercial CA&lt;/STRONG&gt; that has implemented an ACME endpoint&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This means the same workflow, the same Kubernetes manifests, and the same tooling can back both your public-facing services and your internal, corporate-signed certificates. One operator to rule them all.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Why DNS-01 Challenge?&lt;/H3&gt;
&lt;P&gt;ACME offers multiple ways to prove you own a domain. The most common is the &lt;STRONG&gt;HTTP-01 challenge&lt;/STRONG&gt;, where the ACME server checks a well-known URL on your domain. It works well, but has limitations:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The endpoint must be publicly reachable on port 80&lt;/LI&gt;
&lt;LI&gt;It cannot issue &lt;STRONG&gt;wildcard certificates&lt;/STRONG&gt; (&lt;SPAN class="lia-text-color-13"&gt;&lt;EM&gt;*.example.com&lt;/EM&gt;&lt;/SPAN&gt;)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The &lt;STRONG&gt;DNS-01 challenge&lt;/STRONG&gt; takes a different approach: cert-manager (via a solver webhook) creates a &lt;SPAN class="lia-text-color-13"&gt;&lt;EM&gt;_acme-challenge.example.com&lt;/EM&gt; &lt;/SPAN&gt;TXT record in your DNS zone. The ACME server checks for this record. Once verified, the TXT record is cleaned up automatically.&lt;/P&gt;
&lt;P&gt;Benefits:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Works behind firewalls&lt;/STRONG&gt; — no inbound HTTP needed&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Supports wildcard certificates&lt;/STRONG&gt; — a single &lt;SPAN class="lia-text-color-13"&gt;&lt;EM&gt;*.example.com&lt;/EM&gt;&lt;/SPAN&gt; certificate covers all subdomains&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Fully automated&lt;/STRONG&gt; — the webhook handles record creation and deletion&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;If your DNS is managed by &lt;STRONG&gt;F5 Distributed Cloud (F5 XC)&lt;/STRONG&gt;, you can now wire this entire flow together with the open-source &lt;SPAN class="lia-text-color-13"&gt;&lt;A class="lia-external-url" href="https://artifacthub.io/packages/helm/cert-manager-webhook-f5xc/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;cert-manager-webhook-f5xc&lt;/A&gt;&amp;nbsp;&lt;/SPAN&gt;solver.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Architecture Overview&lt;/H2&gt;
&lt;P&gt;Here's what happens when cert-manager issues a certificate using the F5 XC webhook:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Developer applies Certificate manifest&lt;BR /&gt;▼&lt;BR /&gt;cert-manager creates Order + Challenge&lt;BR /&gt;▼&lt;BR /&gt;cert-manager calls webhook (DNS-01 solver)&lt;BR /&gt;▼&lt;BR /&gt;Webhook calls F5 XC DNS API → Creates TXT record: _acme-challenge.example.com&lt;BR /&gt;▼&lt;BR /&gt;ACME server (Let's Encrypt / other) validates the TXT record&lt;BR /&gt;▼&lt;BR /&gt;Webhook cleans up the TXT record&lt;BR /&gt;▼&lt;BR /&gt;cert-manager stores the issued certificate in a Kubernetes Secret&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The webhook runs as a standard Kubernetes Deployment inside your cluster, registered with cert-manager via a &lt;STRONG&gt;&lt;EM&gt;&lt;SPAN class="lia-text-color-13"&gt;ValidatingWebhookConfiguration&lt;/SPAN&gt;.&lt;/EM&gt;&lt;/STRONG&gt; It receives solver calls from cert-manager and translates them into F5 XC DNS API calls using an API token you provide as a Kubernetes Secret.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Prerequisites&lt;/H2&gt;
&lt;P&gt;Before we start, make sure you have the following in place:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A Kubernetes cluster (1.21+)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;cert-manager&lt;/STRONG&gt; installed (v1.14+)&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI-CODE lang="bash"&gt;kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml&lt;/LI-CODE&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Helm&lt;/STRONG&gt; 3.8+&lt;/LI&gt;
&lt;LI&gt;An &lt;STRONG&gt;F5 Distributed Cloud tenant&lt;/STRONG&gt; with DNS management enabled&lt;/LI&gt;
&lt;LI&gt;Your domain's DNS zone managed in F5 XC&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;F5 XC credentials&lt;/STRONG&gt; for DNS API access — either an &lt;STRONG&gt;API Token&lt;/STRONG&gt; or a &lt;STRONG&gt;Client Certificate&lt;/STRONG&gt; (P12); see Step 1 below for details&lt;/LI&gt;
&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Least privilege note:&lt;/STRONG&gt; The service account or user whose credentials you use must have permission to manage DNS records. As of the time of writing, the built-in role &lt;SPAN class="lia-text-color-13"&gt;&lt;STRONG&gt;f5xc-dns-management-admin&lt;/STRONG&gt;&lt;/SPAN&gt; is sufficient. Avoid using tenant-admin or other overly broad roles — the webhook only needs to create and delete TXT records in your DNS zone.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;Step 1: Prepare F5 XC Credentials&lt;/H2&gt;
&lt;P&gt;The webhook supports two authentication methods against the F5 XC DNS API: an &lt;STRONG&gt;API Token&lt;/STRONG&gt; or a &lt;STRONG&gt;Client Certificate (P12)&lt;/STRONG&gt;. Both are stored as a Kubernetes Secret in the &lt;SPAN class="lia-text-color-13"&gt;&lt;EM&gt;cert-manager&lt;/EM&gt;&lt;/SPAN&gt; namespace.&lt;/P&gt;
&lt;H3&gt;Obtaining credentials in F5 XC Console&lt;/H3&gt;
&lt;P&gt;Regardless of which method you choose, the service account must have sufficient permissions to manage DNS records. Follow the least-privilege principle:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;In the F5 XC Console, navigate to &lt;STRONG&gt;Account Settings → Administration&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Create a dedicated service credential under IAM and assign it the &lt;SPAN class="lia-text-color-13"&gt;&lt;EM&gt;&lt;STRONG&gt;f5xc-dns-management-admin&lt;/STRONG&gt;&lt;/EM&gt;&lt;/SPAN&gt; role in the &lt;EM&gt;&lt;SPAN class="lia-text-color-13"&gt;system namespace&lt;/SPAN&gt;&lt;/EM&gt; — this is the minimum required role as of the time of writing and grants access to DNS Zone Management without unnecessary privileges elsewhere in the tenant. Or use an existing account privileges under Personal Management credentials.&lt;/LI&gt;
&lt;LI&gt;Generate the credentials of your preferred type (API Token or API Certificate)&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Option A: API Token (simpler, recommended for most setups)&lt;/H3&gt;
&lt;P&gt;Take the API Token obtained from the F5XC console and use it with the following command&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl create secret generic f5xc-api-token \
--namespace cert-manager \
--from-literal=token=&amp;lt;YOUR_F5XC_API_TOKEN&amp;gt;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Option B: Client Certificate (P12)&lt;/H3&gt;
&lt;P&gt;F5 XC also supports certificate-based authentication using a P12 (PKCS#12) client certificate, which may be preferred in environments. Use the certificate and password generated in the previous step and store it as a Secret:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl create secret generic f5xc-client-cert \
--namespace cert-manager \
--from-file=certificate.p12=&amp;lt;PATH_TO_YOUR.p12&amp;gt; \
--from-literal=password=&amp;lt;P12_PASSWORD&amp;gt;&lt;/LI-CODE&gt;
&lt;P&gt;Refer to the &lt;A href="https://github.com/Wenkow/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;webhook documentation&lt;/A&gt; for the exact certificateSecretRef fields to use in the solver config when choosing this method.&lt;/P&gt;
&lt;P&gt;Verify the secret was created:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get secret f5xc-api-token -n cert-manager&lt;/LI-CODE&gt;&lt;img /&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;Step 2: Install the Webhook via Helm&lt;/H2&gt;
&lt;P&gt;The chart is published as an OCI artifact on GitHub Container Registry. Install it into the &lt;SPAN class="lia-text-color-13"&gt;cert-manager&lt;/SPAN&gt; namespace:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;helm install cert-manager-webhook-f5xc \
oci://ghcr.io/wenkow/charts/cert-manager-webhook-f5xc \
--namespace cert-managerbaba&lt;/LI-CODE&gt;
&lt;P&gt;Check the rollout:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl rollout status \
deployment cert-manager-webhook-f5xc \
-n cert-manager
&lt;/LI-CODE&gt;&lt;img /&gt;&lt;LI-CODE lang="bash"&gt;kubectl get pods -n cert-manager&lt;/LI-CODE&gt;&lt;img /&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;Step 3: Configure a ClusterIssuer&lt;/H2&gt;
&lt;P&gt;A &lt;SPAN class="lia-text-color-13"&gt;ClusterIssuer&lt;/SPAN&gt; tells cert-manager which ACME server to use and how to solve challenges. Here we're pointing it at Let's Encrypt production and configuring the F5 XC DNS-01 solver.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Note on &lt;SPAN class="lia-text-color-13"&gt;groupName&lt;/SPAN&gt;:&lt;/STRONG&gt; The field appears twice in the YAML below and serves different purposes. At the &lt;SPAN class="lia-text-color-13"&gt;webhook&lt;/SPAN&gt; level, it's a fixed identifier (&lt;SPAN class="lia-text-color-13"&gt;acme.f5xc.io&lt;/SPAN&gt;) that tells cert-manager which registered webhook to call. Inside &lt;SPAN class="lia-text-color-13"&gt;config&lt;/SPAN&gt;, it's the &lt;EM&gt;&lt;STRONG&gt;RRSet group name&lt;/STRONG&gt; &lt;/EM&gt;within your F5 XC DNS zone — a logical container for DNS records created by the webhook. You can choose any name; F5 XC will create the group if it doesn't exist.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;clusterissuer.yaml:&lt;/P&gt;
&lt;LI-CODE lang="yaml"&gt;apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-f5xc-prod
spec:
  acme:
    email: admin@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-f5xc-prod-account-key
    solvers:
      - dns01:
          webhook:
            # Fixed identifier — tells cert-manager which webhook to call
            groupName: acme.f5xc.io
            solverName: f5xc
            config:
              # Your F5 XC tenant name (subdomain part of your console URL)
              tenantName: my-tenant
              # RRSet group name in F5 XC DNS zone
              groupName: "cert-manager"
              # ttl: 120   # optional, default is 120 seconds
              apiTokenSecretRef:
                name: f5xc-api-token
                key: token
              # If using certificate-based auth instead of a token, replace
              # apiTokenSecretRef with certificateSecretRef — see webhook docs.&lt;/LI-CODE&gt;
&lt;P&gt;Apply it:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl apply -f clusterissuer.yaml
&lt;/LI-CODE&gt;
&lt;P&gt;Verify it's ready:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get clusterissuer letsencrypt-f5xc-prod
&lt;/LI-CODE&gt;&lt;img /&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;Step 4: Request a Certificate&lt;/H2&gt;
&lt;P&gt;Now the fun part. Create a Certificate resource. Note that we're requesting &lt;STRONG&gt;both the apex domain and a wildcard&lt;/STRONG&gt; — something that's only possible with DNS-01.&lt;/P&gt;
&lt;P&gt;certificate.yaml:&lt;/P&gt;
&lt;LI-CODE lang="yaml"&gt;apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-tls
  namespace: default
spec:
  secretName: example-tls
  issuerRef:
    name: letsencrypt-f5xc-prod
    kind: ClusterIssuer
  dnsNames:
    - example.com
    - "*.example.com"&lt;/LI-CODE&gt;
&lt;P&gt;Apply it:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl apply -f certificate.yaml
&lt;/LI-CODE&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;H2&gt;Step 5: Watch the Certificate Lifecycle&lt;/H2&gt;
&lt;P&gt;This is where it gets satisfying to watch. cert-manager creates an Order, which spawns one or more Challenge objects. Each Challenge triggers the F5 XC webhook to create a DNS TXT record.&lt;/P&gt;
&lt;H3&gt;Watch Certificate status&lt;/H3&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get certificate example-tls -n default -w
&lt;/LI-CODE&gt;&lt;img /&gt;
&lt;H3&gt;Inspect the Order&lt;/H3&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get orders -n default
&lt;/LI-CODE&gt;&lt;img /&gt;&lt;LI-CODE lang="bash"&gt;kubectl describe order example-tls-1-3552197254 -n default
&lt;/LI-CODE&gt;&lt;LI-CODE lang="zig"&gt;Status:
  Authorizations:
    Challenges:
      Token:        &amp;lt;token&amp;gt;
      Type:         dns-01
      URL:          https://acme-v02.api.letsencrypt.org/acme/chall/...
    Identifier:     example.com
    Initial State:  valid
    URL:            https://acme-v02.api.letsencrypt.org/acme/authz/...
    Wildcard:       true
    Challenges:
      Token:        &amp;lt;token&amp;gt;
      Type:         dns-01
      URL:          https://acme-v02.api.letsencrypt.org/acme/chall/...
    Identifier:     example.com
    Initial State:  valid
    URL:            https://acme-v02.api.letsencrypt.org/acme/authz/...
    Wildcard:       false
  Certificate:      REDACTED
  Finalize URL:     https://acme-v02.api.letsencrypt.org/acme/finalize/...
  State:            valid
  URL:              https://acme-v02.api.letsencrypt.org/acme/order/...
Events:
  Type    Reason    Age    From                 Message
  ----    ------    ----   ----                 -------
  Normal  Complete  8m37s  cert-manager-orders  Order completed successfully&lt;/LI-CODE&gt;
&lt;H3&gt;Inspect the Challenges before it's done&lt;/H3&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get challenges -n default
&lt;/LI-CODE&gt;&lt;LI-CODE lang="bash"&gt;kubectl describe challenge example-tls-&amp;lt;1234567890&amp;gt; -n default
&lt;/LI-CODE&gt;
&lt;H3&gt;Verify the Issued Certificate&lt;/H3&gt;
&lt;LI-CODE lang="bash"&gt;kubectl get secret example-tls -n default -o jsonpath='{.data.tls\.crt}' \
  | base64 -d | openssl x509 -noout -text | grep -E "Subject:|DNS:|Not After"&lt;/LI-CODE&gt;&lt;LI-CODE lang="rust"&gt;            Not After : Aug 19 19:22:31 2026 GMT
        Subject: CN = example.com
                DNS:*.example.com, DNS:example.com
&lt;/LI-CODE&gt;
&lt;P&gt;Both the apex domain and the wildcard are covered by a single certificate.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Using a Custom or Internal ACME Server&lt;/H2&gt;
&lt;P&gt;One of the most powerful aspects of this setup is that the ACME server is completely configurable. If&amp;nbsp;you run an internal CA — for example&amp;nbsp;&lt;STRONG&gt;HashiCorp Vault&lt;/STRONG&gt; with the ACME secrets engine, or &lt;STRONG&gt;Step CA&lt;/STRONG&gt; — just change the server field in your ClusterIssuer:&lt;/P&gt;
&lt;LI-CODE lang="yaml"&gt;spec:
  acme:
    email: admin@internal.example.com
    server: https://vault.internal.example.com/v1/pki/acme/directory
    # or
    # server: https://step-ca.internal.example.com/acme/acme/directory&lt;/LI-CODE&gt;
&lt;P&gt;The webhook doesn't care which ACME server you use — it only handles the DNS side of the challenge. This makes the setup equally useful for:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Internet-facing services using Let's Encrypt&lt;/LI&gt;
&lt;LI&gt;Internal services using a corporate CA&lt;/LI&gt;
&lt;LI&gt;Mixed environments where different ClusterIssuer objects point to different CAs, all sharing the same F5 XC DNS solver&lt;/LI&gt;
&lt;LI&gt;&amp;nbsp;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Troubleshooting Tips&lt;/H2&gt;
&lt;P&gt;&lt;STRONG&gt;Challenge stays in pending for a long time&lt;/STRONG&gt; Check the webhook logs for API errors:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;kubectl logs -n cert-manager -l app=cert-manager-webhook-f5xc --tail=50&lt;/LI-CODE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN class="lia-text-color-13"&gt;READY: False&lt;/SPAN&gt; on ClusterIssuer&lt;/STRONG&gt; Usually means cert-manager couldn't register an ACME account. Check that the email field is valid and the ACME server URL is reachable.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;SPAN class="lia-text-color-13"&gt;TXT record not appearing in F5 XC&lt;/SPAN&gt; -&lt;/STRONG&gt;&amp;nbsp;Verify that the credentials you stored in the Secret have the right DNS permissions. In F5 XC Console, check that the service account has the&amp;nbsp;&lt;STRONG&gt;f5xc-dns-management-admin&lt;/STRONG&gt; role (or equivalent). API token permission issues will typically surface as 403 Forbidden errors in the webhook logs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Summary&lt;/H2&gt;
&lt;P&gt;The &lt;SPAN class="lia-text-color-13"&gt;cert-manager-webhook-f5xc&lt;/SPAN&gt; project closes the loop between F5 Distributed Cloud DNS and the Kubernetes-native certificate management ecosystem. With a few manifests and a Helm install, you get:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Fully automated certificate issuance and renewal&lt;/STRONG&gt; — no manual interventions, no expiry surprises&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Wildcard certificate support&lt;/STRONG&gt; out of the box via DNS-01&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;ACME provider flexibility&lt;/STRONG&gt; — works with Let's Encrypt, commercial CAs, or your internal PKI&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Clean Kubernetes-native UX&lt;/STRONG&gt; — certificates are just resources; the entire lifecycle is observable with standard &lt;SPAN class="lia-text-color-13"&gt;kubectl&lt;/SPAN&gt; commands&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The webhook is open source, available on &lt;A href="https://github.com/Wenkow/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;GitHub&lt;/A&gt; and packaged on &lt;A href="https://artifacthub.io/packages/helm/cert-manager-webhook-f5xc/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;Artifact Hub&lt;/A&gt;. Contributions and feedback are welcome.&lt;/P&gt;
&lt;H3&gt;Related Resources&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://cert-manager.io/docs/" target="_blank" rel="noopener"&gt;cert-manager documentation&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://cert-manager.io/docs/configuration/acme/dns01/webhook/" target="_blank" rel="noopener"&gt;cert-manager DNS01 webhook reference&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://docs.cloud.f5.com/docs-v2/dns-management/quickstart/dns-services" target="_blank" rel="noopener"&gt;F5 Distributed Cloud DNS Management docs&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://github.com/Wenkow/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;GitHub: Wenkow/cert-manager-webhook-f5xc&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://artifacthub.io/packages/helm/cert-manager-webhook-f5xc/cert-manager-webhook-f5xc" target="_blank" rel="noopener"&gt;Artifact Hub: cert-manager-webhook-f5xc&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 May 2026 08:22:39 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/automating-tls-certificates-in-kubernetes-with-cert-manager-and/ta-p/346541</guid>
      <dc:creator>mkylian</dc:creator>
      <dc:date>2026-05-23T08:22:39Z</dc:date>
    </item>
    <item>
      <title>F5 certificate deployment with iControl REST and HashiCorp Vault</title>
      <link>https://community.f5.com/t5/community-articles/f5-certificate-deployment-with-icontrol-rest-and-hashicorp-vault/ta-p/346445</link>
      <description>&lt;P&gt;Welcome to the first article in a comprehensive series dedicated to administrating F5 BIG-IP systems through the power of the iControl REST API. This series is designed for both beginners and experienced network administrators who want to streamline their F5 management workflows and embrace infrastructure-as-code principles.&lt;/P&gt;
&lt;P&gt;Throughout this series, we will explore practical, real-world scenarios for managing F5 BIG-IP appliances programmatically. Rather than relying solely on the F5 web interface, we'll leverage the iControl REST API.&lt;/P&gt;
&lt;P&gt;To make this journey accessible and efficient, I'll be using Restsh, my open-source command-line interface tool. Restsh is purpose-built to simplify interactions with the iControl REST API, abstracting away complexity while maintaining full flexibility. Whether you're new to F5 REST API or looking to enhance your automation skills, these tutorials will provide clear, step-by-step guidance with practical examples you can implement immediately.&lt;/P&gt;
&lt;P&gt;In this workflow, you’ll create the certificate materials on the F5, have them signed by a trusted Certificate Authority (in this case, HashiCorp Vault), and then deploy the signed certificate back to the F5. This process ensures that the private key never leaves the F5.&lt;/P&gt;
&lt;H2&gt;Initial configuration of Restsh&lt;/H2&gt;
&lt;P&gt;See &lt;A href="https://axiansitsecurity.github.io/Restsh/FirstSteps/index.html" target="_blank" rel="noopener"&gt;First Steps&lt;/A&gt; for the initial configuration of Restsh.&lt;/P&gt;
&lt;H2&gt;Connect&lt;/H2&gt;
&lt;P&gt;Connect to the F5 with Restsh:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;restsh&lt;/LI&gt;
&lt;LI&gt;Select your F5&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;1. Create a key pair and signing request (CSR) on the F5&lt;/H2&gt;
&lt;P&gt;The first step is to create a key pair and a Certificate Signing Request (CSR) on the F5. A key pair consists of a private key (which stays secret on the F5) and a public key. The CSR contains the public key and certificate details that will be sent to a Certificate Authority (CA) for signing.&lt;/P&gt;
&lt;P&gt;Below are the certificate parameters we’ll use for this example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Name on the F5: test.lab.lan&lt;/LI&gt;
&lt;LI&gt;Partition: Common&lt;/LI&gt;
&lt;LI&gt;CN: test.lab.lan&lt;/LI&gt;
&lt;LI&gt;Subject Alternative Names: test.lab.lan, test2.lab.lan&lt;/LI&gt;
&lt;LI&gt;Keytype: EC with SECP384R1&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI-CODE lang="shell"&gt;f5.cert.csr.create --cn=test.lab.lan --keytype=ec-private --curvename=secp384r1 -a test.lab.lan -a test2.lab.lan -n test.lab.lan&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;2. Download the signing request&lt;/H2&gt;
&lt;P&gt;The next step is to download the Certificate Signing Request from the F5 to your local machine. This file contains the public key and certificate information that needs to be signed by the Certificate Authority. We’ll save it to a temporary directory for processing.&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;f5.cert.csr.get /Common/test.lab.lan &amp;gt; "$RESTSH_TMP/test.lab.lan.csr"&lt;/LI-CODE&gt;
&lt;P&gt;You can inspect the details of the CSR to verify it contains the correct information (domain names, key type, etc.). The cert.* commands are convenient wrapper scripts for the OpenSSL command-line tool, making certificate operations easier.&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;cert.csr.show "$RESTSH_TMP/test.lab.lan.csr"&lt;/LI-CODE&gt;
&lt;P&gt;You can also view the public key contained in the CSR:&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;cert.csr.pubkey "$RESTSH_TMP/test.lab.lan.csr"&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;3. Sign the CSR with HashiCorp Vault&lt;/H2&gt;
&lt;P&gt;Now we use HashiCorp Vault to sign the CSR. Vault acts as your Certificate Authority (CA) and will create a signed certificate based on your CSR. First, you authenticate with Vault using vault login, then you submit the CSR for signing.&lt;/P&gt;
&lt;P&gt;The vault write command sends your CSR to the Vault PKI backend, which signs it and returns a complete certificate. In this example, we’re using the signing backend/role pki/sign/lab-ca (adjust this to match your Vault configuration).&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;vault login
vault write -field=certificate pki/sign/lab-ca csr=@"$RESTSH_TMP/test.lab.lan.csr" &amp;gt; "$RESTSH_TMP/test.lab.lan.crt"&lt;/LI-CODE&gt;
&lt;P&gt;After signing, you can verify the certificate details to ensure it was signed correctly and contains the expected information (domain names, validity period, key type, etc.):&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;cert.x509.show "$RESTSH_TMP/test.lab.lan.crt"&lt;/LI-CODE&gt;
&lt;P&gt;You can also view the public key in the signed certificate to confirm it matches the public key from the CSR:&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;cert.x509.pubkey "$RESTSH_TMP/test.lab.lan.crt"&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;4. Upload the signed certificate to the F5&lt;/H2&gt;
&lt;P&gt;Finally, we upload the signed certificate back to the F5. This makes the certificate available for use in SSL profiles. We use the same certificate name that we used when creating the CSR, so the F5 knows to pair it with the private key we created in step 1.&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;f5.cert.import /Common/test.lab.lan "$RESTSH_TMP/test.lab.lan.crt"&lt;/LI-CODE&gt;
&lt;P&gt;You can view the imported certificate with following command:&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;f5.cert.get /Common/test.lab.lan&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;5. Cleanup&lt;/H2&gt;
&lt;P&gt;Cleanup is optional the files in the temporary directory will be automatically removed after Restsh finishes. However, if you want to manually remove the CSR and certificate files from your local machine, you can do so with the following command:&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;rm "$RESTSH_TMP/test.lab.lan.csr" "$RESTSH_TMP/test.lab.lan.crt"&lt;/LI-CODE&gt;
&lt;P&gt;Optionally sync the F5 cluster to ensure the new certificate is available on all cluster members. "failover" is here the name of the Sync-Failover device group.&lt;/P&gt;
&lt;LI-CODE lang="shell"&gt;f5.cluster.config-sync failover&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Summary&lt;/H2&gt;
&lt;P&gt;In this tutorial, we walked through the process of deploying a new certificate on an F5 device using Restsh and HashiCorp Vault. We created a key pair and CSR on the F5, signed the CSR with Vault, and then imported the signed certificate back to the F5. This workflow allows you to securely manage certificates without exposing private keys, while leveraging the power of Restsh for automation and integration with your existing infrastructure.&lt;/P&gt;</description>
      <pubDate>Fri, 15 May 2026 05:31:30 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/f5-certificate-deployment-with-icontrol-rest-and-hashicorp-vault/ta-p/346445</guid>
      <dc:creator>Juergen_Mang</dc:creator>
      <dc:date>2026-05-15T05:31:30Z</dc:date>
    </item>
    <item>
      <title>The Blind Spot in Cloud WAF Architectures: Shared IPs and the Origin Bypass Problem</title>
      <link>https://community.f5.com/t5/community-articles/the-blind-spot-in-cloud-waf-architectures-shared-ips-and-the/ta-p/346393</link>
      <description>&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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: &lt;STRONG&gt;shared egress IPs&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;How Cloud WAF Proxying Actually Works&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;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."&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;That distinction matters enormously.&lt;/P&gt;
&lt;P&gt;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 &lt;EM&gt;your&lt;/EM&gt; 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.&lt;/P&gt;
&lt;P&gt;Your server is now reachable by anyone, even with a $20/month account for some vendors, on the same WAF platform.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Why This Matters More Than It Seems&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;This isn't a theoretical edge case. The attack surface is:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Broad&lt;/STRONG&gt;: Every Cloud WAF customer on a given platform could potentially reach any other customer's origin.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Silent&lt;/STRONG&gt;: The origin server receives the traffic without any obvious indication it bypassed the WAF policy.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Persistent&lt;/STRONG&gt;: It doesn't require exploiting a vulnerability, it exploits an intentional architectural property.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;The Missing Validation: Outbound Origin Ownership&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;What makes this problem interesting is the asymmetry in how Cloud WAFs handle trust.&lt;/P&gt;
&lt;P&gt;On the &lt;STRONG&gt;inbound&lt;/STRONG&gt; 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.&lt;/P&gt;
&lt;P&gt;On the &lt;STRONG&gt;outbound&lt;/STRONG&gt; 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."&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Mitigations Available Today&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;H3 class="lia-indent-padding-left-30px"&gt;&lt;STRONG&gt;Shared Secret Header Authentication&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;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.&lt;/P&gt;
&lt;H3 class="lia-indent-padding-left-30px"&gt;&lt;STRONG&gt;Mutual TLS Between WAF and Origin&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;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.&lt;/P&gt;
&lt;H3 class="lia-indent-padding-left-30px"&gt;&lt;STRONG&gt;Private Tunneling (Eliminating the Public IP Entirely)&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;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.&lt;/P&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;This approach is increasingly the recommended baseline for new deployments, not just a hardening option.&lt;/P&gt;
&lt;H3 class="lia-indent-padding-left-30px"&gt;&lt;STRONG&gt;Host Header Validation at the Origin&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;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.&lt;/P&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;A Note on F5 Distributed Cloud Customer Edge&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;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 &lt;STRONG&gt;Customer Edge (CE)&lt;/STRONG&gt; 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.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;H4&gt;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?&lt;/H4&gt;
&lt;P&gt;&lt;EM&gt;This article was written by the author and formatted with the assistance of AI.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 09 May 2026 09:07:28 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/the-blind-spot-in-cloud-waf-architectures-shared-ips-and-the/ta-p/346393</guid>
      <dc:creator>Injeyan_Kostas</dc:creator>
      <dc:date>2026-05-09T09:07:28Z</dc:date>
    </item>
    <item>
      <title>DNS: El protocolo que nadie ve...hasta que se convierte en el problema más grande de la arquitectura</title>
      <link>https://community.f5.com/t5/community-articles/dns-el-protocolo-que-nadie-ve-hasta-que-se-convierte-en-el/ta-p/346101</link>
      <description>&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;Y eso es precisamente lo peligroso.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;Cuando todo funciona, nadie pregunta por él. Cuando algo falla, todo lo demás deja de importar.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;H2&gt;DNS en la vida real: cuando la teoría se encuentra con la operación&lt;/H2&gt;
&lt;P&gt;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:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A qué sitio o región se dirige un usuario&lt;/LI&gt;
&lt;LI&gt;Qué backend recibe una solicitud&lt;/LI&gt;
&lt;LI&gt;Cómo se distribuye la carga entre múltiples data centers&lt;/LI&gt;
&lt;LI&gt;Qué tan rápido se recupera un servicio ante una degradación o caída&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;Si el DNS no está preparado para absorber ese pico:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;La aplicación nunca recibe tráfico&lt;/LI&gt;
&lt;LI&gt;Los balanceadores no alcanzan a participar&lt;/LI&gt;
&lt;LI&gt;La experiencia del usuario se degrada de inmediato&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Aquí es donde soluciones como &lt;A href="https://www.f5.com/products/big-ip-services/big-ip-dns" target="_blank" rel="noopener"&gt;F5 BIG-IP DNS&lt;/A&gt; 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:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Estado real de los servicios&lt;/LI&gt;
&lt;LI&gt;Salud de los backends&lt;/LI&gt;
&lt;LI&gt;Políticas de disponibilidad y continuidad&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;El boom de la inteligencia artificial y su impacto directo en DNS&lt;/H2&gt;
&lt;P&gt;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:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Más microservicios desacoplados&lt;/LI&gt;
&lt;LI&gt;Más APIs internas y externas&lt;/LI&gt;
&lt;LI&gt;Endpoints efímeros que aparecen y desaparecen&lt;/LI&gt;
&lt;LI&gt;Resoluciones dinámicas y frecuentes&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Cada llamada a un modelo, cada inferencia distribuida y cada backend que escala automáticamente comienza con una consulta DNS.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;¿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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;Desde una perspectiva técnica, esto tiene implicaciones claras:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Crecimiento sostenido y acelerado del volumen de consultas DNS&lt;/LI&gt;
&lt;LI&gt;Mayor sensibilidad a latencia y jitter en la resolución&lt;/LI&gt;
&lt;LI&gt;Mayor impacto de fallas parciales o intermitentes&lt;/LI&gt;
&lt;LI&gt;Patrones de tráfico menos predecibles y más difíciles de planificar&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;H2&gt;El DNS como punto crítico en eventos globales&lt;/H2&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;F5 Labs ha documentado ampliamente cómo:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Ataques volumétricos utilizan DNS como vector principal&lt;/LI&gt;
&lt;LI&gt;La amplificación DNS sigue siendo una técnica efectiva&lt;/LI&gt;
&lt;LI&gt;Eventos globales generan patrones de tráfico anómalos que exponen debilidades de diseño&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Primero la observabilidad: entender antes de reaccionar&lt;/H2&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;A href="https://community.f5.com/kb/technicalarticles/introducing-f5-insight-for-adsp/345601" data-test-app-aware-link="" target="_blank"&gt;F5 Insight&lt;/A&gt;, componente clave dentro de la plataforma F5 ADSP, permite:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Analizar patrones reales de consultas&lt;/LI&gt;
&lt;LI&gt;Identificar picos atípicos y comportamientos anómalos&lt;/LI&gt;
&lt;LI&gt;Correlacionar eventos externos con tráfico DNS&lt;/LI&gt;
&lt;LI&gt;Entender el porqué detrás del comportamiento del sistema&lt;/LI&gt;
&lt;/UL&gt;
&lt;img&gt;Dashboard Demo F5 Insight&lt;/img&gt;
&lt;P&gt;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).&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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"&lt;/P&gt;
&lt;H2&gt;Plataforma y arquitectura: cuando el DNS ya no es "básico"&lt;/H2&gt;
&lt;P&gt;Cuando el DNS se vuelve crítico, la plataforma importa. Arquitecturas basadas en &lt;A href="https://www.f5.com/es_es/products/big-ip-services/velos-hardware-chassis-and-blades" target="_blank" rel="noopener"&gt;VELOS&lt;/A&gt; 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, &lt;A href="https://www.f5.com/es_es/products/big-ip-services/rseries-adc-hardware-appliance" target="_blank" rel="noopener"&gt;rSeries&lt;/A&gt; ofrece un modelo más compacto y eficiente, ideal para despliegues donde el rendimiento por unidad, la latencia y la eficiencia operativa son clave.&lt;/P&gt;
&lt;P&gt;Y cuando la aplicación ya no vive en un solo data center, &lt;A href="https://www.f5.com/products/distributed-cloud-services/dns" target="_blank" rel="noopener"&gt;F5 Distributed Cloud Services&lt;/A&gt; extiende las capacidades del DNS a arquitecturas híbridas y multicloud, manteniendo:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Políticas consistentes&lt;/LI&gt;
&lt;LI&gt;Visibilidad unificada&lt;/LI&gt;
&lt;LI&gt;Control desde el edge hasta el backend&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;El punto no es dónde corre el DNS, sino que acompañe a la aplicación sin perder control, resiliencia ni observabilidad.&lt;/P&gt;
&lt;H2&gt;Seguridad integrada desde el primer paquete&lt;/H2&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Mitigar ataques sin introducir latencia adicional&lt;/LI&gt;
&lt;LI&gt;Aplicar políticas de forma consistente&lt;/LI&gt;
&lt;LI&gt;Mantener visibilidad unificada del tráfico&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Seguridad, rendimiento y disponibilidad no son capas separadas; son partes del mismo flujo.&lt;/P&gt;
&lt;H2&gt;En ocasiones olvidamos&lt;/H2&gt;
&lt;P&gt;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í.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;La pregunta no es si el DNS es crítico. La pregunta es si tu arquitectura está lista para tratarlo como tal.&lt;/P&gt;</description>
      <pubDate>Mon, 13 Apr 2026 18:23:30 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/dns-el-protocolo-que-nadie-ve-hasta-que-se-convierte-en-el/ta-p/346101</guid>
      <dc:creator>CLeonR_Chamo</dc:creator>
      <dc:date>2026-04-13T18:23:30Z</dc:date>
    </item>
    <item>
      <title>Context Cloak: Hiding PII from LLMs with F5 BIG-IP</title>
      <link>https://community.f5.com/t5/community-articles/context-cloak-hiding-pii-from-llms-with-f5-big-ip/ta-p/346062</link>
      <description>&lt;H2&gt;The Story&lt;/H2&gt;&lt;P&gt;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?&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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?&lt;/P&gt;&lt;P&gt;That's Context Cloak.&lt;/P&gt;&lt;H2&gt;The Problem&lt;/H2&gt;&lt;P&gt;An analyst asks an LLM: "Generate a financial report for John Doe, SSN 078-05-1120, account 4532-1189-0042."&lt;/P&gt;&lt;P&gt;The LLM now has real PII. Whether it's logged, cached, fine-tuned on, or exfiltrated -- that data is exposed. Traditional approaches fall short:&lt;/P&gt;&lt;DIV&gt;&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;Approach&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;What Happens&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;The Issue&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;Masking (****)&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;LLM can't see the data&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Can't reason about what it can't see&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;Tokenization (&amp;lt;&amp;lt;SSN:001&amp;gt;&amp;gt;)&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;LLM sees placeholders&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Works with larger models (14B+); smaller models may hallucinate&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;Do nothing&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;LLM sees real PII&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Security and compliance violation&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H2&gt;The Solution: Value Substitution&lt;/H2&gt;&lt;P&gt;Context Cloak takes a different approach -- substitute real PII with realistic fake values:&lt;/P&gt;&lt;P&gt;John Doe&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; Maria Garcia&lt;BR /&gt;078-05-1120&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; 523-50-6675&lt;BR /&gt;4532-1189-0042&amp;nbsp; --&amp;gt;&amp;nbsp; 7865-4412-3375&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;This is conceptually a substitution cipher -- every real value maps to a consistent fake within the session, and the mapping is reversed transparently.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;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:&lt;/P&gt;&lt;P&gt;Lawyer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; Gummy Bear&lt;BR /&gt;Bank&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; Cream Egg&lt;BR /&gt;Documents&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; Jelly Beans&lt;BR /&gt;Western Union&amp;nbsp; --&amp;gt;&amp;nbsp; A Giant Gummy Lizard&lt;/P&gt;&lt;P&gt;The scammer actually uses the code. He writes back:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;"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."&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Watch the talk: &lt;A href="https://www.ted.com/talks/james_veitch_this_is_what_happens_when_you_reply_to_spam_email?t=280" target="_blank" rel="noopener"&gt;https://www.ted.com/talks/james_veitch_this_is_what_happens_when_you_reply_to_spam_email?t=280&lt;/A&gt;&lt;/P&gt;&lt;H2&gt;Why BIG-IP?&lt;/H2&gt;&lt;P&gt;F5 BIG-IP was the natural candidate:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Already in the data path -- BIG-IP is a reverse proxy that organizations already deploy&lt;/LI&gt;&lt;LI&gt;MCP protocol support -- TMOS v21 added native MCP awareness via iRules&lt;/LI&gt;&lt;LI&gt;iRules -- Tcl-based traffic manipulation for real-time HTTP payload inspection and rewriting&lt;/LI&gt;&lt;LI&gt;Subtables -- in-memory key-value storage perfect for session-scoped cloaking maps&lt;/LI&gt;&lt;LI&gt;iAppLX -- deployable application packages with REST APIs and web UIs&lt;/LI&gt;&lt;LI&gt;Trust boundary -- BIG-IP is already the enforcement point for SSL, WAF, and access control&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;How Context Cloak Works&lt;/H2&gt;&lt;OL&gt;&lt;LI&gt;An analyst asks a question in Open WebUI&lt;/LI&gt;&lt;LI&gt;Open WebUI calls MCP tools through the BIG-IP MCP Virtual Server&lt;/LI&gt;&lt;LI&gt;The MCP server queries Postgres and returns real customer data (name, SSN, accounts, transactions)&lt;/LI&gt;&lt;LI&gt;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.&lt;/LI&gt;&lt;LI&gt;Open WebUI receives real data and composes a prompt&lt;/LI&gt;&lt;LI&gt;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&lt;/LI&gt;&lt;LI&gt;The LLM generates its response using fake data&lt;/LI&gt;&lt;LI&gt;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.&lt;/LI&gt;&lt;/OL&gt;&lt;H2&gt;Two Cloaking Modes&lt;/H2&gt;&lt;P&gt;Context Cloak supports two modes, configurable per PII field:&lt;/P&gt;&lt;H3&gt;Substitute Mode&lt;/H3&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;John Doe&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; Maria Garcia&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (name pool)&lt;BR /&gt;078-05-1120&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; 523-50-6675&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (digit shift +5)&lt;BR /&gt;4532-1189-0042&amp;nbsp; --&amp;gt;&amp;nbsp; 7865-4412-3375&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (digit shift +3)&lt;BR /&gt;john@email.com&amp;nbsp; --&amp;gt;&amp;nbsp; maria.g@example.net (derived)&lt;/P&gt;&lt;P&gt;Best for: fields the LLM needs to reason about naturally -- names in reports, account numbers in summaries.&lt;/P&gt;&lt;H3&gt;Tokenize Mode&lt;/H3&gt;&lt;P&gt;Replaces PII with structured placeholders:&lt;/P&gt;&lt;P&gt;078-05-1120&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; &amp;lt;&amp;lt;SSN:32.192.169.232:001&amp;gt;&amp;gt;&lt;BR /&gt;John Doe&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;gt;&amp;nbsp; &amp;lt;&amp;lt;name:32.192.169.232:001&amp;gt;&amp;gt;&lt;BR /&gt;4532-1189-0042&amp;nbsp; --&amp;gt;&amp;nbsp; &amp;lt;&amp;lt;digit_shift:32.192.169.232:001&amp;gt;&amp;gt;&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Both modes can be mixed per-field in the same request.&lt;/P&gt;&lt;H2&gt;The iAppLX Package&lt;/H2&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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:&lt;/P&gt;&lt;DIV&gt;&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;Field&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Aliases&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Mode&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Type / Label&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;full_name&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;customer_name&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Substitute&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Name Pool&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;ssn&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Tokenize&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;SSN&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;account_number&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Substitute&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Digit Shift&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;phone&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Substitute&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Phone&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;P&gt;email&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Substitute&lt;/P&gt;&lt;/td&gt;&lt;td&gt;&lt;P&gt;Email&lt;/P&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;H2&gt;Live Demo&lt;/H2&gt;&lt;P&gt;Enough theory -- here's what it looks like in practice.&lt;/P&gt;&lt;H3&gt;Step 1: Install the RPM&lt;/H3&gt;&lt;img /&gt;&lt;P&gt;Installing Context Cloak via BIG-IP Package Management LX&lt;/P&gt;&lt;H3&gt;Step 2: Configure and Deploy&lt;/H3&gt;&lt;img /&gt;&lt;P&gt;Context Cloak GUI -- MCP server, LLM endpoint, PII fields, one-click deploy&lt;/P&gt;&lt;img /&gt;&lt;P&gt;Deployment output showing session config and saved configuration&lt;/P&gt;&lt;H3&gt;Step 3: Verify Virtual Servers&lt;/H3&gt;&lt;img /&gt;&lt;P&gt;BIG-IP Local Traffic showing MCP VS and Inference VS created by Context Cloak&lt;/P&gt;&lt;H3&gt;Step 4: Baseline -- No Cloaking&lt;/H3&gt;&lt;img /&gt;&lt;P&gt;Without Context Cloak: real PII flows directly to the LLM in cleartext&lt;/P&gt;&lt;P&gt;This is the "before" picture. The LLM sees everything: real names, real SSNs, real account numbers.&lt;/P&gt;&lt;H3&gt;Demo 1: Substitute Mode -- SSN Lookup&lt;/H3&gt;&lt;P&gt;Prompt: "Show me the SSN number for John Doe. Just display the number."&lt;/P&gt;&lt;img /&gt;&lt;P&gt;Substitute mode -- Open WebUI + Context Cloak GUI showing all fields as Substitute&lt;/P&gt;&lt;P&gt;Result: User sees real SSN 078-05-1120. LLM saw a digit-shifted fake.&lt;/P&gt;&lt;H3&gt;Demo 2: Substitute Mode -- Account Lookup&lt;/H3&gt;&lt;P&gt;Prompt: "What accounts are associated to John Doe?"&lt;/P&gt;&lt;img /&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Left: Open WebUI with real data. Right: vLLM logs showing "Maria Garcia" with fake account numbers&lt;/P&gt;&lt;P&gt;What the LLM saw:&lt;/P&gt;&lt;P&gt;"customer_name": "Maria Garcia"&lt;BR /&gt;"account_number": "7865-4412-3375"&amp;nbsp; (checking)&lt;BR /&gt;"account_number": "7865-4412-3322"&amp;nbsp; (investment)&lt;BR /&gt;"account_number": "7865-4412-3376"&amp;nbsp; (savings)&lt;/P&gt;&lt;P&gt;What the user saw:&lt;/P&gt;&lt;P&gt;Customer: John Doe&lt;BR /&gt;Checking:&amp;nbsp;&amp;nbsp; 4532-1189-0042&amp;nbsp; --&amp;nbsp; $45,230.18&lt;BR /&gt;Investment: 4532-1189-0099&amp;nbsp; --&amp;nbsp; $312,500.00&lt;BR /&gt;Savings:&amp;nbsp;&amp;nbsp;&amp;nbsp; 4532-1189-0043&amp;nbsp; --&amp;nbsp; $128,750.00&lt;/P&gt;&lt;H3&gt;Switching to Tokenize Mode&lt;/H3&gt;&lt;img /&gt;&lt;P&gt;Changing PII fields from Substitute to Tokenize in the GUI&lt;/P&gt;&lt;H3&gt;Demo 3: Mixed Mode -- Tokenized SSN&lt;/H3&gt;&lt;P&gt;SSN set to Tokenize, name set to Substitute.&lt;/P&gt;&lt;P&gt;Prompt: "Show me the SSN number for Jane Smith. Just display the number."&lt;/P&gt;&lt;img /&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Mixed mode -- real SSN de-cloaked on left, &amp;lt;&amp;lt;SSN:...&amp;gt;&amp;gt; token visible in vLLM logs on right&lt;/P&gt;&lt;P&gt;What the LLM saw:&lt;/P&gt;&lt;P&gt;"customer_name": "Maria Thompson"&lt;BR /&gt;"ssn": "&amp;lt;&amp;lt;SSN:32.192.169.232:001&amp;gt;&amp;gt;"&lt;/P&gt;&lt;P&gt;What the user saw: Jane Smith, SSN 219-09-9999&lt;/P&gt;&lt;P&gt;Both modes operating on the same customer record, in the same request.&lt;/P&gt;&lt;H3&gt;Demo 4: Full Tokenize -- The Punchline&lt;/H3&gt;&lt;P&gt;ALL fields set to Tokenize mode.&lt;/P&gt;&lt;P&gt;Prompt: "Show me the SSN and account information for Carlos Rivera. Display all the numbers."&lt;/P&gt;&lt;img /&gt;&lt;P&gt;Full tokenize -- every PII field as a token, all de-cloaked on return&lt;/P&gt;&lt;P&gt;What the LLM saw -- every PII field was a token:&lt;/P&gt;&lt;P&gt;"full_name":&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;&amp;lt;name:32.192.169.232:001&amp;gt;&amp;gt;"&lt;BR /&gt;"ssn":&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;&amp;lt;SSN:32.192.169.232:002&amp;gt;&amp;gt;"&lt;BR /&gt;"phone":&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;&amp;lt;phone:32.192.169.232:002&amp;gt;&amp;gt;"&lt;BR /&gt;"email":&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;&amp;lt;email:32.192.169.232:001&amp;gt;&amp;gt;"&lt;BR /&gt;"account_number":&amp;nbsp; "&amp;lt;&amp;lt;digit_shift:32.192.169.232:002&amp;gt;&amp;gt;"&amp;nbsp; (checking)&lt;BR /&gt;"account_number":&amp;nbsp; "&amp;lt;&amp;lt;digit_shift:32.192.169.232:003&amp;gt;&amp;gt;"&amp;nbsp; (investment)&lt;BR /&gt;"account_number":&amp;nbsp; "&amp;lt;&amp;lt;digit_shift:32.192.169.232:004&amp;gt;&amp;gt;"&amp;nbsp; (savings)&lt;/P&gt;&lt;P&gt;What the user saw -- all real data restored:&lt;/P&gt;&lt;P&gt;Name:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Carlos Rivera&lt;BR /&gt;SSN:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 323-45-6789&lt;BR /&gt;Checking:&amp;nbsp;&amp;nbsp;&amp;nbsp; 6789-3345-0022&amp;nbsp; --&amp;nbsp; $89,120.45&lt;BR /&gt;Investment:&amp;nbsp; 6789-3345-0024&amp;nbsp; --&amp;nbsp; $890,000.00&lt;BR /&gt;Savings:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6789-3345-0023&amp;nbsp; --&amp;nbsp; $245,000.00&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;And here's the best part. Qwen's last line in the response:&lt;/P&gt;&lt;P&gt;"Please note that the actual numerical values for the SSN and account numbers are masked due to privacy concerns."&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;H2&gt;What's Next: F5 AI Guardrails Integration&lt;/H2&gt;&lt;P&gt;Context Cloak's tokenize mode is designed to complement F5 AI Guardrails. The &amp;lt;&amp;lt;TYPE:ID:SEQ&amp;gt;&amp;gt; format is intentionally distinctive -- if any token leaks through de-cloaking, a guardrails policy can catch it as a pattern match violation.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Other areas I'm exploring:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Hostname-based LLM routing -- BIG-IP as a model gateway with per-route cloaking policies&lt;/LI&gt;&lt;LI&gt;JSON profile integration -- native BIG-IP JSON DOM parsing instead of regex&lt;/LI&gt;&lt;LI&gt;Auto-discovery of MCP tool schemas for PII field detection&lt;/LI&gt;&lt;LI&gt;Centralized cloaking policy management across multiple BIG-IP instances&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;Try It Yourself&lt;/H2&gt;&lt;P&gt;The complete project is open source:&lt;/P&gt;&lt;P&gt;&lt;A href="https://github.com/j2rsolutions/f5_mcp_context_cloak" target="_blank" rel="noopener"&gt;https://github.com/j2rsolutions/f5_mcp_context_cloak&lt;/A&gt;&lt;/P&gt;&lt;P&gt;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).&lt;/P&gt;&lt;H2&gt;A Note on Production Readiness&lt;/H2&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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?&lt;/P&gt;&lt;P&gt;Let me know in the comments -- and if you want to contribute, PRs are welcome!&lt;/P&gt;&lt;H2&gt;Demo Environment&lt;/H2&gt;&lt;UL&gt;&lt;LI&gt;F5 BIG-IP VE v21.0.0.1 on AWS (m5.xlarge)&lt;/LI&gt;&lt;LI&gt;Qwen 2.5 14B Instruct AWQ on vLLM 0.8.5 (NVIDIA L4, 24GB VRAM)&lt;/LI&gt;&lt;LI&gt;MCP Server: FastMCP 1.26 + PostgreSQL 16 on Kubernetes (RKE2)&lt;/LI&gt;&lt;LI&gt;Open WebUI v0.8.10&lt;/LI&gt;&lt;LI&gt;Context Cloak iAppLX v0.2.0&lt;/LI&gt;&lt;/UL&gt;&lt;H1&gt;References&lt;/H1&gt;&lt;UL&gt;&lt;LI&gt;&lt;A href="https://community.f5.com/kb/technicalarticles/managing-model-context-protocol-in-irules---part-1/344321" target="_blank" rel="noopener"&gt;Managing MCP in iRules -- Part 1&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A href="https://community.f5.com/kb/technicalarticles/managing-model-context-protocol-in-irules---part-2/344421" target="_blank" rel="noopener"&gt;Managing MCP in iRules -- Part 2&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A href="https://community.f5.com/kb/technicalarticles/managing-model-context-protocol-in-irules---part-3/344423" target="_blank" rel="noopener"&gt;Managing MCP in iRules -- Part 3&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A href="https://spec.modelcontextprotocol.io/" target="_blank" rel="noopener"&gt;Model Context Protocol Specification&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A href="https://www.ted.com/talks/james_veitch_this_is_what_happens_when_you_reply_to_spam_email?t=280" target="_blank" rel="noopener"&gt;James Veitch: This is what happens when you reply to spam email (TED, skip to 4:40)&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;</description>
      <pubDate>Tue, 07 Apr 2026 20:06:35 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/context-cloak-hiding-pii-from-llms-with-f5-big-ip/ta-p/346062</guid>
      <dc:creator>jonathanj2r</dc:creator>
      <dc:date>2026-04-07T20:06:35Z</dc:date>
    </item>
    <item>
      <title>Embedding APM Protected Resources into Third-Party Sites</title>
      <link>https://community.f5.com/t5/community-articles/embedding-apm-protected-resources-into-third-party-sites/ta-p/345980</link>
      <description>&lt;P&gt;This is the story of a fight with CORS (Cross-Origin Resource Sharing) and the process of understanding how it actually works.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;Now I was forced to look into CORS for real and how to handle this beast.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In this setup the frontend virtual server - the one exposed to the users - has a single iRule responsible for:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Handling CORS preflight requests by returning the appropriate headers&lt;/LI&gt;
&lt;LI&gt;Injecting CORS headers into responses when the origin is allowed&lt;/LI&gt;
&lt;LI&gt;Forwarding all non-preflight requests to the APM virtual server&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This separation ensures full control over HTTP processing without being constrained by APM behavior.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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').&lt;/P&gt;
&lt;P&gt;One possible workaround was to use "clientless mode" by inserting the special header:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;HTTP::header insert "clientless-mode" 1&lt;/LI-CODE&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Below is a diagram illustrating the request flow and decision logic:&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;P&gt;A user browses the 3. party site which has links to our site. The Origin site.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;The browser retrieves the resources on our site.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;Forward the traffic to the inner APM VS.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;The iRule on the inner APM VS looks up in a datagroup and find no match and the authentication process is executed.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;The iRule on the inner APM VS looks up in a datagroup and find a match and disables APM.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;On the response from the backend we check if the origin was on the approved list.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;and if so we inject the CORS headers which will allow for the browser to show the content.&lt;/P&gt;
&lt;/LI&gt;
&lt;LI&gt;A user browses the site directly which will bypass any CORS logic.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Here is the iRule for the frontend VS:&lt;/P&gt;
&lt;LI-CODE lang="tcl"&gt;# =============================================================================
# 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") &amp;amp;&amp;amp; ([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 "" &amp;amp;&amp;amp; [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") &amp;amp;&amp;amp; ([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 &amp;amp;&amp;amp; $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"
    }
}&lt;/LI-CODE&gt;
&lt;P&gt;Here is the iRule for the inner APM VS:&lt;/P&gt;
&lt;LI-CODE lang="tcl"&gt;# =============================================================================
# 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 &amp;gt;= 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' -&amp;gt; disabling APM"
        } else {
            log local0. "debug: no public prefix matched -&amp;gt; APM remains enabled"
        }
    }

    if { $matched_public_prefix ne "" } {
        ACCESS::disable
        return
    }
}&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I can recommend spending time on&amp;nbsp;&lt;A class="lia-external-url" href="https://www.youtube.com/results?search_query=cors" target="_blank" rel="noopener"&gt;YouTube&lt;/A&gt; 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.&lt;/P&gt;
&lt;P&gt;I hope this example can help you fast-track pass all the headaches I struggled with.&lt;/P&gt;
&lt;P&gt;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.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 01 Apr 2026 13:21:47 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/embedding-apm-protected-resources-into-third-party-sites/ta-p/345980</guid>
      <dc:creator>lnxgeek</dc:creator>
      <dc:date>2026-04-01T13:21:47Z</dc:date>
    </item>
    <item>
      <title>Restsh is now available under an Open Source license!</title>
      <link>https://community.f5.com/t5/community-articles/restsh-is-now-available-under-an-open-source-license/ta-p/345860</link>
      <description>&lt;P&gt;I am proud to announce that the complete Restsh package is now released under the GNU General Public License version 3 (GPLv3) or later. There are no hidden restrictions — we are not withholding any enterprise features. Restsh will remain actively maintained and further developed by Axians IT Security.&lt;/P&gt;
&lt;H2&gt;What is Restsh?&lt;/H2&gt;
&lt;P&gt;Restsh is a lightweight Bash-based shell environment for working with REST APIs from the command line. It was built for interactive use, for automation in scripts, and for robust execution in CI/CD pipelines.&lt;/P&gt;
&lt;P&gt;Restsh is a core component of the &lt;A class="lia-external-url" href="https://www.axians.de/app/uploads/sites/72/2025/10/Axians-Automation-Framework_web.pdf" target="_blank"&gt;Axians Automation Framework&lt;/A&gt;, enabling automated management of F5 environments via GitLab CI/CD pipelines.&lt;/P&gt;
&lt;P&gt;Restsh does not replace your shell. Instead it exports a small set of environment variables and provides focused helper functions to call and parse REST APIs. Combine the power of Bash, curl, jq and Mustache templates to build reliable, repeatable workflows and automation.&lt;/P&gt;
&lt;H2&gt;What can I do with it?&lt;/H2&gt;
&lt;P&gt;Almost anything related to REST API automation. Restsh supports the common REST verbs and includes autocompletion for F5 and GitLab APIs. To simplify day-to-day tasks, it ships hundreds of small, focused helper scripts that wrap API endpoints — designed with the Unix principle in mind: do one thing well.&lt;/P&gt;
&lt;P&gt;These compact scripts can be piped together, filtered, or executed inside loops. For example, exporting all WAF policies from an F5 is a simple one-liner:&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;f5.asm.policy.list -r -f ".items[].fullPath" | XARGS f5.asm.policy.export&lt;/LI-CODE&gt;
&lt;H2&gt;Modular design&lt;/H2&gt;
&lt;P&gt;Restsh is modular and provides many functions to interact with the REST APIs of F5 BIG-IP, F5 OS-A and GitLab:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://axiansitsecurity.github.io/Restsh/restsh/modules/f5/overview.html" target="_blank" rel="noopener"&gt;F5 functions&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://axiansitsecurity.github.io/Restsh/restsh/modules/f5osa/index.html" target="_blank" rel="noopener"&gt;F5 OS-A functions&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://axiansitsecurity.github.io/Restsh/restsh/modules/gitlab/overview.html" target="_blank" rel="noopener"&gt;GitLab functions&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Do I have to sell my soul to get it?&lt;/H2&gt;
&lt;P&gt;Restsh is publicly available and can be downloaded from the official &lt;A class="lia-external-url" href="https://github.com/AxiansITSecurity/Restsh" target="_blank" rel="noopener"&gt;GitHub repository&lt;/A&gt;.&lt;/P&gt;
&lt;H2&gt;Support&lt;/H2&gt;
&lt;P&gt;This is the open-source, community-supported edition of Restsh. For enterprise-grade support and SLAs, Axians IT Security GmbH offers commercial support plans. Contact me to discuss options.&lt;/P&gt;
&lt;H2&gt;Documentation&lt;/H2&gt;
&lt;P&gt;Full documentation is available online: &lt;A class="lia-external-url" href="https://axiansitsecurity.github.io/Restsh/" target="_blank" rel="noopener"&gt;https://axiansitsecurity.github.io/Restsh/&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 25 Mar 2026 10:24:57 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/restsh-is-now-available-under-an-open-source-license/ta-p/345860</guid>
      <dc:creator>Juergen_Mang</dc:creator>
      <dc:date>2026-03-25T10:24:57Z</dc:date>
    </item>
    <item>
      <title>Update an ASM Policy Template via REST-API - the reverse engineering way</title>
      <link>https://community.f5.com/t5/community-articles/update-an-asm-policy-template-via-rest-api-the-reverse/ta-p/345461</link>
      <description>&lt;P&gt;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 "&lt;SPAN class="lia-text-color-13"&gt;The policy template ax-f5-waf-jump-start-template already exists.&lt;/SPAN&gt;".&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;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 "&lt;SPAN class="lia-text-color-13"&gt;Failed Required Fields: Must have at least 1 of (title, name, policyTemplate)&lt;/SPAN&gt;".&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="2"&gt;
&lt;LI&gt;There is also a valid field named "policyTemplate". My first thought: This could be a reference for an existing template to update.&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="3"&gt;
&lt;LI&gt;I added the "policyTemplate" parameter and assigned it an existing template id. The error message has changed again. It now throws "&lt;SPAN class="lia-text-color-13"&gt;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.&lt;/SPAN&gt;". An perl error that is readable and the perl file is in plain text available.&lt;/LI&gt;
&lt;/OL&gt;
&lt;OL start="4"&gt;
&lt;LI&gt;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.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Final the payload for people who do not want to do reverse engineering.&lt;/P&gt;
&lt;H2&gt;Update&lt;/H2&gt;
&lt;P&gt;POST following payload to &lt;SPAN class="lia-text-color-15"&gt;/mgmt/tm/asm/tasks/import-policy-template&lt;/SPAN&gt; to update an ASM policy template:&lt;/P&gt;
&lt;LI-CODE lang="json"&gt;{
    "filename": "&amp;lt;username&amp;gt;~&amp;lt;filename&amp;gt;",
    "policyTemplate": {
        "id": "ox91NUGR6mFXBDG4FnQSpQ"
    }
}&lt;/LI-CODE&gt;
&lt;H2&gt;Create&lt;/H2&gt;
&lt;P&gt;POST following payload &lt;SPAN class="lia-text-color-15"&gt;/mgmt/tm/asm/tasks/import-policy-template&lt;/SPAN&gt; to create an ASM policy template:&lt;/P&gt;
&lt;LI-CODE lang="json"&gt;{
    "name": "&amp;lt;name&amp;gt;",
    "filename": "&amp;lt;username&amp;gt;~&amp;lt;filename&amp;gt;"
}&lt;/LI-CODE&gt;
&lt;P&gt;&lt;STRONG&gt;Hint:&lt;/STRONG&gt; You must upload the template before to /var/config/rest/downloads/&amp;lt;username&amp;gt;~&amp;lt;filename&amp;gt;".&lt;/P&gt;
&lt;H2&gt;Conclusion&lt;/H2&gt;
&lt;P&gt;Documentation is sometimes overrated if you can read Perl. Missed I the API documentation for this endpoint&amp;nbsp;and it was just a exercise for me?&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 15:24:50 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/update-an-asm-policy-template-via-rest-api-the-reverse/ta-p/345461</guid>
      <dc:creator>Juergen_Mang</dc:creator>
      <dc:date>2026-02-17T15:24:50Z</dc:date>
    </item>
    <item>
      <title>F5 Container Ingress Services (CIS) and using k8s traffic policies to send traffic directly to pods</title>
      <link>https://community.f5.com/t5/community-articles/f5-container-ingress-services-cis-and-using-k8s-traffic-policies/ta-p/344846</link>
      <description>&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This article will take a look how you can use health monitors on the BIG-IP to solve the issue with constant AS3 REST-API pool member changes or when there is a sidecar service mesh like Istio (F5 has version called Aspen mesh of the istio mesh) or Linkerd mesh. I also have described some possible enchantments for CIS/AS3, Nginx Ingress Controller or Gateway Fabric that will be nice to have in the future.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Intro&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Install Nginx Ingress Open source and CIS&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt; F5 CIS without Ingress/Gateway&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt; F5 CIS with Ingress&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;F5 CIS with Gateway fabric&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;1. Intro&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;F5 CIS allows integration between F5 and k8s kubernetes or openshift clusters. F5 CIS has two modes and that are NodePort and ClusterIP and this is well documented at&amp;nbsp;&lt;A class="lia-external-url" href="https://clouddocs.f5.com/containers/latest/userguide/config-options.html" target="_blank" rel="noopener"&gt;https://clouddocs.f5.com/containers/latest/userguide/config-options.html&lt;/A&gt; . There is also a mode called auto that I prefer as based on k8s service type NodePort or ClusterIP it knows how to configure the pool members.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;CIS in ClusterIP mode generally is much better as you bypass the kube-proxy as send traffic directly to pods but there could be issues if k8s pods are constantly being scaled up or down as CIS uses AS3 REST-API to talk and configure the F5 BIG-IP. I also have seen some issues where a bug or a config error that is not well validated can bring the entire CIS to BIG-IP control channel down as you then see 422 errors in the F5 logs and on CIS logs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;By using NodePort and "externaltrafficpolicy: local" and if there is an ingress also "internaltrafficpolicy: local" you can also bypass the kubernetes proxy and send traffic directly to the pods and BIG-IP health monitoring will mark the nodes that don't have pods as down as the traffic policies prevent nodes that do not have the web application pods to send the traffic to other nodes.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;2..Install Nginx Ingress Open source and CIS&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As I already have the k8s version of nginx and F5 CIS I need 3 different classes of ingress. k8s nginx is end of life &lt;A class="lia-external-url" href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" target="_blank" rel="noopener"&gt;https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/&lt;/A&gt; , so my example also shows how you can have in parallel the two nginx versions the k8s nginx and F5 nginx.&lt;/P&gt;
&lt;P&gt;There is a new option to use The&amp;nbsp;&lt;EM&gt;Operator Lifecycle&lt;/EM&gt; Manager (OLM) that when installed will install the components and this is even better way than helm (you can install OLM with helm and this is even newer way to manage nginx ingress!) but I found it still in early stage for k8s while for Openshift it is much more advanced.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;I have installed Nginx in a daemonset not deployment and I will mention why later on and I have added a listener config for the F5 TransportServer even if later it is seen why at the moment it is not usable.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;helm install -f values.yaml ginx-ingress oci://ghcr.io/nginx/charts/nginx-ingress \
  --version 2.4.1 \
  --namespace f5-nginx \
  --set controller.kind=daemonset \
  --set controller.image.tag=5.3.1 \
  --set controller.ingressClass.name=nginx-nginxinc \
  --set controller.ingressClass.create=true \
  --set controller.ingressClass.setAsDefaultIngress=false 

cat  values.yaml
controller:
  enableCustomResources: true
  globalConfiguration:
    create: true
    spec:
      listeners:
        - name: nginx-tcp
          port: 88
          protocol: TCP


kubectl get ingressclasses
NAME             CONTROLLER                     PARAMETERS   AGE
f5               f5.com/cntr-ingress-svcs       &amp;lt;none&amp;gt;       8d
nginx            k8s.io/ingress-nginx           &amp;lt;none&amp;gt;       40d
nginx-nginxinc   nginx.org/ingress-controller   &amp;lt;none&amp;gt;       32s

niki@master-1:~$ kubectl get pods -o wide -n f5-nginx
NAME                             READY   STATUS    RESTARTS   AGE   IP              NODE       NOMINATED NODE   READINESS GATES
nginx-ingress-controller-2zbdr   1/1     Running   0          62s   10.10.133.234   worker-2   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-ingress-controller-rrrc9   1/1     Running   0          62s   10.10.226.87    worker-1   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
niki@master-1:~$&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The CIS config is shown below. I have used "pool_member_type" auto as this allows Cluster-IP or NodePort services to be used at the same time.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;helm install -f values.yaml f5-cis f5-stable/f5-bigip-ctlr

cat values.yaml
bigip_login_secret: f5-bigip-ctlr-login
rbac:
  create: true
serviceAccount:
  create: true
  name:
namespace: f5-cis
args:
  bigip_url: X.X.X.X
  bigip_partition: kubernetes
  log_level: DEBUG
  pool_member_type: auto
  insecure: true
  as3_validation: true
  custom_resource_mode: true
  log-as3-response: true
  load-balancer-class: f5
  manage-load-balancer-class-only: true
  namespaces: [default, test, linkerd-viz, ingress-nginx, f5-nginx]
    #  verify-interval: 35
image:
  user: f5networks
  repo: k8s-bigip-ctlr
  pullPolicy: Always
nodeSelector: {}
tolerations: []
livenessProbe: {}
readinessProbe: {}
resources: {}
version: latest&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;3. F5 CIS without Ingress/Gateway&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Without Ingress actually the F5's configuration is much simpler as you just need to create nodeport service and the VirtualServer CR. As you see below the health monitor marks the control node and the worker node that do not have pod from "hello-world-app-new-node" as shown in the F5 picture below.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;U&gt;&lt;EM&gt;Sending traffic without Ingresses or Gateways removes one extra hop and sub-optimal traffic patterns as when the Ingress or Gateway is in deployment mode for example there could be 20 nodes and only 2 ingress/gateway pods on 1 node each. Traffic will need to go to only those 2 nodes to enter the cluster.&lt;/EM&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;apiVersion: v1
kind: Service
metadata:
  name: hello-world-app-new-node
  labels:
    app: hello-world-app-new-node
spec:
  externalTrafficPolicy: Local
  ports:
    - name: http
      protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    app: hello-world-app-new
  type: NodePort
---
apiVersion: "cis.f5.com/v1"
kind: VirtualServer
metadata:
  name: vs-hello-new
  namespace: default
  labels:
    f5cr: "true"
spec:
  virtualServerAddress: "192.168.1.71"
  virtualServerHTTPPort: 80
  host: www.example.com
  hostGroup: "new"
  snat: auto
  pools:
  - monitor:
      interval: 10
      recv: ""
      send: "GET /"
      timeout: 31
      type: http
    path: /
    service: hello-world-app-new-node
    servicePort: 8080&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For Istio and Linkerd Integration an irule could be needed to send custom ALPN extensions to the backend pods that now have a sidecar. I suggest seeing my article at "the Medium" for more information see &lt;A href="https://medium.com/@nikoolayy1/connecting-kubernetes-k8s-cluster-to-external-router-using-bgp-with-calico-cni-and-nginx-ingress-2c45ebe493a1" target="_blank" rel="noopener"&gt;https://medium.com/@nikoolayy1/connecting-kubernetes-k8s-cluster-to-external-router-using-bgp-with-calico-cni-and-nginx-ingress-2c45ebe493a1&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Keep in mind that for the new options with Ambient mesh (sidecarless) the CIS without Ingress will not work as F5 does not speak &lt;EM&gt;HBONE&lt;/EM&gt; (or HTTP-Based Overlay Network Environment) protocol that is send in the HTTP Connect tunnel to inform the zTunnel (layer 3/4 proxy that starts or terminates the mtls) about the real source identity (SPIFFE and SPIRE) that may not be the same as the one in CN/SAN client SSL cert. &lt;U&gt;&lt;EM&gt;Maybe in the future there could be an option based on a CRD to provide the IP address of an external device like F5 and the zTunnel proxy to terminate the TLS/SSL (the waypoint layer 7 proxy usually Envoy is not needed in this case as F5 will do the HTTP processing) and send traffic to the pod but for now I see no way to make F5 work directly with Ambient mesh&lt;/EM&gt;. If the ztunnel takes the identity from the client cert CN/SAN F5 will not have to even speak HBONE.&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;4. F5 CIS with Ingress&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Why we may need an ingress just as a gateway into the k8s you may ask? Nowadays many times a service mesh like linkerd or istio or F5 aspen mesh is used and the pods talk to each other with mTLS handled by the sidecars and an Ingress as shown in &lt;A href="https://linkerd.io/2-edge/tasks/using-ingress/" target="_blank" rel="noopener"&gt;https://linkerd.io/2-edge/tasks/using-ingress/&lt;/A&gt; is an easy way for the client-side to be https while the server side to be the service mesh mtls, Even ambient mesh works with Ingresses as it captures traffic after them. &lt;U&gt;&lt;EM&gt;It is possible from my tests F5 to talk to a linkerd injected pods for example but it is hard!&amp;nbsp;&lt;/EM&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;I have described this in more detail at &lt;A href="https://medium.com/@nikoolayy1/connecting-kubernetes-k8s-cluster-to-external-router-using-bgp-with-calico-cni-and-nginx-ingress-2c45ebe493a1" target="_blank" rel="noopener"&gt;https://medium.com/@nikoolayy1/connecting-kubernetes-k8s-cluster-to-external-router-using-bgp-with-calico-cni-and-nginx-ingress-2c45ebe493a1&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Unfortunately when there is an ingress things as much more complex! F5 has Integration called "IngressLink" but as I recently found out it is when BIG-IP is only for Layer 3/4 Load Balancing and the Nginx Ingress Controller will actually do the decryption and AppProtect WAF will be on the Nginx as well&amp;nbsp; &lt;A class="lia-internal-link lia-internal-url lia-internal-url-content-type-forum" href="https://community.f5.com/discussions/technicalforum/f5-cis-ingresslink-attaching-waf-policy-on-the-big-ip-through-the-crd-/344301" target="_blank" rel="noopener" data-lia-auto-title="F5 CIS  IngressLink attaching WAF policy on the big-ip through the CRD ? | DevCentral" data-lia-auto-title-active="0"&gt;F5 CIS IngressLink attaching WAF policy on the big-ip through the CRD ? | DevCentral&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Wish F5 to make an integration like "IngressLink" but the reverse where each node will have nginx ingress as this can be done with demon set and not deployment on k8s and Nginx Ingress will be the layer 3/4, as the Nginx VirtualServer CRD support this and to just allow F5 in the k8s cluster.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Below is how currently this can be done. I have created a Transportserver but is not used as it does not at the momemt support the option "use-cluster-ip" set to true so that Nginx does not bypass the service and to go directly to the endpoints as this will cause nodes that have nginx ingress pod but no application pod to send the traffic to other nodes and we do not want that as add one more layer of load balancing latency and performance impact.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The gateway is shared as you can have a different gateway per namespace or shared like the Ingress.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt; 

apiVersion: v1
kind: Service
metadata:
  name: hello-world-app-new-cluster
  labels:
    app: hello-world-app-new-cluster
spec:
  internalTrafficPolicy: Local
  ports:
    - name: http
      protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    app: hello-world-app-new
  type: ClusterIP
---
apiVersion: k8s.nginx.org/v1
kind: TransportServer
metadata:
  name: nginx-tcp
  annotations:
    nginx.org/use-cluster-ip: "true"
spec:
  listener:
    name: nginx-tcp
    protocol: TCP
  upstreams:
  - name: nginx-tcp
    service: hello-world-app-new-cluster
    port: 8080
  action:
    pass: nginx-tcp
---
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: nginx-http
spec:
  host: "app.example.com"
  upstreams:
  - name: webapp
    service: hello-world-app-new-cluster
    port: 8080
    use-cluster-ip: true
  routes:
  - path: /
    action:
      pass: webapp&lt;/LI-CODE&gt;
&lt;P&gt;The second part of the configuration is to expose the Ingress to BIG-IP using CIS.&lt;/P&gt;
&lt;LI-CODE lang=""&gt;---
apiVersion: v1
kind: Service
metadata:
  name: f5-nginx-ingress-controller
  namespace: f5-nginx
  labels:
    app.kubernetes.io/name: nginx-ingress
spec:
  externalTrafficPolicy: Local
  type: NodePort
  selector:
    app.kubernetes.io/name: nginx-ingress
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: http
---
apiVersion: "cis.f5.com/v1"
kind: VirtualServer
metadata:
  name: vs-hello-ingress
  namespace: f5-nginx
  labels:
    f5cr: "true"
spec:
  virtualServerAddress: "192.168.1.81"
  virtualServerHTTPPort: 80
  snat: auto
  pools:
  - monitor:
      interval: 10
      recv: "200"
      send: "GET / HTTP/1.1\r\nHost:app.example.com\r\nConnection: close\r\n\r\n"
      timeout: 31
      type: http
    path: /
    service: f5-nginx-ingress-controller
    servicePort: 80&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Only the nodes that have a pod will answer the health monitor.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;U&gt;&lt;EM&gt;Hopefully F5 can make some Integration and CRD that makes this configuration simpler like the "IngressLink" and to add the option "use-cluster-ip" to the Transport server as Nginx does not need to see the HTTP traffic at all. This is on my wish list for this year 😁 Also if AS3 could reference existing group of nodes and just with different ports this could help CIS will need to push AS3 declaration of nodes just one time and then the different VirtualServers could reference it but with different ports and this will make the AS3 REST-API traffic much smaller.&lt;/EM&gt;&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;5. &lt;STRONG&gt;F5 CIS with Gateway fabric&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;This does not at the moment work as gateway-fabric unfortunately does not support "use-cluster-ip" option. &lt;/EM&gt;The idea is to deploy the gateway fabric in daemonset and to inject it with a sidecar or even without one this will work with ambient meshes. As k8s world is moving away from an Ingress this will be a good option.&lt;/P&gt;
&lt;P&gt;Gateway fabric natively supports TCP , UDP traffic and even TLS traffic that is not HTTPS and by exposing the gateway fabric with a Cluster-IP or Node-Port service then with different hostnames the Gateway fabric will select to correct route to send the traffic to!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric --create-namespace -n nginx-gateway -f values-gateway.yaml
cat values-gateway.yaml
nginx:
  # Run the data plane per-node
  kind: daemonSet

  # How the data plane gets exposed when you create a Gateway
  service:
    type: NodePort  # or NodePort

# (optional) if you’re using Gateway API experimental channel features:
  nginxGateway:
    gwAPIExperimentalFeatures:
      enable: true

&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shared-gw
  namespace: nginx-gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: wildcard-tls
    allowedRoutes:
      namespaces:
        from: ALL
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: app
spec:
  parentRefs:
  - name: shared-gw
    namespace: nginx-gateway
  hostnames:
  - app.example.com
  rules:
  - backendRefs:
    - name: app-svc
      port: 8080&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;F5 Nginx Fabric mesh is evolving really fast from what I see , so hopefully we see the features I mentioned soon and always you can open a github case. The documentation is at &lt;A class="lia-external-url" href="https://docs.nginx.com/nginx-gateway-fabric" target="_blank" rel="noopener"&gt;https://docs.nginx.com/nginx-gateway-fabric&lt;/A&gt;&amp;nbsp; and as this use k8s CRD the full options can be seen at &lt;A href="https://gateway-api.sigs.k8s.io/guides/tls/" target="_blank"&gt;TLS - Kubernetes Gateway API&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;6. Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;With the release of TMOS 21 F5 now supports much more health monitors and pool members, so this way of deploying CIS with NodePort services may offer benefits with TMOS 21.1 that will be the stable version as shown in &lt;A class="lia-external-url" href="https://techdocs.f5.com/en-us/bigip-21-0-0/big-ip-release-notes/big-ip-new-features.html" target="_blank" rel="noopener"&gt;https://techdocs.f5.com/en-us/bigip-21-0-0/big-ip-release-notes/big-ip-new-features.html&lt;/A&gt; With auto mode some services can still be directly exposed to BIG-IP as the CIS config changes are usually faster to remove a pool member pod than BIG-IP health monitors to mark a node as down.&lt;/P&gt;
&lt;P&gt;The new version of CIS that will be CIS advanced may take of the concerns of hitting a bug or not well validated configuration that could bring the control channel down and TMOS 21.1 may also handle AS3 config changes better with less cpu/memory issue, so there could be no need in the future of using trafficpolicies and NodePort mode and k8s services of this type.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;For ambient mesh my example with Ingress and Gateway seems the only option for direct communication at the moment.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;We will see what the future holds!&lt;/P&gt;</description>
      <pubDate>Mon, 05 Jan 2026 18:46:44 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/f5-container-ingress-services-cis-and-using-k8s-traffic-policies/ta-p/344846</guid>
      <dc:creator>Nikoolayy1</dc:creator>
      <dc:date>2026-01-05T18:46:44Z</dc:date>
    </item>
    <item>
      <title>F5 Distributed Cloud (XC) Custom Routes: Capabilities, Limitations, and Key Design Considerations</title>
      <link>https://community.f5.com/t5/community-articles/f5-distributed-cloud-xc-custom-routes-capabilities-limitations/ta-p/344691</link>
      <description>&lt;P&gt;This article explores how Custom Routes work in F5 Distributed Cloud (XC), why they differ architecturally from standard Load Balancer routes, and what to watch out for in real-world deployments, covering backend abstraction, Endpoint/Cluster dependencies, and critical TLS trust and Root CA requirements.&lt;/P&gt;</description>
      <pubDate>Wed, 17 Dec 2025 17:45:14 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/f5-distributed-cloud-xc-custom-routes-capabilities-limitations/ta-p/344691</guid>
      <dc:creator>Injeyan_Kostas</dc:creator>
      <dc:date>2025-12-17T17:45:14Z</dc:date>
    </item>
    <item>
      <title>decrypted tcpdump capture without using an iRule and without using tshark</title>
      <link>https://community.f5.com/t5/community-articles/decrypted-tcpdump-capture-without-using-an-irule-and-without/ta-p/344265</link>
      <description>&lt;P&gt;Last week I attended the Wireshark Foundation’s SharkFest in Warsaw. While there I raised a question with core developer &lt;STRONG&gt;Stig Bjørlykke&lt;/STRONG&gt; that’s been bothering me for some time: why go through all the hassle of using tshark when the needed data is already present in the pcap? There must be a smarter way to do this from within Wireshark — and there is.&lt;/P&gt;&lt;P&gt;Although the solution described in &lt;A href="https://my.f5.com/manage/s/article/K31793632" target="_blank" rel="noopener"&gt;https://my.f5.com/manage/s/article/K31793632&lt;/A&gt; and &lt;A href="https://community.f5.com/discussions/technicalforum/decrypted-tcpdump-capture-without-using-an-irule-using-tshark/317403" target="_blank" rel="noopener"&gt;Mohamed_Ahmed_Kansoh&lt;/A&gt;’s post are useful, and Jason Rahm’s script (&lt;A href="https://github.com/f5-rahm/pcap_utils/blob/main/TLSv1_3_captures.py" target="_blank" rel="noopener"&gt;https://github.com/f5-rahm/pcap_utils/blob/main/TLSv1_3_captures.py&lt;/A&gt;) is also helpful, I’m particularly pleased with the Lua-based approach Stig shared with me. I’m happy to pass it along.&lt;/P&gt;&lt;P&gt;The Lua script reads session keys from the capture and exports them to a Pre-Master Secret (PMS) log file, using the correct formatting — no tshark, sed, or other external tools required.&lt;/P&gt;&lt;P&gt;&lt;U&gt;&lt;STRONG&gt;How to use it:&lt;/STRONG&gt;&lt;/U&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Copy the Lua script into a file and place it in your Wireshark Personal Lua Plugins folder. (You can find that folder via Help → About Wireshark → Folders.)&lt;/LI&gt;&lt;LI&gt;Open the capture you want to decrypt. Make sure it was captured as described in K31793632.&lt;/LI&gt;&lt;LI&gt;Make sure the PMS file option is enabled and points to the desired file (Preferences → Protocols → TLS → Pre-Master Secret log filename).&lt;/LI&gt;&lt;LI&gt;Under the Tools menu you will find the Lua script. Run it — it will display which PMS file is being used and how many keys it found.&lt;/LI&gt;&lt;LI&gt;Click &lt;STRONG&gt;Export&lt;/STRONG&gt;, then &lt;STRONG&gt;Close&lt;/STRONG&gt;. That’s it — your capture should now be decrypted.&lt;/LI&gt;&lt;/OL&gt;&lt;LI-CODE lang="lua"&gt;-- F5 Keylog Export Wireshark Plugin
set_plugin_info({version = "1.0", author = "Stig Bjørlykke &amp;lt;stig@bjorlykke.org&amp;gt;"})

local keylog_field = Field.new("f5ethtrailer.tls.keylog")
local keylog_list = ""
local keylog_count = 0

local function export_keylog()
   local keylog_file = get_preference("tls.keylog_file");
   if keylog_file and keylog_file ~= "" then
      io.open(keylog_file, "w"):write(keylog_list):close()
      redissect_packets()
   end
end

local function f5_keylog_export()
   local tw = TextWindow.new("F5 Keylog Export")
   local tap = Listener.new("f5ethtrailer")

   tw:add_button("Export", function() export_keylog() end)
   tw:set_atclose(function () tap:remove() end)

   function tap.packet()
      for _, keylog in ipairs({keylog_field()}) do
         keylog_list = keylog_list .. keylog.value .. "\n"
         keylog_count = keylog_count + 1
      end
   end

   function tap.draw()
      local keylog_file = get_preference("tls.keylog_file");
      if keylog_file and keylog_file ~= "" then
         tw:set("TLS keylog file: " .. keylog_file .. "\n")
         tw:append("Press Export to write keys to file.\n\n")
         tw:append("Found " .. keylog_count .. " keylog entries.")
      else
         tw:set("No TLS keylog file specified in Preferences -&amp;gt; Protocols -&amp;gt; TLS\n\n")
      end
   end

   function tap.reset()
      keylog_list = ""
      keylog_count = 0
      tw:clear()
   end

   retap_packets()
end

register_menu("F5 Keylog Export", f5_keylog_export, MENU_TOOLS_UNSORTED)&lt;/LI-CODE&gt;</description>
      <pubDate>Thu, 13 Nov 2025 20:25:10 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/decrypted-tcpdump-capture-without-using-an-irule-and-without/ta-p/344265</guid>
      <dc:creator>Richard_</dc:creator>
      <dc:date>2025-11-13T20:25:10Z</dc:date>
    </item>
    <item>
      <title>The State Of HTTP/2 Full Proxy With F5 LTM</title>
      <link>https://community.f5.com/t5/community-articles/the-state-of-http-2-full-proxy-with-f5-ltm/ta-p/344157</link>
      <description>&lt;P&gt;In this article, I will attempt to summarize the known challenges of an HTTP/2 full proxy setup, point out possible solutions, and document known bugs and incompatibilities.&lt;/P&gt;
&lt;P&gt;Most major browsers had added HTTP/2 support by the end of 2015. However, I hardly ever see F5 LTM setups with HTTP/2 full proxy configured.&lt;/P&gt;</description>
      <pubDate>Wed, 11 Mar 2026 06:57:48 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/the-state-of-http-2-full-proxy-with-f5-ltm/ta-p/344157</guid>
      <dc:creator>Juergen_Mang</dc:creator>
      <dc:date>2026-03-11T06:57:48Z</dc:date>
    </item>
    <item>
      <title>XC Distributed Cloud and how to keep the Source IP from changing with customer edges(CE)!</title>
      <link>https://community.f5.com/t5/community-articles/xc-distributed-cloud-and-how-to-keep-the-source-ip-from-changing/ta-p/343722</link>
      <description>&lt;H5&gt;Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’.&lt;/H5&gt;
&lt;P&gt;Old applications sometimes do not accept a different IP address to be used by the clients during the session/connection. How can make certain the IP stays the same for a client?&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;The best will always be the application to stop tracking users based on something primitive as an ip address and sometimes the issue is in the Load Balancer or ADC after the XC RE and then if the persistence is based on source IP address on the ADC to be changed in case it is BIG-IP to Cookie or Universal or SSL session based if the Load Balancer is doing no decryption and it is just TCP/UDP layer .&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As an XC Regional Edge (RE) has many ip addresses it can connect to the origin servers adding a CE for the legacy apps is a good option to keep the source IP from changing for the same client HTTP requests during the session/transaction.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Before going through this article I recommend reading the links below:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://community.f5.com/kb/technicalarticles/f5-distributed-cloud-%E2%80%93-ce-high-availability-options-a-comparative-exploration/330189" target="_blank" rel="noopener"&gt;F5 Distributed Cloud – CE High Availability Options: A Comparative Exploration | DevCentral&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/concepts/f5-xc-customer-edge" target="_blank" rel="noopener"&gt;F5 Distributed Cloud - Customer Edge | F5 Distributed Cloud Technical Knowledge&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://docs.cloud.f5.com/docs-v2/multi-cloud-app-connect/how-to/app-nw/ha-apps-vs?searchQuery=virtual%20site" target="_blank" rel="noopener"&gt;Create Two Node HA Infrastructure for Load Balancing Using Virtual Sites with Customer Edges | F5 Distributed Cloud Technical Knowledge&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;RE to CE cluster of&amp;nbsp; 3 nodes&amp;nbsp;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The new SNAT prefix option under the origin pool allows no mater what CE connects to the origin pool the same IP address to be seen by the origin. Be careful as if you have more than a single IP with /32 then again the client may get each time different IP address. This may cause "inet port exhaustion " ( that is what it is called in F5BIG-IP) if there are too many connections to the origin server, so be careful as the SNAT option was added primary for that use case.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;There was an older option called "LB source IP persistence"&amp;nbsp; but better not use it as it was not so optimized and clean as this one.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;RE to 2 CE nodes in a virtual site&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The same option with SNAT pool is not allowed for a virtual site made of 2 standalone CE. For this we can use the ring hash algorithm.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Why this works? Well as &lt;SPAN data-qa="message_sender" data-stringify-type="replace" data-stringify-text="Kayvan FARZANEH"&gt;&lt;a href="javascript:void(0)" data-lia-user-mentions="" data-lia-user-uid="423655" data-lia-user-login="Kayvan" class="lia-mention lia-mention-user"&gt;Kayvan​&lt;/a&gt; explained to me the hashing of the origin is taking into account the CE name, so the same origin under 2 different CE will get the same ring hash and the same source IP address will be send to the same CE to access the Origin Server. This will not work for a single 3-node CE cluster as it all 3 nodes have the same name.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;I have seen 503 errors when ring hash is enabled under the HTTP LB so enable it only under the XC route object and the attached origin pool to it!&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;CE hosted HTTP LB with Advertise policy&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;In XC with CE you can do do HA with 3-cluster CE that can be layer2 HA based on VRRP and arp or Layer 3 persistence based bgp that can work 3 node CE cluster or 2 CE in a virtual site and it's control options like weight, as prepend or local preference options at the router level. For the Layer 2 I will just mention that you need to allow 224.0.0.8 for the VRRP if you are migrating from BIG-IP HA and that XC selects 1 CE to hold active IP that is seen in the XC logs and at the moment the selection for some reason can't be controlled.&lt;/P&gt;
&lt;P&gt;if a CE can't reach the origin servers in the origin pool it should stop advertising the HTTP LB IP address through BGP.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;For those options &lt;A href="https://community.f5.com/kb/technicalarticles/deploying-f5-distributed-cloud-xc-services-in-cisco-aci---layer-three-attached-d/324598" target="_blank" rel="noopener"&gt;Deploying F5 Distributed Cloud (XC) Services in Cisco ACI - Layer Three Attached Deployment&lt;/A&gt; is a great example as it shows ECMP BGP but with the BGP attributes you can easily select one CE to be active and processing connections, so that just one ip address is seen by the origin server.&lt;/P&gt;
&lt;P&gt;When a CE gets traffic by default it does prefer to send it&amp;nbsp; to the origin as by default "Local Preferred" is enabled under the origin pool.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;In the clouds like AWS/Azure just a cloud native LB&amp;nbsp; is added In front of the 3 CE cluster and the solution there is simple as to just modify the LB to have a persistence. Public Clouds do not support ARP, so forget about Layer 2 and play with the native LB that load balances between the CE 😉&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;UL&gt;
&lt;LI&gt;CE on Public Cloud (AWS/Azure/GCP)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;When deploying on a public cloud the CE can be deployed in two ways one is through the XC GUI and adding the AWS credentials but this way you have not a big freedom to be honest as you can't deploy 2 CE and make a virtual site out of them and add cloud LB in-front of them as it always will be 3-CE cluster with preconfigured cloud LB that will use all 3 LB! Using the newer "clickops" method is much better&amp;nbsp; &lt;A class="lia-external-url" href="https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-to/site-management/deploy-site-aws-clickops" target="_blank" rel="noopener"&gt;https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-to/site-management/deploy-site-aws-clickops&lt;/A&gt;&amp;nbsp; or using terraform but with manual mode and aws as a provider (not XC/volterra as it is the same as the XC GUI deployment) &lt;A class="lia-external-url" href="https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-to/site-management/deploy-aws-site-terraform" target="_blank" rel="noopener"&gt;https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-to/site-management/deploy-aws-site-terraform&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;This way you can make the Cloud LB to use just one CE or have some client Persistence or if traffic comes from RE to CE to implement the virtual site 2 CE node!&lt;/EM&gt; There is no Layer 2 ARP support as I mentioned in public cloud with 3-node cluster but there is NAT policy &lt;A class="lia-external-url" href="https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-tos/networking/nat-policies" target="_blank" rel="noopener"&gt;https://docs.cloud.f5.com/docs-v2/multi-cloud-network-connect/how-tos/networking/nat-policies&lt;/A&gt; but I haven't tried it myself to comment on it.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;Hope you enjoyed this article!&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 11 Nov 2025 17:08:34 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/xc-distributed-cloud-and-how-to-keep-the-source-ip-from-changing/ta-p/343722</guid>
      <dc:creator>Nikoolayy1</dc:creator>
      <dc:date>2025-11-11T17:08:34Z</dc:date>
    </item>
    <item>
      <title>Bypass Azure Login Page with OAuth login_hint on F5 BIG-IP APM</title>
      <link>https://community.f5.com/t5/community-articles/bypass-azure-login-page-with-oauth-login-hint-on-f5-big-ip-apm/ta-p/342922</link>
      <description>&lt;H2&gt;&lt;STRONG&gt;Overview&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;This article demonstrates how to enhance the user experience between F5 BIG-IP APM (OAuth Client) and Azure AD (OAuth Authorization Server) by implementing the login_hint parameter. This approach eliminates the need for users to enter their credentials twice, once on the F5 login page and again on the Azure login page.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Problem Statement&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;When users access applications protected by F5 APM that authenticate against Azure AD using OAuth/OIDC, they often encounter a suboptimal experience:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;User enters credentials on the F5 login page (often using their familiar sAMAccountName)&lt;/LI&gt;
&lt;LI&gt;F5 redirects to Azure AD for OAuth authentication&lt;/LI&gt;
&lt;LI&gt;Azure AD presents another login page asking for the same credentials (expecting UPN/email format)&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;This creates additional friction because users may not know their User Principal Name (UPN) and typically use their sAMAccountName for domain authentication. The login_hint parameter solves this by allowing F5 APM to translate the user's sAMAccountName to their UPN and pre-populate the Azure login page, effectively bypassing the redundant login prompt.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Alternative approach&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;The same functionality can be achieved using SAML, as described&amp;nbsp;&lt;A class="lia-internal-link lia-internal-url lia-internal-url-content-type-tkb" href="https://community.f5.com/kb/codeshare/bypass-azure-login-page-by-adding-a-login-hint-in-the-saml-request/288225" target="_blank" rel="noopener" data-lia-auto-title="here" data-lia-auto-title-active="0"&gt;here&lt;/A&gt;. However, I find the OAuth approach cleaner, as it eliminates the need for an iRule and also allows you to include the prompt parameter. This can be useful when you want to force authentication in Azure instead of relying on an existing session. See&amp;nbsp;&lt;A class="lia-external-url" href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow" target="_blank" rel="noopener"&gt;here&lt;/A&gt;for details.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Prerequisites&lt;/STRONG&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;F5 BIG-IP with APM&lt;/LI&gt;
&lt;LI&gt;Azure AD tenant with application registration&lt;/LI&gt;
&lt;LI&gt;Basic OAuth/OIDC configuration between F5 and Azure AD (as outlined in &lt;A class="lia-external-url" href="https://my.f5.com/manage/s/article/K53313351)" target="_blank" rel="noopener"&gt;https://my.f5.com/manage/s/article/K53313351)&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Implementation Steps&lt;/STRONG&gt;&lt;/H2&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 1: Complete Basic OAuth Setup&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Follow the standard F5 APM OAuth configuration with Azure AD:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Configure OAuth Server Object&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Navigate to &lt;STRONG&gt;Access ›› Federation ›› OAuth Client/Resource Server ›› OAuth Server&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Create a new OAuth server configuration for Azure AD&lt;/LI&gt;
&lt;LI&gt;Set the provider type to "Microsoft Identity Platform 2.0"&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Configure Access Profile&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Create an access profile with OAuth Client agent&lt;/LI&gt;
&lt;LI&gt;Configure authentication redirect and token requests&lt;/LI&gt;
&lt;/UL&gt;
&lt;/OL&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 2: Create Custom Authentication Redirect Request&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;The key modification involves creating a custom authentication redirect request that includes the login_hint parameter:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Navigate to Request Configuration&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Access ››&amp;nbsp; Federation ››&amp;nbsp; OAuth Client/Resource Server ››&amp;nbsp; Request&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Clone the Default Request&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Find the existing /Common/MSIdentityPlatform2.0AuthRedirectRequest&lt;/LI&gt;
&lt;LI&gt;Create a copy&lt;/LI&gt;
&lt;LI&gt;Name it something descriptive like MSIdentityPlatform2.0AuthRedirectRequest_LoginHint and the same parameters as /Common/MSIdentityPlatform2.0AuthRedirectRequest&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Add login_hint Parameter&lt;/STRONG&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Parameter Name&lt;/STRONG&gt;: login_hint&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Parameter Type&lt;/STRONG&gt;: custom&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Parameter Value&lt;/STRONG&gt;: %{session.ad.last.attr.userPrincipalName} or any other variable containing user’s UPN based on your environment and Authentication configuration&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Parameters&lt;/STRONG&gt; section, click &lt;STRONG&gt;Add&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Configure the new parameter:&lt;/LI&gt;
&lt;/UL&gt;
&lt;/OL&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 3: Update VPE OAuth Configuration&lt;/STRONG&gt;&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Access the Visual Policy Editor&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Go to &lt;STRONG&gt;Access ›› Profiles/Policies ›› Access Profiles (Per-Session Policies)&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Edit your access profile&lt;/LI&gt;
&lt;LI&gt;Click &lt;STRONG&gt;Edit&lt;/STRONG&gt; to open the VPE&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Modify OAuth Client Agent&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Locate the OAuth Client agent in your policy&lt;/LI&gt;
&lt;LI&gt;Edit the OAuth Client agent properties&lt;/LI&gt;
&lt;LI&gt;In the &lt;STRONG&gt;Authentication Redirect Request&lt;/STRONG&gt; dropdown, select your new custom request: MSIdentityPlatform2.0AuthRedirectRequest_LoginHint&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Apply Access Policy&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Click &lt;STRONG&gt;Apply Access Policy&lt;/STRONG&gt; to save changes&lt;/LI&gt;
&lt;/UL&gt;
&lt;/OL&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 4: Session Variable Configuration and UPN Translation&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;The key to successful login_hint implementation is ensuring the proper session variable is populated with a UPN-formatted email address. F5 APM can automatically translate sAMAccountName to UPN during AD authentication.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;H4&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;STRONG&gt;Complete Policy Flow Example&lt;/STRONG&gt;&lt;/H4&gt;
&lt;P&gt;Start&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;Logon Page (user enters: DOMAIN\john.doe or john.doe)&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;AD Auth (authenticate and populate session variables)&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;AD Query (to fetch user attributes)&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;OAuth Client (with custom redirect request including login_hint=john.doe@company.com)&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;Azure AD (pre-populated with UPN, bypasses login prompt)&lt;/P&gt;
&lt;P&gt;&amp;nbsp; ↓&lt;/P&gt;
&lt;P&gt;Application Access&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Troubleshooting&lt;/STRONG&gt;&lt;/H2&gt;
&lt;H3&gt;&lt;STRONG&gt;Common Issues&lt;/STRONG&gt;&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;login_hint Parameter Not Working&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Verify the session variable contains a valid email address&lt;/LI&gt;
&lt;LI&gt;Check that the custom request is selected in the OAuth Client agent&lt;/LI&gt;
&lt;LI&gt;Ensure the parameter type is set to "custom"&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Session Variable Empty or Wrong Format&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Verify AD authentication and query occurs before OAuth redirect&lt;/LI&gt;
&lt;LI&gt;Check AD attribute mapping configuration&lt;/LI&gt;
&lt;LI&gt;Confirm the userPrincipalName attribute exists in your AD schema&lt;/LI&gt;
&lt;LI&gt;Ensure domain suffix matches Azure AD tenant domain&lt;/LI&gt;
&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Azure AD Still Prompts for Login&lt;/STRONG&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Verify the email format matches Azure AD expectations&lt;/LI&gt;
&lt;LI&gt;Check Azure AD application configuration for login_hint support&lt;/LI&gt;
&lt;LI&gt;Ensure the user exists in the Azure AD tenant&lt;/LI&gt;
&lt;/UL&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Debugging Tips&lt;/STRONG&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;Enable APM debug logging: tmsh modify sys db log.apm.level value debug&lt;/LI&gt;
&lt;LI&gt;Use browser developer tools to inspect the OAuth redirect URL&lt;/LI&gt;
&lt;LI&gt;Verify session variables using Variable Assign agents in VPE&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Security Considerations&lt;/STRONG&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;The login_hint parameter only pre-populates the username field; users still must provide valid credentials&lt;/LI&gt;
&lt;LI&gt;This is a user experience enhancement, not a security bypass&lt;/LI&gt;
&lt;LI&gt;Ensure session variables don't contain sensitive information beyond the username/email&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;Implementing login_hint with OAuth on F5 BIG-IP APM significantly improves user experience by eliminating redundant login prompts. The key advantage is that F5 APM can seamlessly translate users' familiar sAMAccountName credentials to the UPN format required by Azure AD, allowing users to authenticate once with their domain credentials while Azure AD receives the properly formatted UPN for the login_hint.&lt;/P&gt;
&lt;P&gt;This approach maintains security while providing a seamless user experience, particularly beneficial in environments where:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Users are more familiar with their sAMAccountName than their UPN&lt;/LI&gt;
&lt;LI&gt;Organizations want to minimize authentication friction&lt;/LI&gt;
&lt;LI&gt;Azure itself is also federated to another IDP and you want transparent rederiction&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The solution leverages F5 APM's AD integration capabilities to handle the username format translation automatically, making it transparent to end users.&lt;/P&gt;</description>
      <pubDate>Mon, 11 Aug 2025 16:55:15 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/bypass-azure-login-page-with-oauth-login-hint-on-f5-big-ip-apm/ta-p/342922</guid>
      <dc:creator>Injeyan_Kostas</dc:creator>
      <dc:date>2025-08-11T16:55:15Z</dc:date>
    </item>
    <item>
      <title>Seamless Upgrade of F5 BIG-IP SSL Orchestrator (SSLO) L3 HA Cluster Without Downtime</title>
      <link>https://community.f5.com/t5/community-articles/seamless-upgrade-of-f5-big-ip-ssl-orchestrator-sslo-l3-ha/ta-p/342591</link>
      <description>&lt;H2&gt;Introduction&lt;/H2&gt;
&lt;P&gt;Upgrading the SSL Orchestrator (SSLO) in a high availability (HA) deployment can be a daunting task. especially in the BFSI sector, where even minimal downtime can impact mission-critical services such as net banking and mobile banking.&lt;/P&gt;
&lt;P&gt;While F5’s official knowledge article K64003555 provides detailed steps for SSLO upgrades, it typically involves a 30–45 minute service outage. This may not be acceptable in many production environments.&lt;/P&gt;
&lt;P&gt;This article provides a practical, tested method to upgrade SSLO (version 15.x.x and above) in an HA cluster without any service disruption.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Step-by-Step: Zero-Downtime Upgrade Procedure&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;1. Convert Full SSLO Topologies to LTM VIPs&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;SSLO topologies consist of tightly coupled components: virtual servers, access profiles, per-request policies, service chains, inspection services, and iRules. These objects are auto-generated and logically bound. Manual changes or upgrades can cause them to break or behave unpredictably.&lt;/P&gt;
&lt;P&gt;To avoid this, the first step is to recreate your SSLO traffic flow using native LTM virtual servers.&lt;/P&gt;
&lt;P&gt;Use duplicate IPs (or source IP-based routing) to create new LTM VIPs. Attach the corresponding SSLO access policies, profiles, and iRules to the LTM VIPs manually.&lt;/P&gt;
&lt;P&gt;Test traffic flow through these LTM VIPs to ensure they replicate the behavior of your existing SSLO topologies.&lt;/P&gt;
&lt;P&gt;Note: In my setup, I used existing VIP IPs by limiting the source address to my own public IP. I then changed source matching rules for controlled traffic diversion during testing.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG style="color: rgb(34, 34, 34); font-family: 'Neusa Next Pro Wide Bold', system-ui; font-size: 20px;"&gt;2. Detach SSLO Profiles/Policies from VIPs on the Standby Device&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Once the LTM VIPs are functional and validated, detach SSLO-related profiles from them on the &lt;STRONG&gt;standby&lt;/STRONG&gt; device before starting the upgrade.&lt;/P&gt;
&lt;P&gt;Use the following example command:&lt;/P&gt;
&lt;P&gt;modify ltm virtual myapp.example.com \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; per-flow-request-access-policy none \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; profiles delete { sslo_myapp_topology.app/sslo_myapp_topology_accessProfile } \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; rules none&lt;/P&gt;
&lt;P&gt;Once detached, the device will act as a standard LTM unit—safe for upgrades without SSLO-related interruptions.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;3. Upgrade Standby Device to New TMOS Version&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Continue to upgrade the standby SSLO device to your desired TMOS version (e.g., from 16.x to 17.x). Follow the standard BIG-IP upgrade process:&lt;/P&gt;
&lt;P&gt;🔗 &lt;A href="https://my.f5.com/manage/s/article/K84554955" target="_blank" rel="noopener"&gt;F5 KB: Upgrade Process&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="lia-text-color-8"&gt;⚠️ &lt;STRONG&gt;Important:&lt;/STRONG&gt; Do &lt;STRONG&gt;not&lt;/STRONG&gt; access &lt;STRONG&gt;SSLO → Configuration&lt;/STRONG&gt; in the GUI before both devices are upgraded. This may trigger an SSLO RPM package upgrade prematurely.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;4. Validate Post-Upgrade Configuration&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;After the upgrade:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Confirm all access policies and profiles are present via &lt;STRONG&gt;Access → Profiles / Policies&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Verify that the LTM VIPs created earlier are intact and function as expected.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG style="color: rgb(34, 34, 34);"&gt;5. Re-Attach SSLO Policies and Profiles&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Once validation is complete, re-attach the access profiles, policies, and rules to the respective LTM VIPs. You can automate this using TMSH commands, like the example below:&lt;/P&gt;
&lt;P&gt;modify ltm virtual myapp.example.com \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; per-flow-request-access-policy ssloP_IDS_IPS_WAF.app/ssloP_IDS_IPS_WAF_per_req_policy \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; profiles add { sslo_appname.app/sslo_appname_accessProfile { } } \&lt;/P&gt;
&lt;P&gt;&amp;nbsp; rules { sslo_appname.app/sslo_appname-min_in_t ssloS_WAF.app/ssloS_WAF-port_remap }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;6. Failover to the Upgraded Device&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Perform a manual failover to the upgraded standby device. Monitor application behavior and test traffic flow thoroughly.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG style="color: rgb(34, 34, 34);"&gt;7. Repeat for the Second Device&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Now, repeat &lt;STRONG&gt;Steps 2–6&lt;/STRONG&gt; for the second (now standby) SSLO device. This will complete the upgrade process for the full HA pair.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG style="color: rgb(34, 34, 34);"&gt;8. Trigger SSLO GUI Upgrade&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Once both devices are upgraded and traffic is tested from both nodes, access &lt;STRONG&gt;SSLO → Configuration&lt;/STRONG&gt; via GUI. This will initiate the SSLO RPM package upgrade safely.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG style="color: rgb(34, 34, 34);"&gt;9. Monitor Upgrade Status&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;Use the following REST API calls for monitoring upgrade progress and sync status:&lt;/P&gt;
&lt;P&gt;restcurl -u admin: shared/gossip | grep status&lt;/P&gt;
&lt;P&gt;restcurl -u admin: tm/cm/device&lt;/P&gt;
&lt;P&gt;restcurl -u admin: tm/cm/device | jq '.items[] | {devicename: .name, ConfigSyncIP: .configsyncIp, UnicastAddress: .unicastAddress}'&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;References&lt;/STRONG&gt;&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;🔗 &lt;A href="https://my.f5.com/manage/s/article/K64003555" target="_blank" rel="noopener"&gt;K64003555 – SSL Orchestrator Upgrade Process&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;🔗 &lt;A href="https://my.f5.com/manage/s/article/K84554955" target="_blank" rel="noopener"&gt;K84554955 – BIG-IP General Upgrade Steps&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/H2&gt;
&lt;P&gt;Upgrading a F5 SSLO HA cluster without downtime is possible with proper planning and by converting topologies into LTM-native VIPs. This approach ensures continuous traffic flow and minimizes the risk associated with auto-generated SSLO objects during upgrades.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 06 Aug 2025 12:00:00 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/seamless-upgrade-of-f5-big-ip-ssl-orchestrator-sslo-l3-ha/ta-p/342591</guid>
      <dc:creator>Vidyadhar_Patil</dc:creator>
      <dc:date>2025-08-06T12:00:00Z</dc:date>
    </item>
    <item>
      <title>F5 XC Distributed Cloud DNS GSLB implementing Split-DNS</title>
      <link>https://community.f5.com/t5/community-articles/f5-xc-distributed-cloud-dns-gslb-implementing-split-dns/ta-p/342091</link>
      <description>&lt;P&gt;Have you ever wondered how to achieve Bind-like 'VIEW' behavior with F5 XC Load Balancer where depending on the customer’s IP, different DNS responses are returned? Well wonder no more!&lt;/P&gt;</description>
      <pubDate>Mon, 18 Aug 2025 19:47:54 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/f5-xc-distributed-cloud-dns-gslb-implementing-split-dns/ta-p/342091</guid>
      <dc:creator>Nikoolayy1</dc:creator>
      <dc:date>2025-08-18T19:47:54Z</dc:date>
    </item>
    <item>
      <title>How to achieve hiding internal URLs and HTTP dynamic redirection with F5 XC HTTP Load Balancer</title>
      <link>https://community.f5.com/t5/community-articles/how-to-achieve-hiding-internal-urls-and-http-dynamic-redirection/ta-p/342126</link>
      <description>&lt;P&gt;This is a comprehensive list of the XC options to change the Host or URL values in the requests and to trigger dynamic redirections.&lt;/P&gt;</description>
      <pubDate>Mon, 15 Sep 2025 15:29:27 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/how-to-achieve-hiding-internal-urls-and-http-dynamic-redirection/ta-p/342126</guid>
      <dc:creator>Nikoolayy1</dc:creator>
      <dc:date>2025-09-15T15:29:27Z</dc:date>
    </item>
    <item>
      <title>Hey Claude, can you write iRules?</title>
      <link>https://community.f5.com/t5/community-articles/hey-claude-can-you-write-irules/ta-p/340881</link>
      <description>&lt;img /&gt;
&lt;P&gt;I asked Claude to write 5 different iRules.&lt;/P&gt;</description>
      <pubDate>Thu, 17 Apr 2025 15:54:25 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/hey-claude-can-you-write-irules/ta-p/340881</guid>
      <dc:creator>Daniel_Wolf</dc:creator>
      <dc:date>2025-04-17T15:54:25Z</dc:date>
    </item>
    <item>
      <title>Sharing User Credentials Between SAML IDP and SP Policies in F5 APM</title>
      <link>https://community.f5.com/t5/community-articles/sharing-user-credentials-between-saml-idp-and-sp-policies-in-f5/ta-p/340677</link>
      <description>&lt;P&gt;In F5 APM environments with one SAML Identity Provider (IDP) and multiple Service Providers (SPs), SP policies may need access to user credentials (like passwords) for SSO mechanisms such as NTLM or RDP. Since SAML doesn't transmit passwords, this solution enables secure credential sharing by storing the password in a custom session variable on the IDP side and passing the IDP session ID to the SP as a SAML attribute. An iRule on the SP side then uses this session ID to retrieve the password from the IDP session, making it available for SSO credential mapping. This approach maintains security by avoiding password exposure in the SAML assertion and leverages internal session sharing between policies.&lt;/P&gt;</description>
      <pubDate>Tue, 08 Apr 2025 19:19:21 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/sharing-user-credentials-between-saml-idp-and-sp-policies-in-f5/ta-p/340677</guid>
      <dc:creator>Injeyan_Kostas</dc:creator>
      <dc:date>2025-04-08T19:19:21Z</dc:date>
    </item>
    <item>
      <title>Log Source IPs for Traffic Sent to a BIG-IP Virtual Address Port it is not Listening on</title>
      <link>https://community.f5.com/t5/community-articles/log-source-ips-for-traffic-sent-to-a-big-ip-virtual-address-port/ta-p/340522</link>
      <description>&lt;P class="lia-indent-padding-left-30px"&gt;&lt;U&gt;&lt;STRONG&gt;Warning&lt;/STRONG&gt;&lt;/U&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Before using this iRule, please assess an potential impacts to your BIG-IP based on it's current performance as iRules can negatively impact the BIG-IP and its traffic management processing.&lt;/LI&gt;&lt;/UL&gt;&lt;P class="lia-indent-padding-left-30px"&gt;&lt;U&gt;&lt;STRONG&gt;Related Log Message&lt;/STRONG&gt;&lt;/U&gt;&lt;/P&gt;&lt;LI-CODE lang=""&gt;011e0001	Limiting closed port RST response from 501 to 500 packets/sec for traffic-group /Common/traffic-group-1&lt;/LI-CODE&gt;&lt;P class="lia-indent-padding-left-30px"&gt;&lt;U&gt;&lt;STRONG&gt;Create iRule&lt;/STRONG&gt;&lt;/U&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Create an iRule by navigating to Local Traffic &amp;gt; iRules &amp;gt; iRule List &amp;gt; Create&lt;/LI&gt;&lt;LI&gt;Name: log_source_ip_to_closed_ports&lt;/LI&gt;&lt;LI&gt;Paste the code below into the “Definition” box.&lt;/LI&gt;&lt;LI&gt;Click Finished, and sync to peer if needed/desired.&lt;/LI&gt;&lt;/OL&gt;&lt;LI-CODE lang="tcl"&gt;when CLIENT_ACCEPTED { set client_ip [IP::client_addr] # source IP variable set virtual_server_ip [IP::local_addr] # destination IP a variable set virtual_server_port [TCP::local_port] # destination port variable # Log information to /var/log/ltm log local0. "Connection attempted to unsupported port: $client_ip to destination $virtual_server_ip:$virtual_server_port" }&lt;/LI-CODE&gt;&lt;P&gt;&lt;U&gt;&lt;STRONG&gt;Create Reject Virtual Server&lt;/STRONG&gt;&lt;/U&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Create a new virtual server by navigating to Local Traffic &amp;gt; Virtual Servers &amp;gt; Virtual Servers List &amp;gt; Create&lt;/LI&gt;&lt;LI&gt;Name: reject_vs&lt;/LI&gt;&lt;LI&gt;Type: reject&lt;/LI&gt;&lt;LI&gt;Source Address: 0.0.0.0/0&lt;/LI&gt;&lt;LI&gt;Dest. Address: 0.0.0.0/0&lt;/LI&gt;&lt;LI&gt;Service Port: 0 *All Ports&lt;/LI&gt;&lt;LI&gt;Protocol: * All Protocols&lt;/LI&gt;&lt;LI&gt;Optionally specifics the VLANs and Tunnels the virtual server should listen on.&lt;/LI&gt;&lt;/OL&gt;&lt;LI-CODE lang=""&gt;ltm virtual reject_vs { destination 0.0.0.0:0 mask any profiles { fastL4 { } } reject rules { new_irule } serverssl-use-sni disabled source 0.0.0.0/0 translate-address enabled translate-port enabled vlans { External } vlans-enabled vs-index 26 }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 31 Mar 2025 17:15:15 GMT</pubDate>
      <guid>https://community.f5.com/t5/community-articles/log-source-ips-for-traffic-sent-to-a-big-ip-virtual-address-port/ta-p/340522</guid>
      <dc:creator>PhillyPDXMike</dc:creator>
      <dc:date>2025-03-31T17:15:15Z</dc:date>
    </item>
  </channel>
</rss>

