all work
infra/2023/archived

CTF Infrastructure

Docker-based infrastructure for hosting Capture the Flag competitions: isolated challenge environments, per-team instances, and a minimal scoreboard.

stack
  • Docker
  • Python
  • Nginx
  • SQLite

Overview

Infrastructure built for running small-to-medium CTF competitions. The design priority was isolation: every team gets its own challenge instance with no shared state. Exploiting one team's environment should not affect another's.

Architecture

Each challenge is a Docker image with a defined interface: a TCP port, an HTTP endpoint, or a shell. The orchestrator spins instances per team on demand and assigns random external ports mapped through Nginx.

[Team A] -> nginx:10001 -> challenge-a:team-1 (container)
[Team B] -> nginx:10002 -> challenge-a:team-2 (container)

A lightweight Python service manages the lifecycle: spawn on first connection, idle timeout after 30 minutes, hard limit of 2 hours per team per challenge.

Scoreboard

The scoreboard is intentionally minimal. A SQLite database, a Python backend, and a single-page frontend. No real-time websockets, no live leaderboard animations. Scores update on page refresh.

Flags are validated server-side against per-team HMAC-signed tokens generated at deployment. The flag for a given challenge is different for every team, which eliminates flag sharing between teams at the protocol level.

Lessons

The per-container model is more expensive than a shared process model but worth it for CTFs involving pwn challenges. One bad exploit should not take down the challenge for everyone else.

The SQLite + no-realtime-updates scoreboard held up fine for 60 concurrent teams. The overhead from Docker per-team instances was the actual bottleneck, not the database.