arn-c0de / arn-c0de/ESP32-LABs

ESP32 Red/Blue Team Lab – Gameplay & Defense Mechanics

Open
#1 0 comments 0 reactions 0 assignees View on GitHub
documentation enhancement
Dominant language
C++
Stars
8
Forks
0
PR merge metrics
No merged PRs in 30d

Description

- Every lab shares identical defense mechanics, command syntax (iptables/tc/session-like), and JSON automation format.
- ESP32 acts as central simulated "server/host".
- **No real kernel-level changes**, no real packet filtering — everything is simulated at the application level (HTTP, WebSocket, Telnet, etc.).
- Purely **educational** — never use in production or on real/connected networks.

## Core Game Principles

- Blue Team cannot block everything → defenses cost **DP** (Defense Points) and reduce **SS** (Stability Score) when overused.
- Red Team must choose smart vectors and timing under **AP** (Actions Per round/window) constraints.
- Time-limited rounds + per-defense cooldowns create realistic pressure.
- All parameters (DP/AP/SS costs, durations, cooldowns) are **configurable** and **persist** across reboots.

## Core Concepts & Resources

| Resource | Meaning | Default | Notes |
|-------------------|--------------------------------------|---------|-------|
| DP | Defense Points budget | 100 | Spent when activating defenses |
| AP | Max actions per round / time window | 2 | Global limit on defense activations |
| SS | Stability Score (system health) | 100 | Reduced by aggressive/high-cost defenses |

## Supported Defenses

| Defense Type | Command Alias | DP Cost | AP Cost | Default Duration | Default Cooldown | Side Effects / Notes |
|-------------------|---------------|---------|---------|------------------|------------------|----------------------|
| IP Block | iptables DROP | 15 | 1 | 30 s | 60 s | Blocks all traffic from IP/subnet |
| Rate Limit | tc rate-limit | 10 | 1 | 60 s | 30 s | Limits requests per second from src |
| Session Reset | session reset | 25 | 1 | immediate | 90 s | Forces disconnect (closes WS/Telnet) |
| Mistrust Mode | mistrust mode | 40 | 2 | 300 s | 600 s | Log-only / observe mode + extra logging |

All values configurable via `defense config set ...`

## Command Interfaces

### Human-readable (single-line, iptables/tc/session style)

Examples:

```bash
# Add IP block
iptables -A INPUT -s 192.168.4.100 -j DROP --duration 30 --dp 15 --ap 1 --id req-01

# Remove by id
iptables -D INPUT -s 192.168.4.100 -j DROP --id req-01

# Rate limit subnet to 10 req/s
tc qdisc add rate-limit --src 192.168.4.0/24 --rps 10 --duration 60 --dp 10 --id req-02

# Delete rate limit rule
tc qdisc del rate-limit --src 192.168.4.0/24 --id req-02

# Force session reset
session reset --ip 192.168.4.101 --reason "suspect" --dp 25 --id req-03

# Show rules
iptables -L
tc qdisc show

# Config management
defense status
defense config set dp=80 ap=3 stability=90
defense config show
```

### JSON (single-line, machine-readable)

**Add IP block example** (one line):

```json
{"action":"add","type":"ipblock","chain":"INPUT","src":"192.168.4.100","jump":"DROP","duration":45,"dp":15,"ap":1,"id":"req-17"}
```

**Remove example**:

```json
{"action":"del","type":"ipblock","id":"req-01"}
```

**Config example**:

```json
{"action":"config","set":{"dp":90,"ap":2,"stability":85}}
```

**Typical response** (mirror input style — human or JSON):

Human:

```
Rule req-01 added: DROP from 192.168.4.100 for 30s (DP-15, AP-1)
```

JSON:

```json
{"status":"ok","id":"req-01","message":"Rule added","remaining_dp":85,"remaining_ap":1}
```

Error example:

```json
{"status":"error","code":"insufficient_dp","message":"Need 15 DP, only 10 remaining"}
```

## Implementation Outline (15_Defense.ino)

### Main Classes / Structures

```cpp
// In 15_Defense.h / .ino

#include
#include
#include
#include

enum DefenseType { IP_BLOCK, RATE_LIMIT, SESSION_RESET, MISTRUST_MODE };

struct DefenseRule {
String id; // unique request id
DefenseType type;
IPAddress src; // or subnet start
uint8_t subnet; // CIDR (0 = single IP)
String jump; // DROP, REJECT etc (mostly cosmetic)
uint32_t startTime;
uint32_t duration; // seconds (0 = permanent, rare)
uint32_t cooldownEnd; // when rule can be re-added
uint8_t dpCost;
uint8_t apCost;
String reason; // for session reset
// ... rate limit specific fields (rps etc)
};

class DefenseManager {
public:
bool begin();
bool applyDefense(const String &cmdLine); // human or JSON
bool removeDefense(const String &id);
bool isIpBlocked(IPAddress ip);
bool checkRateLimit(IPAddress ip); // returns true = allow
void forceSessionReset(IPAddress ip, const String &reason);
void tick(); // call from main loop ~every second

String getStatusHuman();
String getStatusJson();
void loadConfig();
void saveConfig();

// config values
int dpRemaining = 100;
int apPerWindow = 2;
int stability = 100;
// ... per-type defaults/cooldowns

private:
std::vector activeRules;
std::set recentIds; // last N for idempotency (~50)
Preferences prefs;
// helper parsers
bool parseHumanCommand(const String &line);
bool parseJsonCommand(const String &line);
bool canAfford(uint8_t dp, uint8_t ap);
void deductCosts(uint8_t dp, uint8_t ap);
void broadcastEvent(const String &msg); // ws.textAll + Serial
};
```

### Integration Points

1. **Serial command handler** (`12_Debug.ino`):

```cpp
void handleSerialCommands() {
if (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim();
if (line.length() == 0) return;

if (line.startsWith("{")) {
// JSON → DefenseManager → JSON reply
String reply = defenseManager.applyDefense(line) ? ... : ...;
Serial.println(reply);
} else {
// human command → DefenseManager → human reply
String reply = defenseManager.applyDefense(line);
Serial.println(reply);
}
}
}
```

2. **Enforcement hooks** (application layer only):

- `03_WebServer.ino` — in request handler (early):

```cpp
if (defenseManager.isIpBlocked(client.remoteIP())) {
client.send(403, "text/plain", "Blocked by defense rule");
return;
}
if (!defenseManager.checkRateLimit(client.remoteIP())) {
// throttle or 429
}
```

- `07_WebSocket.ino` — on new connection / message:

Similar IP block / rate limit check → close if needed.

- `08_Telnet.ino` — on connect / before command:

Block or reset session.

3. **Tick loop** (main `loop()` or timer):

```cpp
static uint32_t lastTick = 0;
if (millis() - lastTick >= 1000) {
defenseManager.tick(); // expire rules, cooldowns, etc.
lastTick = millis();
}
```

4. **Persistence**:

- **Preferences**: store scalars (`dp`, `ap`, `stability`, per-type defaults)
- **LittleFS**: `/defense.json` — full rules + recent ids (atomic write: write to temp → rename)

5. **Idempotency**:

Store last 50–100 ids. If `id` already seen → ignore or reply "already processed".

6. **Events**:

```cpp
void DefenseManager::broadcastEvent(const String &msg) {
ws.textAll(msg); // if WebSocket active
Serial.println("[DEF] " + msg);
}
```

## Safety & Ethics Reminders (README)

- **Simulation only** — application-layer checks, **no** real firewall/tc/iptables.
- **Isolated network required** — never connect lab ESP32s to internet or shared LAN.
- Educational purpose: classrooms, CTF-style labs, red/blue exercises.
- Explicit warning: do **not** use outside controlled environments.

Contributor guide

Open the contributing guide

Research direction

Start by reading the proposed DefenseManager in 15_Defense.h/.ino, then trace command handling in 12_Debug.ino and enforcement hooks in 03_WebServer.ino, 07_WebSocket.ino, and 08_Telnet.ino. Done means the simulated defenses, human and JSON commands, resource limits, ticking, persistence, idempotency, events, and safety guidance work together without real kernel or packet-filtering changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
arduino, cpp
Domain
embedded-iot, game-dev, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.