Dead Man’s Switch#

The dead man’s switch automatically stops C2 traffic forwarding when the operator fails to check in within a configurable time window. This prevents abandoned redirectors from remaining active indefinitely - a common OPSEC failure in long-running engagements.

How It Works#

The DeadManSwitch starts a background asyncio task that monitors the time since the last operator heartbeat. If the TTL expires without a heartbeat, the switch sets an internal asyncio.Event that the router checks before forwarding C2 traffic.

                ┌─────────────┐
                │  Operator   │
                │ (heartbeat) │
                └──────┬──────┘
                       │ POST /api/heartbeat
                       ▼
               ┌───────────────┐
               │ DeadManSwitch │──── TTL timer (background task)
               └───────┬───────┘
                       │
          ┌────────────┴────────────┐
          │                         │
   TTL not expired             TTL expired
          │                         │
   C2 traffic flows          C2 traffic stopped

Configuration#

deadman_switch:
  enabled: true
  ttl_hours: 24              # how long before the switch trips (default: 24)

The background check task runs at min(ttl / 10, 60 seconds) intervals, so an expiry is detected quickly without excessive polling.

Heartbeat#

The operator must periodically call the heartbeat endpoint to prove they are still active. Each heartbeat resets the TTL timer:

# Send a heartbeat
curl -X POST -H "Authorization: Bearer $TOKEN" https://ig:8080/api/heartbeat

The heartbeat can be automated via a cron job, a CI/CD scheduled pipeline, or a monitoring system.

Behavior When Expired#

When the dead man’s switch trips:

  1. An asyncio.Event is set, signaling the router
  2. The router stops forwarding C2 beacon traffic (requests are dropped or redirected to the decoy)
  3. A burn alert fires through the plugin pipeline
  4. The redirector continues serving decoy pages and canary tokens (so it still looks alive to scanners)

Resetting#

The operator can reset the switch by sending another heartbeat. The event is cleared and C2 traffic resumes immediately:

# Resume after expiry
curl -X POST -H "Authorization: Bearer $TOKEN" https://ig:8080/api/heartbeat

No restart is required - the switch resets in-place.

Operational Notes#

  • Set the TTL based on your check-in cadence. For active engagements, 24 hours is typical. For long-term persistent infrastructure, consider 72 hours or longer.
  • Combine with Discord/Slack alerts so the operator is warned before the switch trips (the background task logs warnings as the TTL approaches).
  • The switch only affects C2 traffic forwarding. Management API endpoints remain accessible so the operator can always recover.