Skip to content

Commit ac61416

Browse files
franckfermanclaude
andcommitted
Merge branch 'dev': more offensive context, better architecture, improved why section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 parents 9905a18 + 61f64a2 commit ac61416

2 files changed

Lines changed: 228 additions & 88 deletions

File tree

README.md

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,40 @@
4747

4848
## Overview
4949

50-
`do-manager` is built on top of [`godo`](https://github.com/digitalocean/godo), the official DigitalOcean Go client. It is designed as a **dual-purpose project**:
50+
`do-manager` is built directly on [`godo`](https://github.com/digitalocean/godo), the official DigitalOcean Go client. Two interfaces, one codebase:
5151

52-
- A **CLI tool** for interacting with your DigitalOcean account from the terminal.
53-
- A **Go library** (`pkg/`) that can be imported directly into other Go programs.
52+
- A **CLI tool** for operational use from the terminal - campaign orchestration, IP rotation, node rebuild, security audit.
53+
- A **Go library** (`pkg/`) that can be imported directly into any Go program.
5454

55-
Unlike a wrapper around `doctl`, `do-manager` calls the DigitalOcean API directly via `godo`. No external binary, proper Go types throughout, full composability.
55+
Unlike `doctl`, `do-manager` calls the API directly via `godo` - no subprocess, no string parsing, proper Go types throughout.
5656

57-
The CLI is designed for **operational use cases**: Red Team infrastructure, lab automation, CI/CD provisioning. It supports campaign orchestration (deploy / rotate IPs / destroy a full stack in one command), VPC-isolated networks, firewall presets for common roles, and a security audit scanner.
57+
The design targets **Red Team infrastructure**: deploy a full engagement stack in one command, rotate IPs when they get burned, rebuild a single compromised node without touching the rest, tear everything down cleanly. The primitive operations (create/list/delete/power) are there, but the value is in the higher-level abstractions: `campaign`, firewall presets, `rotate-ips`, `rebuild`, `audit`.
5858

5959
---
6060

6161
## Why do-manager?
6262

63-
| | doctl | Terraform / Pulumi | do-manager |
64-
|---|---|---|---|
65-
| **Type** | CLI binary | Infrastructure-as-Code | CLI + Go library |
66-
| **Importable as Go lib** | No | No | **Yes** |
67-
| **Requires external binary** | Yes | Yes | No |
68-
| **State management** | No | Yes (statefile) | No (stateless) |
69-
| **Parallel batch ops** | No | Partial | **Yes** |
70-
| **Campaign orchestration** | No | Partial | **Yes** (deploy/status/destroy/rotate) |
71-
| **Firewall presets** | No | No | **Yes** (c2/phishing/redirector/bastion/lockdown) |
72-
| **Security audit** | No | No | **Yes** (exit 1 on CRITICAL/HIGH) |
73-
| **Multi-role campaign** | No | No | **Yes** (`--role "c2:..."` + `--role "redirector:..."`) |
74-
| **JSON output** | Yes | N/A | **Yes** (`-o json`) |
75-
| **Embed in a Go project** | Subprocess + parsing | SDK only | `import "pkg/droplet"` |
63+
Three tools are commonly used to manage DO infrastructure from a Red Team perspective:
64+
65+
| | doctl | bash + curl | Terraform / Pulumi | do-manager |
66+
|---|---|---|---|---|
67+
| **Type** | Official CLI | Ad-hoc scripts | Infrastructure-as-Code | CLI + Go library |
68+
| **Campaign orchestration** | No | Manual | Partial | **Yes** (deploy/status/destroy/rotate) |
69+
| **Firewall presets** | No | No | No | **Yes** (c2/phishing/redirector/bastion/lockdown) |
70+
| **IP rotation** | No | Script it yourself | No | **Yes** (rotate-ips) |
71+
| **Parallel batch ops** | No | `&` + wait | Partial | **Yes** (goroutines, per-slot errors) |
72+
| **Security audit** | No | No | No | **Yes** (exit 1 on CRITICAL/HIGH) |
73+
| **Importable as Go lib** | No | No | No | **Yes** (`import "pkg/droplet"`) |
74+
| **Requires state file** | No | No | Yes (.tfstate) | No (stateless) |
75+
| **Requires external binary** | Yes (doctl) | curl, jq | Yes (terraform) | **No** |
76+
77+
**doctl** is fine for manual one-off ops. It covers every DO resource but has no campaign concept, no firewall presets, and no Red Team abstractions.
78+
79+
**bash + curl** is where most people start. It breaks down under engagement pressure: parallel provisioning races, ID extraction with fragile `grep`/`jq`, no error aggregation per Droplet, scripts that diverge between operators.
80+
81+
**Terraform** is the right choice for long-lived stable infrastructure. It is overkill for engagements: statefile management is a liability during ops, the feedback loop is slow, and there are no Red Team primitives.
82+
83+
**do-manager** is the choice when you need to deploy a full stack fast, rotate IPs when they get burned, rebuild a single node without disrupting the campaign, tear everything down cleanly, and optionally embed all of that into a Go automation tool.
7684

7785
---
7886

@@ -373,29 +381,49 @@ do-manager reservedip delete 1.2.3.4
373381

374382
### Snapshots
375383

384+
Snapshots are the foundation for repeatable deployments. The workflow: provision one Droplet, install and configure your tooling (GoPhish, Havoc, evilginx2, nginx redirector config, WireGuard), take a snapshot, delete the source Droplet. On engagement day, `campaign deploy --snapshot <slug>` restores that exact state across N nodes in parallel. No reinstalling, no drift between nodes.
385+
376386
```bash
377387
do-manager snapshot list
378388
do-manager snapshot get <id>
389+
390+
# Freeze a configured Droplet into a reusable image
379391
do-manager snapshot create --droplet 12345678 --name gophish-v2 --wait
392+
393+
# Now deploy that exact state to 5 nodes
394+
do-manager campaign deploy --name phish-q2 --snapshot gophish-v2 --count 5 ...
395+
380396
do-manager snapshot delete <id>
381397
```
382398

383-
Workflow: bake your tooling into a snapshot once, then deploy N identical nodes via `campaign deploy --snapshot gophish-v2`.
384-
385399
---
386400

387401
### VPC
388402

389403
An isolated private network scoped to a region. Droplets share a private IP range; traffic between them never leaves the DO fabric.
390404

405+
**What VPC is and is not.** A VPC is a network isolation layer - it gives your C2 node a private IP that only other Droplets in the same VPC can reach. It is not the channel you use to proxy C2 traffic; that is the redirector's job. The redirector (nginx, socat, Apache mod_proxy) forwards inbound HTTPS to the C2 over the private IP. No public firewall rule needed on the C2 node.
406+
407+
Three common approaches to route traffic from redirector to C2:
408+
409+
| Method | How it works | Notes |
410+
|---|---|---|
411+
| **DO VPC private IP** | Both nodes same region/VPC. nginx forwards to `10.x.x.x:port`. | Zero extra setup. Same region required. |
412+
| **WireGuard** | VPN tunnel between redirector and C2. C2 listens on `wg0` only. | Cross-provider, cross-region. Extra cloud-init setup. |
413+
| **SSH reverse tunnel** | C2 runs `ssh -R 8080:localhost:8080 user@redirector`. | Simple. Use autossh/systemd to survive disconnects. |
414+
391415
```
392-
Internet
393-
|
394-
[Redirector] 1.2.3.4:443 (public)
395-
|
396-
| VPC 10.20.0.0/24 (private, never reaches internet)
397-
|
398-
[C2 Server] 0 public ports for C2 protocol
416+
Internet
417+
|
418+
Agent HTTPS :443
419+
|
420+
[Redirector] 1.2.3.4 public: 80/443 open
421+
nginx proxy_pass http://10.20.0.2:443
422+
|
423+
VPC 10.20.0.0/24 (private, stays inside datacenter fabric)
424+
|
425+
[C2 Server] 10.20.0.2 no public C2 port
426+
public firewall: SSH only from operator IP
399427
```
400428

401429
```bash
@@ -407,6 +435,9 @@ do-manager vpc delete <id>
407435

408436
# Attach a Droplet to the VPC at creation time
409437
do-manager droplet create --name c2-node --vpc-uuid <id> ...
438+
439+
# Or let campaign create the VPC automatically
440+
do-manager campaign deploy --name op-ghost --vpc-auto ...
410441
```
411442

412443
---
@@ -415,6 +446,8 @@ do-manager droplet create --name c2-node --vpc-uuid <id> ...
415446

416447
Deploy and tear down a complete infrastructure campaign with a single command. A campaign groups all resources under the tag `campaign:<name>`.
417448

449+
The campaign lifecycle exists because Red Team infra has a specific tempo: provision fast, rotate IPs when they get burned, rebuild compromised nodes without disrupting the rest, tear down cleanly at the end. `campaign deploy` creates Droplets, firewall, and reserved IPs in the right order and tags everything. `campaign destroy` deletes all of it in one shot. Nothing left behind.
450+
418451
#### Simple (single role)
419452

420453
```bash

0 commit comments

Comments
 (0)