Technical Articles
F5 SMEs share good practice.
Showing results for 
Search instead for 
Did you mean: 
F5 Employee
F5 Employee

The Content Delivery Network (CDN) market has become increasingly commoditized. Many providers have augmented their CDN capabilities with WAFs/WAAPs, DNS, load balancing, edge compute, and networking. Managing all these solutions together creates a web of operational complexity, which can be confusing.

F5’s synergistic bundling of CDN with Web Application and API Protection (WAAP) benefits those looking for simplicity and ease of use. It provides a way around the complications and silos that many resource-strapped organizations face with their IT systems.

This bundling also signifies how CDN has become a commodity product often not purchased independently anymore. This trend is encouraging many competitors to evolve their capabilities to include edge computing – a space where F5 has gained considerable experience in recent years.

F5 is rapidly catching up to other providers’ CDNs. F5’s experience and leadership building the world’s best-of-breed Application Delivery Controller (ADC), the BIG-IP load balancer, put it in a unique position to offer the best application delivery and security services directly at the edge with many of its CDN points of presence. With robust regional edge capabilities and a global network, F5 has entered the CDN space with a complementary offering to an already compelling suite of features. This includes the ability to run microservices and Kubernetes workloads anywhere, with a complete range of services to support app infrastructure deployment, scale, and lifecycle management all within a single management console.


With advancements made in the application security space at F5, WAAP capabilities are directly integrated into the Distributed Cloud Platform to protect both web apps and APIs. Features include (yet not limited to):

  • Web Application Firewall: Signature + Behavioral WAF functionality
  • Bot Defense: Detect client signals, determining if clients are human or automated
  • DDoS Mitigation: Fully managed by F5
  • API Security: Continuous inspection and detection of shadow APIs


Combining the Distributed Cloud WAAP with CDN as a form of service chaining is a straightforward process. This not only gives you the best security protection for web apps and APIs, but also positions apps regionally to deliver them with low latency and minimal compute per request.

In the following solution, we’ve combined Distributed Cloud WAAP and CDN to globally deliver an app protected by a WAF policy from the closest regional point of presence to the user. Follow along as I demonstrate how to configure the basic elements.




Log in to the Distributed Cloud Console and navigate to the DNS Management service. Decide if you want Distributed Cloud to manage the DNS zone as a Primary DNS server or if you’d rather delegate the fully qualified domain name (FQDN) for your app to Distributed Cloud with a CNAME. While using Delegation or Managed DNS is optional, doing so makes it possible for Distributed Cloud to automatically create and manage the SSL certificates needed to securely publish your app.

CDN-WAAP-Step2 DNS.png

Next, in Distributed Cloud Console, navigate to the Web App and API Protection service, then go to App Firewall, then Add App Firewall. This is where you’ll create the security policy that we’ll later connect our HTTP LB. Let’s use the following basic WAF policy in YAML format, you can paste it directly in to the Console by changing the configuration view to JSON and then changing the format to YAML. Note: This uses the namespace “waap-cdn”, change this to match your individual tenant’s configuration.

  name: buytime-waf
  namespace: waap-cdn
  labels: {}
  annotations: {}
  disable: false
  blocking: {}
      default_attack_type_settings: {}
      high_medium_low_accuracy_signatures: {}
    enable_suppression: {}
    enable_threat_campaigns: {}
    default_violation_settings: {}
    malicious_bot_action: BLOCK
    suspicious_bot_action: REPORT
    good_bot_action: REPORT
  allow_all_response_codes: {}
  default_anonymization: {}
  use_default_blocking_page: {}

With the WAF policy saved, it’s time to configure the origin server. Navigate to Load Balancers > Origin Pools, then Add Origin Pool. The following YAML uses a FQDN DNS name reach the app server. Using an IP address for the server is possible as well.

  name: buytime-pool
  namespace: waap-cdn
  labels: {}
  annotations: {}
  disable: false
    - public_name:
      labels: {}
  no_tls: {}
  port: 80
  same_as_endpoint_port: {}
  healthcheck: []
  loadbalancer_algorithm: LB_OVERRIDE
  endpoint_selection: LOCAL_PREFERRED

With the supporting WAF and Origin Pool resources configured, it’s time to create the HTTP Load Balancer. Navigate to Load Balancers > HTTP Load Balancers, then create a new one. Use the following YAML to create the LB and use both resources created above.

  name: buytime-online
  namespace: waap-cdn
  labels: {}
  annotations: {}
  disable: false
    http_redirect: true
    add_hsts: true
    port: 443
      default_security: {}
    no_mtls: {}
    default_header: {}
    enable_path_normalize: {}
    non_default_loadbalancer: {}
      default_header_transformation: {}
  advertise_on_public_default_vip: {}
    - pool:
        tenant: your-tenant-uid
        namespace: waap-cdn
        name: buytime-pool
        kind: origin_pool
      weight: 1
      priority: 1
      endpoint_subsets: {}
  routes: []
    tenant: your-tenant-uid
    namespace: waap-cdn
    name: buytime-waf
    kind: app_firewall
  add_location: true
  no_challenge: {}
  user_id_client_ip: {}
  disable_rate_limit: {}
  waf_exclusion_rules: []
  data_guard_rules: []
  blocked_clients: []
  trusted_clients: []
  ddos_mitigation_rules: []
  service_policies_from_namespace: {}
  round_robin: {}
  disable_trust_client_ip_headers: {}
  disable_ddos_detection: {}
  disable_malicious_user_detection: {}
  disable_api_discovery: {}
  disable_bot_defense: {}
  disable_api_definition: {}
  disable_ip_reputation: {}
  disable_client_side_defense: {}
resource_version: "517528014"

With the HTTP LB successfully deployed, check that its status is ready on the status page.


You can verify the LB is working by sending a basic request using the command line tool, curl. Confirm that the value of the HTTP header “Server” is “volt-adc”.

da.potter@lab ~ % curl -I
HTTP/2 200 
date: Mon, 17 Oct 2022 23:23:55 GMT
content-type: text/html; charset=UTF-8
content-length: 2200
vary: Origin
access-control-allow-credentials: true
accept-ranges: bytes
cache-control: public, max-age=0
last-modified: Wed, 24 Feb 2021 11:06:36 GMT
etag: W/"898-177d3b82260"
x-envoy-upstream-service-time: 136
strict-transport-security: max-age=31536000
set-cookie: 1f945=1666049035840-557942247; Path=/;; Expires=Sun, 17 Oct 2032 23:23:55 GMT
set-cookie: 1f9403=viJrSNaAp766P6p6EKZK7nyhofjXCVawnskkzsrMBUZIoNQOEUqXFkyymBAGlYPNQXOUBOOYKFfs0ne+fKAT/ozN5PM4S5hmAIiHQ7JAh48P4AP47wwPqdvC22MSsSejQ0upD9oEhkQEeTG1Iro1N9sLh+w+CtFS7WiXmmJFV9FAl3E2; path=/
x-volterra-location: wes-sea
server: volt-adc

Now it’s time to configure the CDN Distribution and service chain it to the WAAP HTTP LB. Navigate to Content Delivery Network > Distributions, then Add Distribution. The following YAML creates a basic CDN configuration that uses the WAAP HTTP LB above.

  name: buytime-cdn
  namespace: waap-cdn
  labels: {}
  annotations: {}
  disable: false
    http_redirect: true
    add_hsts: true
      tls_12_plus: {}
  add_location: false
      cache_ttl_override: 1m
      use_host_header_as_sni: {}
        default_security: {}
      volterra_trusted_ca: {}
      no_mtls: {}
      - public_name:
    follow_origin_redirect: false
resource_version: "518473853"

After saving the configuration, verify that the status is “Active”. You can confirm the CDN deployment status for each individual region by going to the distribution’s action button “Show Global Status”, and scrolling down to each region to see that each region’s “site_status.status” value is “DEPLOYMENT_STATUS_DEPLOYED”.



With the CDN Distribution successfully deployed, it’s possible to confirm with the following basic request using curl. Take note of the two HTTP headers “Server” and “x-cache-status”. The Server value will now be “volt-cdn”, and the x-cache-status will be “MISS” for the first request.

da.potter@lab ~ % curl -I      
HTTP/2 200 
date: Mon, 17 Oct 2022 23:24:04 GMT
content-type: text/html; charset=UTF-8
content-length: 2200
vary: Origin
access-control-allow-credentials: true
accept-ranges: bytes
cache-control: public, max-age=0
last-modified: Wed, 24 Feb 2021 11:06:36 GMT
etag: W/"898-177d3b82260"
x-envoy-upstream-service-time: 63
strict-transport-security: max-age=31536000
set-cookie: 1f945=1666049044863-471593352; Path=/;; Expires=Sun, 17 Oct 2032 23:24:04 GMT
set-cookie: 1f9403=aCNN1JINHqvWPwkVT5OH3c+OIl6+Ve9Xkjx/zfWxz5AaG24IkeYqZ+y6tQqE9CiFkNk+cnU7NP0EYtgGnxV0dLzuo3yHRi3dzVLT7PEUHpYA2YSXbHY6yTijHbj/rSafchaEEnzegqngS4dBwfe56pBZt52MMWsUU9x3P4yMzeeonxcr; path=/
x-volterra-location: dal3-dal
server: volt-cdn
x-cache-status: MISS
strict-transport-security: max-age=31536000

To see a security violation detected by the WAF in real-time, you can simulate a simple XSS exploit with the following curl:

da.potter@lab ~ % curl -Gv "<script>('alert:XSS')</script>"
*   Trying x.x.x.x:443...
* Connected to (x.x.x.x) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject:
*  start date: Oct 14 23:51:02 2022 GMT
*  expire date: Jan 12 23:51:01 2023 GMT
*  subjectAltName: host "" matched cert's ""
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x14f010000)
> GET /?<script>('alert:XSS')</script> HTTP/2
> Host:
> user-agent: curl/7.79.1
> accept: */*
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< date: Sat, 22 Oct 2022 01:04:39 GMT
< content-type: text/html; charset=UTF-8
< content-length: 269
< cache-control: no-cache
< pragma: no-cache
< set-cookie: 1f945=1666400679155-452898837; Path=/;; Expires=Fri, 22 Oct 2032 01:04:39 GMT
< set-cookie: 1f9403=/1b+W13c7xNShbbe6zE3KKUDNPCGbxRMVhI64uZny+HFXxpkJMsCKmDWaihBD4KWm82reTlVsS8MumTYQW6ktFQqXeFvrMDFMSKdNSAbVT+IqQfSuVfVRfrtgRkvgzbDEX9TUIhp3xJV3R1jdbUuAAaj9Dhgdsven8FlCaADENYuIlBE; path=/
< x-volterra-location: dal3-dal
< server: volt-cdn
< x-cache-status: MISS
< strict-transport-security: max-age=31536000
<html><head><title>Request Rejected</title></head>
<body>The requested URL was rejected. Please consult with your administrator.<br/><br/>
Your support ID is 85281693-eb72-4891-9099-928ffe00869c<br/><br/><a href='javascript&colon;history.back();'>[Go Back]</a></body></html>
* Connection #0 to host left intact

Notice that the above request intentionally by-passes the CDN cache and is sent to the HTTP LB for the WAF policy to inspect. With this request rejected, you can confirm the attack by navigating to the WAAP HTTP LB Security page under the WAAP Security section within Apps & APIs. After refreshing the page, you’ll see the security violation under the “Top Attacked” panel.



To see all of this in action, watch my video below. This uses all of the configuration details above to make a WAAP + CDN service chain in Distributed Cloud.

Additional Guides

Virtually deploy this solution in our product simulator, or hands-on with step-by-step comprehensive demo guide. The demo guide includes all the steps, including those that are needed prior to deployment, so that once deployed, the solution works end-to-end without any tweaks to local DNS. The demo guide steps can also be automated with Ansible, in case you'd either like to replicate it or simply want to jump to the end and work your way back.


This shows just how simple it can be to use the Distributed Cloud CDN to frontend your web app protected by a WAF, all natively within the F5 Distributed Cloud’s regional edge POPs. The advantage of this solution should now be clear – the Distributed Cloud CDN is cloud-agnostic, flexible, agile, and you can enforce security policies anywhere, regardless of whether your web app lives on-prem, in and across clouds, or even at the edge.

For more information about Distributed Cloud WAAP and Distributed Cloud CDN, visit the following resources:
Product website:
Distributed Cloud CDN & WAAP Demo Guide:
Demo Guide:

Version history
Last update:
‎06-Feb-2023 21:23
Updated by: