NGFW Configuration Reference — TLSStress.Art DUT Mode¶
Who this is for: The network engineer responsible for configuring the firewall being tested (the Device Under Test — DUT). This document contains every VLAN, IP address, route, and TLS policy the NGFW must be configured with before the test-bed can generate traffic.
Author: André Luiz Gallon — agallon@Cisco.com | Version: v3.6.0
Scope status (post-Scope-Freeze 2026-05-10) — See ARCHITECTURE.md for the canonical 37 MÓDULOs + 7 Test Kinds + DOM/CPOS/PIE-PA safety architecture. ADRs 0014, 0019-0025 cover post-Freeze additions.
Table of Contents¶
- How the Test-Bed Works
- Physical Connectivity
- Complete VLAN and IP Reference
- NGFW Interface Configuration
- Routing Table
- PKI — The Two CAs
- TLS Inspection Policy
- Vendor Configuration Examples
- Cisco FTD (FMC)
- Cisco FTD (FDM)
- Cisco ASA
- FortiGate
- Palo Alto PAN-OS
- Check Point
- Verification
- Troubleshooting
1. How the Test-Bed Works¶
The TLSStress.Art places the NGFW in the middle of all HTTPS traffic between simulated users (agents) and simulated websites (personas). The NGFW must perform TLS inspection on every connection — this is exactly what is being measured.
┌─────────────────────────────────────────────────────────────────┐
│ TLSStress.Art (Ubuntu + k3s) │
│ │
│ browser-engine agents (VLAN 20 — 172.16.x.x) │
│ synthetic-load agents (VLAN 30 — 172.17.x.x) │
└───────────────────────────┬─────────────────────────────────────┘
│ TLS Leg 1
│ Agents → NGFW
│ NGFW presents its own CA-signed cert
│ Agents trust ngfw-ca (installed in cluster)
▼
┌─────────────────────────┐
│ NGFW (Device Under │ ◄── This is what is being tested
│ Test) │
│ │
│ TLS Inspection Engine │
│ Decrypt → Inspect → │
│ Re-encrypt │
└─────────────┬───────────┘
│ TLS Leg 2
│ NGFW → Persona webservers
│ Persona certs signed by persona-ca
│ NGFW trusts persona-ca (installed on NGFW)
▼
┌─────────────────────────────────────────────────────────────────┐
│ 20 Persona Webservers (Caddy + Kubernetes) │
│ │
│ shop VLAN 101 — 10.1.1.0/27 │
│ news VLAN 102 — 10.1.2.0/27 │
│ ... ... │
│ har-media VLAN 120 — 10.1.20.0/27 │
└─────────────────────────────────────────────────────────────────┘
Two TLS legs — two separate certificate trust relationships:
| Leg | Direction | Who presents cert | Who must trust it | How |
|---|---|---|---|---|
| Leg 1 | Agent → NGFW | NGFW (forward-proxy cert) | Agents (browser-engine + synthetic-load) | ngfw-ca.crt installed in Kubernetes cluster |
| Leg 2 | NGFW → Persona webservers | Persona webserver (Caddy) | NGFW | persona-ca.pem installed in NGFW trust store |
2. Physical Connectivity¶
Cabling¶
Ubuntu Server (test-bed)
eth1 (802.1q trunk) ──────────► Nexus 9000 trunk port
│
VLAN trunk
(all VLANs)
│
┌────────┴────────┐
│ Nexus 9000 │
└────────┬────────┘
│
┌──────────┴──────────┐
│ Access port(s) │
│ to NGFW data │
│ interfaces │
└──────────┬──────────┘
│
┌────┴────┐
│ NGFW │
│ (DUT) │
└─────────┘
Nexus 9000 requirements¶
The Nexus 9000 must be configured with the following VLANs and trunk:
vlan 20,30,99,101-120,200-209
interface <trunk-to-ubuntu>
switchport mode trunk
switchport trunk allowed vlan 20,30,99,101-120,200-209
interface <to-ngfw-inside> ! agent-side NGFW port
switchport mode trunk
switchport trunk allowed vlan 20,30
interface <to-ngfw-outside> ! webserver-side NGFW port (Synthetic + Cloned Personas)
switchport mode trunk
switchport trunk allowed vlan 101-120,200-209
interface <to-ngfw-mgmt> ! management NGFW port (optional)
switchport mode access
switchport access vlan 99
Note on VLAN 10 (removed in v3.7.0): the legacy single-Caddy Docker-mode webserver layer that lived on VLAN 10 / 10.20.30.0/24 was removed. Kubernetes is the single source of truth for DUT webservers — 20 Synthetic Personas on VLANs 101–120 + 10 Cloned Persona slots on VLANs 200–209.
3. Complete VLAN and IP Reference¶
3.0 NGFW Security Zone Mapping (v4.3, locked 2026-05-09)¶
The NGFW has 8 interfaces (or sub-interfaces on a trunk) distributed across 3 zones:
| Zone | VLANs | Carries |
|---|---|---|
| TRUST / INSIDE | 20, 30, 2900 | Agent corporate LANs (browser-engine + synthetic-load) + control-plane stress agent (MAC + ARP/NDP) |
| UNTRUST / OUTSIDE | 1982, 2001, 2809, 4338 | VyOS routing/peer endpoints (OSPF, ISP/edge, BGP, MÓDULO SDWAN/CoR-N.Art local mode — legacy "VPN-REMOTE") |
| MGMT | 99 | Management — SNMP only |
VLANs that do NOT terminate on the NGFW:
| VLAN | Reason |
|---|---|
40 (cloner-isp) |
Cloner egress goes directly to public Internet — bypasses NGFW |
| 101–120 (Synthetic Personas) | Personas live BEHIND the VyOS-ISP pod (one country /24 per VLAN); the NGFW only sees the single edge link (VLAN 2001) — VyOS-ISP routes onward to each country |
| 200–209 (Cloned Personas) | Being deprecated — cloned personas migrate to country /24s alongside Synthetic ones |
⚠️ Sections 3.3 and 4.2 below describe the LEGACY v3.x topology where personas terminated on NGFW sub-interfaces (one per VLAN 101–120, with NGFW gateway
10.1.x.1). For v4.3, personas live behind VyOS-ISP and the NGFW only has the single VLAN 2001 outside interface for all persona traffic. Seedocs/ARCHITECTURE.md"DUT network segments" for the corrected topology. Migration tracked separately (Personas v4.3 IP migration option B).
3.1 Agent VLANs (Inside — toward NGFW)¶
These are the subnets where the test agents live. The NGFW is the default gateway for agents.
| VLAN | Purpose | Subnet | NGFW Interface IP | Agent IP range | Protocol |
|---|---|---|---|---|---|
| 20 | browser-engine agents (real browser) | 172.16.0.0/16 |
172.16.0.1 |
172.16.1.0 – 172.16.255.254 |
HTTPS (TCP 443) |
| 30 | synthetic-load agents (HTTP load) | 172.17.0.0/16 |
172.17.0.1 |
172.17.1.0 – 172.17.255.254 |
HTTPS (TCP 443) |
browser-engine agents generate real browser-style HTTPS with full TLS handshake and JavaScript. synthetic-load agents generate high-scale HTTP/2 and HTTP/3 load.
3.2 Management VLAN¶
| VLAN | Purpose | Subnet | Nexus 9000 IP | NGFW mgmt IP | K8s SNMP pod range |
|---|---|---|---|---|---|
| 99 | SNMP monitoring | 10.254.254.0/24 |
10.254.254.2 |
10.254.254.3 |
10.254.254.10 – .49 |
The SNMP Exporter pod collects CPU, memory, and interface counters from both the Nexus 9000 and the NGFW to correlate traffic load with hardware performance.
3.3 Persona VLANs (Outside — toward Caddy webservers)¶
There are two groups of persona VLANs, both in the data path (NGFW → Caddy):
Synthetic Personas — 20 permanent personas, each with its own Kubernetes namespace and generated content:
Each persona runs in its own Kubernetes namespace with a dedicated VLAN, /27 subnet, TLS certificate, and DNS name. The NGFW is the gateway for inbound connections from the agent side.
| VLAN | Persona | Subnet | NGFW Interface IP | Webserver IP(s) | DNS name | Site type |
|---|---|---|---|---|---|---|
| 101 | shop | 10.1.1.0/27 |
10.1.1.1 |
10.1.1.2 |
shop.persona.internal |
E-Commerce (Saleor) |
| 102 | news | 10.1.2.0/27 |
10.1.2.1 |
10.1.2.2 |
news.persona.internal |
News Portal |
| 103 | blog | 10.1.3.0/27 |
10.1.3.1 |
10.1.3.2 |
blog.persona.internal |
Blog |
| 104 | docs | 10.1.4.0/27 |
10.1.4.1 |
10.1.4.2 |
docs.persona.internal |
Technical Documentation |
| 105 | gallery | 10.1.5.0/27 |
10.1.5.1 |
10.1.5.2 |
gallery.persona.internal |
Image Gallery |
| 106 | stream | 10.1.6.0/27 |
10.1.6.1 |
10.1.6.2 |
stream.persona.internal |
HLS Video Streaming |
| 107 | download | 10.1.7.0/27 |
10.1.7.1 |
10.1.7.2 |
download.persona.internal |
File Hosting |
| 108 | edu | 10.1.8.0/27 |
10.1.8.1 |
10.1.8.2 |
edu.persona.internal |
Learning Platform |
| 109 | gov | 10.1.9.0/27 |
10.1.9.1 |
10.1.9.2 |
gov.persona.internal |
Government Portal |
| 110 | cdn | 10.1.10.0/27 |
10.1.10.1 |
10.1.10.2 |
cdn.persona.internal |
Asset CDN |
| 111 | api-rest | 10.1.11.0/27 |
10.1.11.1 |
10.1.11.2 |
api-rest.persona.internal |
REST API |
| 112 | api-graphql | 10.1.12.0/27 |
10.1.12.1 |
10.1.12.2 |
api-graphql.persona.internal |
GraphQL API |
| 113 | chat | 10.1.13.0/27 |
10.1.13.1 |
10.1.13.2 |
chat.persona.internal |
Chat / Messaging |
| 114 | webhook | 10.1.14.0/27 |
10.1.14.1 |
10.1.14.2 |
webhook.persona.internal |
Webhooks |
| 115 | telemetry | 10.1.15.0/27 |
10.1.15.1 |
10.1.15.2 |
telemetry.persona.internal |
Analytics / Telemetry |
| 116 | ads | 10.1.16.0/27 |
10.1.16.1 |
10.1.16.2 |
ads.persona.internal |
Ad Network |
| 117 | har-saas | 10.1.17.0/27 |
10.1.17.1 |
10.1.17.2 |
har-saas.persona.internal |
Enterprise SaaS (HAR replay) |
| 118 | har-social | 10.1.18.0/27 |
10.1.18.1 |
10.1.18.2 |
har-social.persona.internal |
Social Network (HAR replay) |
| 119 | har-webmail | 10.1.19.0/27 |
10.1.19.1 |
10.1.19.2 |
har-webmail.persona.internal |
Webmail (HAR replay) |
| 120 | har-media | 10.1.20.0/27 |
10.1.20.1 |
10.1.20.2 |
har-media.persona.internal |
Media Streaming (HAR replay) |
Webserver IPs: each persona pod gets the first available IP in its range (
.2). If replicas > 1, additional IPs (.3,.4…) are assigned. The TLS certificate covers the full range.2–.30. The NGFW connects to the webserver IP directly (IP SAN validation).
Cloned Personas — 10 dynamic slots serving static site mirrors cloned from public websites:
| VLAN | Slot | Subnet | NGFW Interface IP | Webserver IP(s) | Content |
|---|---|---|---|---|---|
| 200 | clone-persona-1 | 10.2.1.0/27 |
10.2.1.1 |
10.2.1.2 |
Cloned site (file_server from PVC) |
| 201 | clone-persona-2 | 10.2.2.0/27 |
10.2.2.1 |
10.2.2.2 |
Cloned site (file_server from PVC) |
| 202 | clone-persona-3 | 10.2.3.0/27 |
10.2.3.1 |
10.2.3.2 |
Cloned site (file_server from PVC) |
| 203 | clone-persona-4 | 10.2.4.0/27 |
10.2.4.1 |
10.2.4.2 |
Cloned site (file_server from PVC) |
| 204 | clone-persona-5 | 10.2.5.0/27 |
10.2.5.1 |
10.2.5.2 |
Cloned site (file_server from PVC) |
| 205 | clone-persona-6 | 10.2.6.0/27 |
10.2.6.1 |
10.2.6.2 |
Cloned site (file_server from PVC) |
| 206 | clone-persona-7 | 10.2.7.0/27 |
10.2.7.1 |
10.2.7.2 |
Cloned site (file_server from PVC) |
| 207 | clone-persona-8 | 10.2.8.0/27 |
10.2.8.1 |
10.2.8.2 |
Cloned site (file_server from PVC) |
| 208 | clone-persona-9 | 10.2.9.0/27 |
10.2.9.1 |
10.2.9.2 |
Cloned site (file_server from PVC) |
| 209 | clone-persona-10 | 10.2.10.0/27 |
10.2.10.1 |
10.2.10.2 |
Cloned site (file_server from PVC) |
Cloned Persona slots are assigned via Dashboard:
PATCH /api/clone/persona-slots/{n} { "siteName": "<site>" }. Certs are signed by the samepersona-ca-issueras Synthetic Personas. The NGFW CA trust configuration is identical.
3.4 Summary — all subnets¶
| VLAN | Subnet | Role | NGFW interface IP |
|---|---|---|---|
| 20 | 172.16.0.0/16 |
browser-engine agents | 172.16.0.1 |
| 30 | 172.17.0.0/16 |
synthetic-load agents | 172.17.0.1 |
| 99 | 10.254.254.0/24 |
SNMP management | 10.254.254.3 |
| 101 | 10.1.1.0/27 |
shop | 10.1.1.1 |
| 102 | 10.1.2.0/27 |
news | 10.1.2.1 |
| 103 | 10.1.3.0/27 |
blog | 10.1.3.1 |
| 104 | 10.1.4.0/27 |
docs | 10.1.4.1 |
| 105 | 10.1.5.0/27 |
gallery | 10.1.5.1 |
| 106 | 10.1.6.0/27 |
stream | 10.1.6.1 |
| 107 | 10.1.7.0/27 |
download | 10.1.7.1 |
| 108 | 10.1.8.0/27 |
edu | 10.1.8.1 |
| 109 | 10.1.9.0/27 |
gov | 10.1.9.1 |
| 110 | 10.1.10.0/27 |
cdn | 10.1.10.1 |
| 111 | 10.1.11.0/27 |
api-rest | 10.1.11.1 |
| 112 | 10.1.12.0/27 |
api-graphql | 10.1.12.1 |
| 113 | 10.1.13.0/27 |
chat | 10.1.13.1 |
| 114 | 10.1.14.0/27 |
webhook | 10.1.14.1 |
| 115 | 10.1.15.0/27 |
telemetry | 10.1.15.1 |
| 116 | 10.1.16.0/27 |
ads | 10.1.16.1 |
| 117 | 10.1.17.0/27 |
har-saas | 10.1.17.1 |
| 118 | 10.1.18.0/27 |
har-social | 10.1.18.1 |
| 119 | 10.1.19.0/27 |
har-webmail | 10.1.19.1 |
| 120 | 10.1.20.0/27 |
har-media | 10.1.20.1 |
| 200 | 10.2.1.0/27 |
clone-persona-1 | 10.2.1.1 |
| 201 | 10.2.2.0/27 |
clone-persona-2 | 10.2.2.1 |
| 202 | 10.2.3.0/27 |
clone-persona-3 | 10.2.3.1 |
| 203 | 10.2.4.0/27 |
clone-persona-4 | 10.2.4.1 |
| 204 | 10.2.5.0/27 |
clone-persona-5 | 10.2.5.1 |
| 205 | 10.2.6.0/27 |
clone-persona-6 | 10.2.6.1 |
| 206 | 10.2.7.0/27 |
clone-persona-7 | 10.2.7.1 |
| 207 | 10.2.8.0/27 |
clone-persona-8 | 10.2.8.1 |
| 208 | 10.2.9.0/27 |
clone-persona-9 | 10.2.9.1 |
| 209 | 10.2.10.0/27 |
clone-persona-10 | 10.2.10.1 |
4. NGFW Interface Configuration¶
4.1 Required interfaces¶
The NGFW must have at minimum two physical interfaces (or one trunk):
| Interface | Connected to | Carries VLANs | Direction |
|---|---|---|---|
| Inside (agent-side) | Nexus 9000 | 20, 30 | Agents → NGFW |
| Outside (server-side) | Nexus 9000 | 101–120, 200–209 | NGFW → Persona webservers (Synthetic + Cloned) |
| Management (optional) | Nexus 9000 | 99 | SNMP monitoring only |
4.2 Subinterface IPs to configure¶
For each VLAN, the NGFW needs a subinterface with the gateway IP listed in section 3. Example for a trunk-capable inside interface:
# Inside interface — agent-facing
VLAN 20 → IP 172.16.0.1/16 (browser-engine agent gateway)
VLAN 30 → IP 172.17.0.1/16 (synthetic-load agent gateway)
# Outside interface — webserver-facing (Synthetic Personas)
VLAN 101 → IP 10.1.1.1/27 (shop gateway)
VLAN 102 → IP 10.1.2.1/27 (news gateway)
VLAN 103 → IP 10.1.3.1/27 (blog gateway)
VLAN 104 → IP 10.1.4.1/27 (docs gateway)
VLAN 105 → IP 10.1.5.1/27 (gallery gateway)
VLAN 106 → IP 10.1.6.1/27 (stream gateway)
VLAN 107 → IP 10.1.7.1/27 (download gateway)
VLAN 108 → IP 10.1.8.1/27 (edu gateway)
VLAN 109 → IP 10.1.9.1/27 (gov gateway)
VLAN 110 → IP 10.1.10.1/27 (cdn gateway)
VLAN 111 → IP 10.1.11.1/27 (api-rest gateway)
VLAN 112 → IP 10.1.12.1/27 (api-graphql gateway)
VLAN 113 → IP 10.1.13.1/27 (chat gateway)
VLAN 114 → IP 10.1.14.1/27 (webhook gateway)
VLAN 115 → IP 10.1.15.1/27 (telemetry gateway)
VLAN 116 → IP 10.1.16.1/27 (ads gateway)
VLAN 117 → IP 10.1.17.1/27 (har-saas gateway)
VLAN 118 → IP 10.1.18.1/27 (har-social gateway)
VLAN 119 → IP 10.1.19.1/27 (har-webmail gateway)
VLAN 120 → IP 10.1.20.1/27 (har-media gateway)
# Outside interface — webserver-facing (Cloned Persona slots)
VLAN 200 → IP 10.2.1.1/27 (clone-persona-1 gateway)
VLAN 201 → IP 10.2.2.1/27 (clone-persona-2 gateway)
VLAN 202 → IP 10.2.3.1/27 (clone-persona-3 gateway)
VLAN 203 → IP 10.2.4.1/27 (clone-persona-4 gateway)
VLAN 204 → IP 10.2.5.1/27 (clone-persona-5 gateway)
VLAN 205 → IP 10.2.6.1/27 (clone-persona-6 gateway)
VLAN 206 → IP 10.2.7.1/27 (clone-persona-7 gateway)
VLAN 207 → IP 10.2.8.1/27 (clone-persona-8 gateway)
VLAN 208 → IP 10.2.9.1/27 (clone-persona-9 gateway)
VLAN 209 → IP 10.2.10.1/27 (clone-persona-10 gateway)
# Management interface
VLAN 99 → IP 10.254.254.3/24 (SNMP monitoring)
4.3 Security zones¶
Create two security zones on the NGFW:
| Zone name | Interfaces | Trust level |
|---|---|---|
agents |
VLAN 20, VLAN 30 | Lower (clients — untrusted traffic source) |
personas |
VLANs 101–120, 200–209 | Higher (servers — inspect traffic going here) |
5. Routing Table¶
The NGFW must be able to route traffic between the agent and persona subnets. Since it is the gateway for all subnets, the connected routes cover local forwarding. No static routes are strictly required unless the NGFW needs a management default route.
| Destination | Next Hop | Interface | Purpose |
|---|---|---|---|
172.16.0.0/16 |
directly connected | Inside.20 | browser-engine agents |
172.17.0.0/16 |
directly connected | Inside.30 | synthetic-load agents |
10.1.1.0/27 – 10.1.20.0/27 |
directly connected | Outside.101–120 | Synthetic Persona webservers |
10.2.1.0/27 – 10.2.10.0/27 |
directly connected | Outside.200–209 | Cloned Persona slots |
10.254.254.0/24 |
directly connected | Mgmt.99 | SNMP management |
0.0.0.0/0 |
management network GW | Management | Internet access for updates (optional) |
Policy-based routing: some NGFWs apply routing decisions per security policy rule. Ensure your access policy allows traffic from
agentszone topersonaszone on TCP 443 (and UDP 443 for HTTP/3 / QUIC).
6. PKI — The Two CAs¶
This is the most critical part of the NGFW configuration. There are two completely different CAs, each used for a different TLS leg.
6.1 CA for Leg 2 — persona-ca-issuer CA (import INTO the NGFW)¶
What it is: the internal CA used by cert-manager (persona-ca-issuer ClusterIssuer in platform/pki/) to sign the TLS certificates of all 20 Synthetic Persona webservers and all 10 Cloned Persona slots (Caddy).
Why the NGFW needs it: in TLS Leg 2 (NGFW → webserver), the NGFW acts as a TLS client and must validate the server certificate presented by Caddy. If the NGFW doesn't trust this CA, it will reject the connection with a certificate validation error.
How to export it from the cluster:
# On the Ubuntu server (after running k8s-dut-up.sh or k8s-install.sh)
kubectl get secret persona-ca-bundle -n web-agents \
-o jsonpath='{.data.ca\.crt}' | base64 -d > persona-ca.pem
# Verify the certificate
openssl x509 -in persona-ca.pem -text -noout | grep -E "Subject:|Issuer:|Not After"
Expected output:
Subject: O=Web Agent Cluster, OU=Persona PKI, CN=Persona CA
Issuer: O=Web Agent Cluster, OU=Persona PKI, CN=Persona CA
Not After: <date ~10 years from cluster creation>
Where to import it on the NGFW: see section 8 for vendor-specific instructions. Generally: trusted CA store / SSL inspection trusted CAs.
This single CA signs certs for all 30 webserver VLANs (20 Synthetic Personas on VLANs 101–120 + 10 Cloned Persona slots on VLANs 200–209). You only need to import one CA into the NGFW.
6.2 CA for Leg 1 — ngfw-ca (export FROM the NGFW, install in cluster)¶
What it is: the CA the NGFW uses to sign the forward-proxy certificates it presents to the agents during TLS Leg 1. This is the NGFW's own interception CA.
Why the cluster needs it: browser engine (Node.js) and synthetic-load engine (Go) agents validate the server certificate during every HTTPS connection. If they don't trust the NGFW's CA, every connection will fail with CERT_AUTHORITY_INVALID or similar.
How to export it from each NGFW vendor:
| Vendor | Where to find it | Export format |
|---|---|---|
| Cisco FTD (FMC) | Objects → PKI → CA Certificates → select intercept CA → Export | PEM |
| Cisco FTD (FDM) | Policies → SSL → Trusted CA → export | PEM |
| Cisco ASA | crypto ca export <trustpoint> certificate |
PEM (copy from terminal) |
| FortiGate | Security Profiles → SSL/SSH Inspection → CA Certificate → Download | PEM |
| Palo Alto | Device → Certificate Management → Certificates → select forward-trust cert → Export | PEM |
| Check Point | SmartConsole → Gateways → HTTPS Inspection → CA Certificate → Export | PEM or Base64 |
| Huawei USG | System → PKI → CA Certificate → Export | PEM |
| Meraki MX | Security & SD-WAN → Content Filtering → SSL Inspection → Download CA Certificate | PEM |
How to install it in the cluster:
# Replace with the actual path to the exported PEM file
kubectl create configmap ngfw-ca \
-n web-agents \
--from-file=ngfw-ca.crt=./ngfw-ca.pem \
--dry-run=client -o yaml | kubectl apply -f -
# Verify it was applied
kubectl get configmap ngfw-ca -n web-agents -o yaml | grep 'ngfw-ca.crt' -A 3
# Restart agents to pick up the new CA
kubectl rollout restart deployment/web-agent -n web-agents
kubectl rollout restart deployment/k6-agent -n web-agents
kubectl rollout status deployment/web-agent -n web-agents
kubectl rollout status deployment/k6-agent -n web-agents
7. TLS Inspection Policy¶
7.1 What to inspect¶
Configure the TLS inspection policy to decrypt and inspect all HTTPS traffic between the agent subnets and the persona subnets:
| Source | Destination | Port | Action |
|---|---|---|---|
172.16.0.0/16 (browser engine) |
10.1.0.0/16 (Synthetic Personas) |
TCP 443 | Decrypt & Inspect |
172.17.0.0/16 (synthetic-load engine) |
10.1.0.0/16 (Synthetic Personas) |
TCP 443 | Decrypt & Inspect |
172.16.0.0/16 (browser engine) |
10.1.0.0/16 (Synthetic Personas) |
UDP 443 | Decrypt & Inspect (QUIC/HTTP3) |
172.17.0.0/16 (synthetic-load engine) |
10.1.0.0/16 (Synthetic Personas) |
UDP 443 | Decrypt & Inspect (QUIC/HTTP3) |
172.16.0.0/16 (browser engine) |
10.2.0.0/16 (Cloned Persona slots) |
TCP 443 | Decrypt & Inspect |
172.17.0.0/16 (synthetic-load engine) |
10.2.0.0/16 (Cloned Persona slots) |
TCP 443 | Decrypt & Inspect |
172.16.0.0/16 (browser engine) |
10.2.0.0/16 (Cloned Persona slots) |
UDP 443 | Decrypt & Inspect (QUIC/HTTP3) |
172.17.0.0/16 (synthetic-load engine) |
10.2.0.0/16 (Cloned Persona slots) |
UDP 443 | Decrypt & Inspect (QUIC/HTTP3) |
7.2 TLS versions¶
The Caddy webservers support TLS 1.2 and TLS 1.3. Configure the NGFW to inspect both:
- Minimum: TLS 1.2
- Maximum: TLS 1.3
- Disable: TLS 1.1, TLS 1.0, SSL 3.0
7.3 Cipher suites¶
Caddy uses only ECDHE+AEAD cipher suites (ECDSA certificates). Ensure your inspection policy does not downgrade to RSA or CBC ciphers:
TLS_AES_256_GCM_SHA384 (TLS 1.3)
TLS_AES_128_GCM_SHA256 (TLS 1.3)
TLS_CHACHA20_POLY1305_SHA256 (TLS 1.3)
ECDHE-ECDSA-AES256-GCM-SHA384 (TLS 1.2)
ECDHE-ECDSA-AES128-GCM-SHA256 (TLS 1.2)
ECDHE-ECDSA-CHACHA20-POLY1305 (TLS 1.2)
7.4 HTTP/3 (QUIC) — important note¶
The synthetic-load agent can generate HTTP/3 (QUIC over UDP 443). HTTP/3 TLS inspection is harder for NGFWs and is one of the key metrics being measured. Check your NGFW vendor documentation for QUIC inspection support:
- If QUIC inspection is supported: enable it and include UDP 443 in the inspection policy.
- If QUIC inspection is not supported (or you want to measure only HTTP/2): add a rule to block or reset UDP 443, which forces agents to fall back to HTTP/2 over TCP. This is a valid test scenario — it measures the impact of forcing QUIC-capable clients to downgrade.
7.5 Certificate validation on Leg 2¶
The NGFW must validate the server certificate during Leg 2 (NGFW → Caddy). Ensure:
- Server certificate validation: Enabled (not bypassed)
- Trusted CA store: includes
persona-ca.pem(see section 6.1) — this single CA covers both Synthetic Personas (VLANs 101–120) and Cloned Persona slots (VLANs 200–209) - Certificate revocation: CRL/OCSP can be disabled — this is a lab with no revocation infrastructure
8. Vendor Configuration Examples¶
8.1 Cisco FTD — Firepower Management Center¶
Step 1: Import persona-ca (trust persona webserver certs)¶
- Objects → PKI → Trusted CAs → Add Trusted CA
- Name:
Persona-CA - Upload
persona-ca.pem - Click Save
Step 2: Export ngfw-ca (so agents can trust NGFW)¶
- Objects → PKI → CA Certificates → select your intercept CA
- Click Export → download PEM
- Install on cluster:
kubectl create configmap ngfw-ca -n web-agents --from-file=ngfw-ca.crt=<file>.pem
Step 3: Create SSL Policy¶
- Policies → SSL → New Policy
- Name:
DUT-TLS-Inspection - Add rule:
- Action: Decrypt — Resign
- Source Zones:
agents - Destination Zones:
personas - Destination Ports: TCP 443, UDP 443
- Resign CA: select your intercept CA
- Default Action: Do Not Decrypt (pass through other traffic)
Step 4: Create Access Control Policy rule¶
- Policies → Access Control → your policy
- Add rule above the default:
- Source Networks:
172.16.0.0/16,172.17.0.0/16 - Destination Networks:
10.1.0.0/16 - Destination Ports: TCP 443, UDP 443
- SSL Policy:
DUT-TLS-Inspection - Action: Allow (with inspection)
- Intrusion Policy: attach if you want IPS metrics during the test
- Deploy to the FTD sensor
Step 5: Configure interfaces¶
# In FMC: Devices → Device Management → select your FTD → Interfaces
# Set up subinterfaces on the physical interfaces:
Inside interface (trunk):
Subinterface 20: VLAN 20, IP 172.16.0.1/16, Security Zone: agents
Subinterface 30: VLAN 30, IP 172.17.0.1/16, Security Zone: agents
Outside interface (trunk):
Subinterface 101: VLAN 101, IP 10.1.1.1/27, Security Zone: personas
Subinterface 102: VLAN 102, IP 10.1.2.1/27, Security Zone: personas
...
Subinterface 120: VLAN 120, IP 10.1.20.1/27, Security Zone: personas
Management interface:
Subinterface 99: VLAN 99, IP 10.254.254.3/24 (out-of-band, SNMP)
8.2 Cisco FTD — Firepower Device Manager¶
Import persona-ca¶
- Objects → Certificates → Trusted CA → Add
- Name:
Persona-CA, uploadpersona-ca.pem
Export ngfw-ca¶
- Policies → SSL → Trusted CA → export your intercept CA
Create SSL Decryption Policy¶
- Policies → SSL Decryption → Add Rule
- Source:
172.16.0.0/16,172.17.0.0/16 - Destination:
10.1.0.0/16 - Port: HTTPS (443/tcp)
- Action: Decrypt — Resign with your intercept CA
8.3 Cisco ASA¶
ASA with FirePOWER Services (SFR module) or ASA with AnyConnect SSL inspection:
# Import persona-ca as trusted CA
crypto ca authenticate DUT-ROOT-CA
# Paste the PEM content when prompted (the persona-ca.pem contents)
# Create crypto map or SSL inspection policy targeting:
# src 172.16.0.0 255.255.0.0 and 172.17.0.0 255.255.0.0
# dst 10.1.0.0 255.255.0.0
# port 443
# Create subinterfaces for agent VLANs
interface GigabitEthernet0/0.20
encapsulation dot1Q 20
ip address 172.16.0.1 255.255.0.0
nameif agents-pw
security-level 50
interface GigabitEthernet0/0.30
encapsulation dot1Q 30
ip address 172.17.0.1 255.255.0.0
nameif agents-k6
security-level 50
# Create subinterfaces for persona VLANs (repeat for 101-120)
interface GigabitEthernet0/1.101
encapsulation dot1Q 101
ip address 10.1.1.1 255.255.255.224
nameif persona-shop
security-level 0
# ... repeat for VLANs 102-120 ...
# Enable SSL inspection via FirePOWER module or ASA CX
8.4 FortiGate¶
Create VLANs and interface IPs¶
# In CLI:
config system interface
edit "inside.20"
set vdom "root"
set ip 172.16.0.1 255.255.0.0
set allowaccess ping
set type vlan
set interface "port1"
set vlanid 20
set role lan
next
edit "inside.30"
set vdom "root"
set ip 172.17.0.1 255.255.0.0
set type vlan
set interface "port1"
set vlanid 30
set role lan
next
edit "outside.101"
set vdom "root"
set ip 10.1.1.1 255.255.255.224
set type vlan
set interface "port2"
set vlanid 101
set role wan
next
# ... repeat for VLANs 102-120 ...
end
Import persona-ca¶
# GUI: Security Profiles → SSL/SSH Inspection → Create/Edit profile
# Under "CA Certificate": import persona-ca.pem
# Or via CLI:
config vpn certificate ca
edit "Persona-CA"
set ca "<base64-encoded-persona-ca>"
next
end
Export ngfw-ca¶
# GUI: Security Profiles → SSL/SSH Inspection → select your profile
# → CA Certificate → Download
# This downloads the FortiGate's intercept CA in PEM format.
Create SSL/SSH Inspection Profile¶
# GUI: Security Profiles → SSL/SSH Inspection → Create New
config firewall ssl-ssh-profile
edit "DUT-Inspection"
set comment "TLSStress.Art DUT mode"
config https
set ports 443
set status deep-inspection
set proxy-after-tcp-handshake enable
end
config ssl
set inspect-all deep-inspection
end
set caname "Persona-CA"
next
end
Create firewall policy¶
config firewall policy
edit 100
set name "DUT-agents-to-personas"
set srcintf "inside.20" "inside.30"
set dstintf "outside.101" "outside.102" ... "outside.120"
set srcaddr "172.16.0.0/16" "172.17.0.0/16"
set dstaddr "10.1.0.0/16"
set action accept
set schedule "always"
set service "HTTPS"
set ssl-ssh-profile "DUT-Inspection"
set utm-status enable
set logtraffic all
next
end
8.5 Palo Alto PAN-OS¶
Import persona-ca¶
# GUI: Device → Certificate Management → Certificates → Import
# Name: Persona-CA
# File: persona-ca.pem
# Mark as: "Trusted Root CA"
# Or via CLI:
scp import certificate from <user@host:/path/persona-ca.pem>
> certificate-name Persona-CA
> category trusted-root-CA
Export ngfw-ca¶
# GUI: Device → Certificate Management → Certificates →
# select your forward-trust certificate → Export Certificate
# Format: Base64 Encoded Certificate (PEM)
Create interfaces¶
# GUI: Network → Interfaces → Ethernet → Add Sub-Interface
# Inside interface (toward agents)
Ethernet1/1.20: IP 172.16.0.1/16, VLAN 20, Zone: agents
Ethernet1/1.30: IP 172.17.0.1/16, VLAN 30, Zone: agents
# Outside interface (toward personas)
Ethernet1/2.101: IP 10.1.1.1/27, VLAN 101, Zone: personas
Ethernet1/2.102: IP 10.1.2.1/27, VLAN 102, Zone: personas
# ... repeat for 103-120 ...
Create Decryption Profile¶
# GUI: Objects → Decryption Profile → Add
# Name: DUT-Decrypt-Profile
# SSL Forward Proxy:
# Forward Trust Certificate: <your intercept CA>
# Forward Untrust Certificate: <your untrust CA>
# Server Certificate Verification:
# Block sessions with expired certificates: yes
# Block sessions with untrusted issuers: yes (with persona-ca as trusted)
Create Decryption Policy¶
# GUI: Policies → Decryption → Add
# Name: DUT-Decrypt-All
# Source Zone: agents
# Destination Zone: personas
# Source Address: 172.16.0.0/16, 172.17.0.0/16
# Destination Address: 10.1.0.0/16
# Service: application-default (or create HTTPS service for 443/tcp + 443/udp)
# Type: SSL Forward Proxy
# Profile: DUT-Decrypt-Profile
Create Security Policy¶
# GUI: Policies → Security → Add
# Name: agents-to-personas
# Source Zone: agents
# Destination Zone: personas
# Application: ssl, web-browsing
# Service: application-default
# Action: Allow
# Profile Group: attach your threat/URL profile
8.6 Check Point¶
Import persona-ca¶
# SmartConsole → Objects → New → Certificate Authority → Trusted CA
# Name: Persona-CA
# Upload: persona-ca.pem
Export ngfw-ca¶
# SmartConsole → Gateways & Servers → double-click your gateway
# → HTTPS Inspection → CA Certificate → Export
# Save as PEM
Configure HTTPS Inspection¶
# SmartConsole → Security Policies → HTTPS Inspection → Policy
# Add rule:
# Name: DUT-Inspection
# Source: Group(172.16.0.0/16, 172.17.0.0/16)
# Destination: Group(10.1.1.0/27 - 10.1.20.0/27)
# Services: HTTPS (443)
# Site Category: Any
# Action: Inspect
# Track: Log
# Under Blade Control → SSL Inspection → Trusted CA:
# Add Persona-CA to the trusted store
Configure interfaces¶
# SmartConsole → Gateways → Interfaces → Add VLAN
# Create sub-interfaces for each VLAN (20, 30, 101-120)
# Assign IPs per section 3 above
9. Verification¶
9.1 Verify connectivity from the cluster¶
# SSH into one of the agent pods
kubectl exec -it -n web-agents deployment/web-agent -- sh
# Test that the NGFW gateway is reachable
ping -c 3 172.16.0.1 # browser-engine VLAN 20 gateway
ping -c 3 172.17.0.1 # K6 VLAN 30 gateway (from K6 pod)
# Test HTTPS to a persona (should succeed if TLS inspection is working)
curl -v https://shop.persona.internal/ --max-time 5
# Expected: HTTP 200, certificate issued by NGFW CA
9.2 Verify TLS inspection is active¶
# From an agent pod, inspect the certificate chain presented by the NGFW
echo | openssl s_client -connect shop.persona.internal:443 -servername shop.persona.internal 2>/dev/null \
| openssl x509 -noout -issuer -subject
# Expected output (certificate issued by NGFW, not by persona-ca):
# issuer=CN=<your NGFW intercept CA name>
# subject=CN=shop.persona.internal (re-signed by NGFW)
9.3 Verify SNMP monitoring¶
# From the SNMP pod, test connectivity to the NGFW
kubectl exec -it -n web-agents deployment/snmp-exporter -- sh
snmpwalk -v2c -c <community> 10.254.254.3 1.3.6.1.2.1.1.1.0
# Expected: sysDescr of the NGFW
9.4 Verify TLS Leg 2 (NGFW trusts webserver cert)¶
Check NGFW logs for TLS errors on the outbound leg. If you see certificate validation failures toward 10.1.x.x (Synthetic Personas) or 10.2.x.x (Cloned Personas), the persona-ca was not imported correctly.
# On the cluster: confirm the webserver certificate chain
echo | openssl s_client -connect 10.1.1.2:443 2>/dev/null \
| openssl x509 -noout -issuer -subject
# Expected (before NGFW interception — direct from Ubuntu server):
# issuer=CN=Persona CA (or similar — the persona-ca-issuer CN)
# subject=CN=shop.persona.internal
10. Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
Agents get CERT_AUTHORITY_INVALID |
ngfw-ca not installed in cluster, or agents not restarted |
Re-run kubectl create configmap ngfw-ca ... and kubectl rollout restart deployment/web-agent |
| NGFW shows TLS Leg 2 cert validation error | persona-ca not imported in NGFW trust store |
Export persona-ca.pem from cluster (kubectl get secret persona-ca-bundle ...) and import in NGFW trusted CA store |
| HTTP/3 connections fail but HTTP/2 works | NGFW doesn't support QUIC inspection | Block UDP 443 on NGFW to force HTTP/2 downgrade; note this in test results |
Agents can't reach persona IPs (10.1.x.x) |
Missing routes or NGFW policy blocking | Check NGFW security policy allows 172.16.0.0/16 and 172.17.0.0/16 to 10.1.0.0/16 |
| SNMP exporter shows no data from NGFW | NGFW SNMP not enabled, wrong community, or VLAN 99 not reachable | Verify NGFW SNMP is enabled with community public (or matching observability/snmp/snmp.yml); verify VLAN 99 IP 10.254.254.3 is pingable |
| TLS inspection not triggered | SSL policy not attached to access rule, or zones misconfigured | Verify source/destination zones match agent and persona interfaces |
| Certificate errors after persona cert renewal | NGFW cached old cert fingerprint | Cert-manager auto-renews persona certs every 11 months; Stakater Reloader restarts Caddy pods — no NGFW change needed |
For test-bed architecture details, see docs/ARCHITECTURE.md.
For deployment instructions, see docs/UBUNTU_K3S_SINGLENODE_QUICKSTART_DEPLOY.en.md.
For the automated Kubernetes installer, see scripts/k8s-install.sh.