Phase 4: DDoS + Bot Detection + Capstone (Days 91–120)
Phase Goal: Add the final security layers: DDoS mitigation and bot detection. Then build the capstone — a production-ready, single-binary security proxy.
Week 13: DDoS Detection & Mitigation (Days 91–98)
Why this week matters: DDoS attacks are the most common attack against internet-facing services. Understanding the mechanics helps you configure DDoS protection services (Cloudflare, AWS Shield, Akamai) well and build your own first line of defense.
Day 91 — DDoS taxonomy
- Why: "We're under DDoS" has a very different response depending on the attack type. L3/L4 volumetric vs L7 application attacks require different mitigations
- Topic: Volumetric (bandwidth exhaustion), Protocol (SYN flood, connection exhaustion), Application (HTTP flood, slowloris, slow POST), Amplification (UDP reflection — DNS, NTP, memcached)
- Exercise: For each DDoS type, write a Go program that simulates the attack pattern (at small scale, against localhost): (1) TCP connection flood (10k connections, no data), (2) HTTP flood (1000 req/s), (3) slowloris (100 connections, headers drip at 1 byte/sec).
Day 92 — Rate limiting algorithms (deep dive)
- Why: Token bucket vs sliding window have different behavior under bursty traffic. The right algorithm for DDoS is different from the right algorithm for API rate limiting
- Topic: Fixed window (fast, inaccurate at boundaries), sliding window log (accurate, memory heavy), sliding window counter (approximation, memory efficient), token bucket (allows burst), leaky bucket (smooths traffic)
- Exercise: Implement all 5. Test with a traffic pattern: 100 req/s normally, spike to 1000 req/s for 5 seconds, back to 100. Which algorithms block the spike cleanly? Which have boundary issues? Which allow the most burst?
Day 93 — Per-IP rate limiting with CIDR awareness
- Why: DDoS attackers use IP ranges (ASNs), not just single IPs. Rate limiting by /24 or /16 blocks more attack traffic
- Topic: Per-IP counters (
sync.Map), CIDR matching (net.IPNet), X-Forwarded-For extraction (with trust chain), IPv6 considerations (/48 prefix grouping), counter expiry (memory cleanup) - Exercise: Build per-IP and per-/24-subnet rate limiting. Handle both IPv4 and IPv6. Extract real IP from
X-Forwarded-For(trust only 1 hop). Clean up expired counters with a background goroutine. Test with 1000 unique IPs.
Day 94 — SYN flood defense
- Why: SYN floods are still the most common L4 DDoS. Understanding them helps you configure
net.ipv4.tcp_syncookiesand size your TCP backlog - Topic: SYN cookie concept, half-open connection limits, accept queue limits, Go-side defense (limit concurrent
Acceptgoroutines, connection per IP limit), backlog tuning - Exercise: Implement connection-level SYN flood defense: max 5 half-open connections per source IP (track IPs that connected but haven't sent data yet). Drain half-open connections after 3s. Track and expose metrics.
Day 95 — Slowloris defense
- Why: Slowloris can take down Apache/nginx with a single machine. Go's
ReadHeaderTimeoutpartially defends against it, but you need to detect and block the source IP too - Topic: Slowloris mechanics (send headers slowly, keep connection open), detection (header arrival rate < threshold),
ReadHeaderTimeoutis not enough (attackers rotate), connection rate per IP - Exercise: Build slowloris detection: track bytes received per second per connection. If a connection sends < 50 bytes/second during header phase for > 5 seconds, classify as slowloris, close connection, add source IP to block list (5-minute expiry).
Day 96 — Traffic analysis & anomaly detection
- Why: DDoS traffic often looks legitimate at the request level but anomalous at the traffic level (too many requests from one IP, unusual user-agents, single endpoint targeted). Statistical detection is more accurate than static thresholds
- Topic: Sliding window request rates (per-IP, per-path, global), baseline estimation, z-score anomaly detection, exponential moving average
- Exercise: Build a traffic analyzer: maintain per-IP request rate with sliding window (60s). Compute global mean and stddev using exponential moving average. Flag IPs > 3 stddev above mean. Emit alert with IP, rate, and deviation score.
Day 97 — IP blocking & challenges
- Why: Outright blocking causes false positives. Challenges (CAPTCHA-like, PoW) let legitimate traffic through while slowing bots. Understanding the tradeoff is a product decision
- Topic: IP blocklist (
sync.Map+ expiry),429 Too Many RequestswithRetry-After, proof-of-work challenge (SHA256 puzzle), challenge verification, whitelist (trusted CIDRs bypass) - Exercise: Build a tiered response: (1) suspected IPs (score 50–80): 429 + SHA256 PoW challenge, (2) confirmed attackers (score > 80): 403 block for 5 minutes, (3) trusted IPs: bypass. Implement PoW: server issues random challenge, client must find nonce such that SHA256(challenge+nonce) has N leading zero bits.
Day 98 — UDP amplification defense
- Why: NTP, DNS, and memcached amplification attacks are still common. Understanding the mechanics helps you design UDP services that can't be weaponized
- Topic: Amplification factor (response >> request size), rate limiting UDP responses per source IP, response size caps, requiring handshake (challenge-response) before large responses
- Exercise: Build a UDP service with anti-amplification: (1) response size cap (response ≤ 1.5× request size), (2) rate limit responses per source IP (10/sec), (3) reject requests that trigger > 2 rate limit violations (add to block list). Measure: can your service be used for amplification?
Week 13 Mini Project: DDoS Mitigation Layer
- Build a complete DDoS mitigation proxy:
- Per-IP and per-/24 rate limiting (token bucket, sliding window)
- Slowloris detection (byte rate per connection)
- SYN flood defense (per-IP half-open connection limit)
- Traffic anomaly detection (z-score, EMA baseline)
- Tiered response: challenge (PoW) → block → whitelist
- IP blocklist with expiry (
sync.Map, background cleanup) - Real-time stats:
/debug/ddos(top IPs, current block list, attack status, request rates by source) - CIDR whitelist (bypass mitigation for trusted ranges)
- Integrate with
ThreatIntelstore from Phase 3
- Key packages:
net,net/http,sync,sync/atomic,crypto/sha256,time,net(IPNet) - Engineer Takeaway: Cloudflare Magic Transit, AWS Shield Advanced, and Akamai Prolexic implement this logic at 100Tbps scale. You've now built the core algorithms from scratch.
Week 14: Bot Detection (Days 99–105)
Why this week matters: Bot traffic accounts for 40–50% of internet traffic. Bots scrape prices, credential-stuff accounts, and abuse APIs. Bot detection is a multi-signal problem that requires understanding both network behavior and application behavior.
Day 99 — Bot taxonomy & signal framework
- Why: Not all bots are bad (Googlebot is welcome, scrapers are not). Signal-based detection with configurable thresholds lets you tune aggression. Understanding signals helps you integrate and tune bot detection products (Cloudflare Bot Management, DataDome, PerimeterX)
- Topic: Bot types: simple HTTP clients, headless browsers (Puppeteer/Playwright), residential proxy bots, human-like bots. Signal categories: network signals (IP, ASN, TLS), HTTP signals (headers, timing), behavioral signals (session patterns)
- Exercise: Design a
BotSignalscoring system:type Signal struct { Name string; Weight float64; Category string }. ImplementBotScorerthat accumulates signals for each request/session. Score > threshold → challenge/block.
Day 100 — HTTP header fingerprinting
- Why: Real browsers send headers in a consistent order with specific values. Bots often send wrong Accept headers, missing Accept-Language, or User-Agents that don't match the Accept-Encoding
- Topic: Browser header consistency (Chrome always sends headers in the same order), User-Agent parsing, Accept-Encoding consistency (Chrome never sends
compress), Accept-Language presence - Exercise: Build a header consistency scorer: for each User-Agent claiming to be a specific browser, check: (1) Accept-Encoding matches expected values, (2) Accept-Language is present, (3) header count is within normal range. Score anomalies.
Day 101 — TLS fingerprinting (JA3)
- Why: JA3 fingerprints the TLS ClientHello — cipher suites, extensions, elliptic curves. Real Chrome has a specific JA3.
curland Pythonrequestshave different JA3s. This is hard to fake without modifying the TLS stack - Topic: TLS ClientHello structure (cipher suites, extensions list, elliptic curves, EC point formats), JA3 algorithm (sort + join → MD5), known JA3 hashes for Chrome/Firefox/curl
- Exercise: Implement JA3 fingerprinting: intercept TLS ClientHello via
tls.Config.GetConfigForClient(which receives*tls.ClientHelloInfo). Compute JA3 hash. Compare against known hashes for major browsers. Flag non-browser TLS stacks.
Day 102 — Session behavioral analysis
- Why: Bots interact with APIs in non-human patterns: too fast, no referrer chain, no session depth, single endpoint focus. Session tracking exposes these patterns
- Topic: Session tracking (session ID via cookie or token), request velocity (requests/second), path diversity (how many unique paths in session), referrer chain (direct API calls vs navigation)
- Exercise: Build a session tracker: per session, track: request count, unique paths, requests/second (sliding window), referrer presence rate. Score sessions with: velocity > 10 req/s (+20), referrer missing > 80% (+15), path diversity < 2 paths (+10).
Day 103 — IP reputation & ASN classification
- Why: Bots disproportionately originate from cloud provider IPs (AWS, GCP, Azure, DigitalOcean) and residential proxy networks. IP classification gives a strong first-pass signal
- Topic: ASN-to-IP CIDR mapping (embedded hardcoded ranges), datacenter IP classification, residential proxy patterns, VPN exit node indicators
- Exercise: Build an IP classifier: embed CIDR ranges for major cloud providers (AWS:
3.0.0.0/8, etc. — hardcode a representative subset). Score requests: datacenter IP (+15), known hosting provider (+20). Also detect: IPv6-only requests from unusual ASNs.
Day 104 — Proof-of-work & invisible challenges
- Why: PoW is a cost-imposing challenge — it slows bots without blocking legitimate users. It works because bots can't amortize computational cost across many requests the way they amortize network cost
- Topic: PoW challenge mechanics (SHA256 hash puzzle), difficulty levels (leading zero bits), challenge issuance (signed by server, time-limited), validation, re-challenge on failure
- Exercise: Build a PoW challenge system:
GET /challengereturns{challenge, difficulty, expires}(challenge is random bytes, signed with HMAC-SHA256). Client sendsPOST /verifywith{challenge, nonce}. Server verifies SHA256(challenge+nonce) hasdifficultyleading zero bits. Issue session cookie on success.
Day 105 — Bot mitigation strategies
- Why: Hard blocking bots causes false positives. Tiered mitigation (slow → challenge → block) reduces false positives while still raising the cost for bots
- Topic: Slow response (artificial
time.Sleepfor suspected bots), shadow-ban (return fake200 OKwith empty data), honeypot (hidden endpoint that only bots call), hard block - Exercise: Implement tiered bot mitigation: (1) score 20–40: add 500ms artificial delay, (2) score 40–70: serve PoW challenge, (3) score > 70: block with
403, (4) honeypot: any IP that hits/api/hiddengets score +100. Implement shadow-ban endpoint that returns200 OKwith plausible but empty data.
Week 14 Mini Project: Bot Detection Engine
- Build a complete bot detection middleware:
- Header consistency fingerprinting
- JA3-like TLS fingerprinting (via
tls.ClientHelloInfo) - Session behavioral scoring (velocity, path diversity, referrer rate)
- IP ASN classification (datacenter CIDR list)
- PoW challenge issuance and verification
- Honeypot endpoint (flags IP permanently)
- Tiered mitigation: delay → challenge → block
- Dashboard:
/debug/bots(scores, flagged sessions, challenge success/fail rates, top bot IPs) - Integrate with
ThreatIntelstore
- Key packages:
crypto/tls,net,net/http,crypto/md5,crypto/sha256,sync,time - Engineer Takeaway: DataDome and PerimeterX sell bot detection as a product. You now understand their core algorithms, so you can integrate them, tune them, and know when a simple in-house detector is enough.
Week 15: Production Hardening (Days 106–112)
Why this week matters: Software that works on your laptop is not production software. This week is about the operational characteristics that matter at scale.
Day 106 — Health checks & readiness
- Why: Kubernetes uses liveness and readiness probes to route traffic and restart unhealthy pods. Getting these right prevents cascading failures
- Topic: Liveness (is the process alive and not deadlocked?), readiness (is the service ready to serve traffic — upstream connections established?), startup probe (allow slow startup),
/healthz,/readyz - Exercise: Build a health check framework: each subsystem registers a
Check func(ctx context.Context) error./healthzruns all checks with 2s timeout per check, returns JSON with per-check status./readyzchecks upstream connectivity.
Day 107 — Multi-stage graceful shutdown
- Why:
kill -9drops connections.SIGTERMshould drain connections gracefully. Getting shutdown right prevents data loss and user-visible errors - Topic: 3-stage shutdown: (1) stop accepting new connections/requests, (2) wait for in-flight to complete (with timeout budget), (3) force-close remaining.
sync.WaitGroupfor in-flight tracking. Signal handling. - Exercise: Build a complete 3-stage shutdown sequence:
SIGTERM/SIGINTtriggers stage 1 (10s budget), then stage 2 (30s budget), then force-close. Log each stage. Test: send requests, send SIGTERM mid-flight, observe graceful drain.
Day 108 — Signal handling & operational controls
- Why: Operations teams need runtime controls without restarts: reload config, rotate logs, dump goroutine stack for debugging. These are table-stakes for production services
- Topic:
SIGHUP(reload config),SIGUSR1(rotate logs),SIGUSR2(dump goroutine stack to log),SIGTERM(graceful shutdown),signal.Notify+ goroutine dispatch - Exercise: Add signal handlers to the gateway:
SIGHUP→ reload config from file,SIGUSR1→ rotate log file,SIGUSR2→runtime.Stackdump to log. Test each signal.
Day 109 — Observability: traces & spans
- Why: Distributed tracing (Jaeger, Zipkin, Datadog APM) is how you debug latency across microservices. Understanding the W3C Trace Context standard helps you integrate with your observability stack
- Topic: W3C Trace Context (
traceparentheader format:version-traceid-parentid-flags), span lifecycle (start, add attributes, end), context propagation, in-memory trace store - Exercise: Build a manual tracer: inject
traceparenton ingress (or propagate incoming), create child spans for each middleware, record spans in memory (ring buffer of last 1000 traces). Expose at/debug/tracesas JSON.
Day 110 — Chaos engineering
- Why: Systems fail in unexpected ways. Chaos engineering (random failures in test) reveals brittleness before production does
- Topic: Fault injection (random errors), latency injection (random delays), circuit breaker pattern (open after N failures, half-open after timeout, close after M successes)
- Exercise: Build a chaos middleware: configurable fault injection (5% chance of
500, 2% chance of random delay 100–2000ms, 1% chance of connection close). Build a circuit breaker: open after 5 failures in 10s, half-open after 30s (pass 1 request), close after 2 successes.
Day 111 — Memory & goroutine leak hunting
- Why: Memory leaks and goroutine leaks turn a 99.9% uptime service into a service that needs weekly restarts. Production services must not leak
- Topic: Goroutine leak patterns (goroutine waiting on unbuffered channel with no sender, goroutine whose context is never cancelled), heap leak patterns (growing
sync.Map, unbounded slices),runtime.Stack,pprofheap diff - Exercise: Audit all projects: (1) run load test, (2) after load, check
runtime.NumGoroutine()— should return to baseline in 10s, (3) compare heap before and after load test using/debug/pprof/heap. Find and fix any leaks.
Day 112 — Zero-downtime deployment
- Why: Deployments that drop connections cause user-visible errors. Zero-downtime deployment is a production requirement for high-traffic services
- Topic: Listener FD inheritance (old process passes listener FD to new process via
os.StartProcess),SO_REUSEPORT(multiple processes share port), graceful handoff, connection draining - Exercise: Implement FD inheritance: old server, on
SIGUSR1, starts new server process with listener FD inExtraFiles. New server starts serving. Old server drains and exits. No connections dropped.
Week 15 Mini Project: Production-Hardened Gateway
- Take the Week 12 Unified Security Proxy and add:
- Health check framework (
/healthz,/readyz) with per-subsystem checks - 3-stage graceful shutdown
- Signal handlers (SIGHUP, SIGUSR1, SIGUSR2, SIGTERM)
- W3C trace context propagation with span recording
- Chaos middleware (configurable, off by default)
- Goroutine and memory leak validation (automated test)
- FD inheritance for zero-downtime restart
- Health check framework (
- Key packages: All stdlib
- Engineer Takeaway: This is what separates "software that works" from "production software." SRE teams live and die by these operational characteristics.
Week 16: Advanced Integration + Capstone Prep (Days 113–119)
Day 113 — End-to-end attack simulation
- Why: You've built each defense in isolation. Testing the integrated stack against real attack scenarios is how you know it actually works
- Topic: Attack playbook: SQLi, XSS, path traversal, credential stuffing, SYN flood, HTTP flood, slowloris, bot scraping
- Exercise: Write an attack simulator: 8 goroutines, each running a different attack type against the full integrated stack. Verify: each attack is detected, correct mitigation applied (block vs challenge vs rate limit), no false positives for legitimate traffic interleaved.
Day 114 — Performance profiling the full stack
- Why: Security middleware adds overhead. Every millisecond of added latency is a business cost. Knowing the actual overhead helps you tune and justify
- Topic: Per-middleware latency measurement, allocation profiling (per middleware), CPU flame graph interpretation, hot path optimization with
sync.Pool - Exercise: Profile the full middleware chain under load (500 concurrent clients). Measure p50/p95/p99 latency contribution per layer. Find the 2 highest-latency middleware. Optimize each (reduce allocations, pre-compile regex). Re-measure.
Day 115 — Security audit of your own code
- Why: Adversarial review of your own code is how you build the habit of writing secure code from the start
- Topic: Timing attacks (auth paths), integer overflow (packet parsers), goroutine leak under attack (deliberate goroutine exhaustion), information leakage in error messages
- Exercise: Audit: (1) all auth paths use
subtle.ConstantTimeCompare, (2) all packet parsers check bounds before indexing, (3) error messages to clients contain no internal details (IP, stack trace, file paths), (4) no goroutine is started without a clear exit condition.
Day 116 — Test coverage audit
- Why: Coverage numbers are metrics. Below 80% on security-critical code is a risk. Knowing what's untested helps you prioritize test writing
- Topic:
go test -cover,go test -coverprofile,go tool cover -html, identifying uncovered security paths (bypass conditions, error paths) - Exercise: Run coverage on all projects. For any security-critical file (WAF rules, auth, rate limiting, bot detection) below 80% — write tests to reach 80%. Focus on negative paths (what blocks the attack).
Day 117 — Fuzz testing critical parsers
- Why: WAF normalization pipelines and binary protocol parsers are exactly the code fuzzing was designed to test. A panic in your WAF is a denial-of-service
- Topic:
testing/fuzzfor parsers, seed corpus design, interpreting fuzz failures, fixing panics safely (bounds check, recover) - Exercise: Write fuzz tests for: (1) WAF normalization pipeline, (2) JA3 TLS fingerprint parser, (3) binary protocol parser from Week 8. Run each for 60 seconds with
go test -fuzz -fuzztime=60s. Fix any panics.
Day 118 — Documentation & architecture review
- Why: Code you can't explain to your teammates is a liability. Architecture documentation is how you transfer knowledge
- Topic: ASCII architecture diagrams, package-level documentation (
doc.go), decision records (why token bucket vs sliding window for rate limiting?), runbook for each operational control - Exercise: Write an architecture document for the full security proxy: ASCII diagram of all layers, description of each module, key design decisions with rationale, runbook: how to add a new WAF rule, how to block an IP, how to reload config.
Day 119 — Capstone preparation
- Final integration: wire all components
- Run:
go build ./...,go vet ./...,go test -race ./... - Fix all warnings and race conditions
- Run the attack simulator (Day 113) against the fully integrated system
- Final performance baseline: RPS at p99 < 10ms overhead
Day 120 — Capstone: Cloud-Edge Security Proxy
Build a production-ready, single-binary security proxy that demonstrates every skill from 120 days:
Internet → [L4: mTLS + SNI + Rate Limit + Circuit Breaker]
→ [L7: HTTP/2 + Bot Detection + DDoS Mitigation]
→ [Security: WAF + API Auth + Schema Validation]
→ [Observability: slog + expvar + pprof + Traces]
→ [Upstream: Reverse Proxy]
Requirements checklist:
Transport & L4:
- TLS termination (TLS 1.2 minimum, TLS 1.3 preferred)
- mTLS support (client cert required for internal services)
- SNI routing (different backends by hostname)
- Cert hot-reload (SIGHUP, no dropped connections)
- L4 connection rate limiting (per-IP, global)
- Circuit breaker per backend
Bot Detection:
- HTTP header consistency fingerprinting
- JA3-like TLS fingerprint (via
tls.ClientHelloInfo) - Session behavioral scoring (velocity, path diversity)
- IP ASN classification (datacenter vs residential)
- PoW challenge for suspected bots
- Honeypot endpoint
DDoS Mitigation:
- Token bucket rate limiting (per-IP, per-/24 subnet)
- Slowloris detection (byte rate per connection)
- SYN flood defense (per-IP half-open limit)
- Traffic anomaly detection (z-score, EMA)
- IP blocklist with auto-expiry
- Tiered response: challenge → block
WAF:
- Multi-layer normalization (URL-decode → HTML-unescape → lowercase)
- SQLi detection (scoring)
- XSS detection (scoring)
- Path traversal detection (immediate block)
- Command injection detection (immediate block)
- Body inspection (JSON + form, up to 1MB)
- CIDR allow-list bypass
API Security:
- ECDSA-signed token auth
- HMAC request signing validation
- Per-API-key rate limiting (token bucket)
- JSON schema validation per route
- Input validation (struct tags)
- Response PII scrubber
- CORS (strict origin allowlist)
- Security headers (HSTS, CSP, X-Frame-Options)
Observability & Operations:
- Structured logging (
log/slog, JSON, correlation IDs) -
expvarmetrics (requests, errors, latency percentiles, blocked IPs) - pprof endpoints (
/debug/pprof) - Manual trace context (W3C
traceparent) - Health checks (
/healthz,/readyz, per-subsystem) - 3-stage graceful shutdown
- Signal handlers (SIGHUP: config reload, SIGUSR1: log rotate, SIGUSR2: goroutine dump)
- Zero-downtime restart (FD inheritance)
- Chaos middleware (configurable fault injection)
Quality:
-
go test -race ./...— zero races - Security-critical packages: >80% test coverage
- Fuzz tests: WAF normalization, JA3 parser, schema validator
- Load test: 500 concurrent clients, p99 overhead < 10ms
Deliverable: Single binary, ~4000–6000 lines of Go, zero external dependencies.