Hybrid edge-to-cloud SSH honeypot pipeline. A Cowrie honeypot at the network edge captured real-world attacks over a 14-day run, shipped logs through a serverless AWS pipeline, and rendered attack telemetry in a React dashboard. The AWS pipeline and dashboard remain live; the edge sensor has been decommissioned after its collection run.
autossh holds a persistent reverse SSH tunnel to a DigitalOcean droplet running HAProxy as the public ingress. Home IP stays private; attackers hit the droplet.127.0.0.1 because of the reverse tunnel. The ingest Lambda joins each Cowrie session to the corresponding HAProxy log line on a 500ms window (empirically widened from a 200ms baseline after measuring real-traffic handshake latency — see ADR-010), recovering the real source IP. Enriched with MaxMind GeoLite2 Country + ASN.sigma-validate.yml. Real-attacker-fixture corpus with sanitization enforced by ADR-005 (password strip, RFC 5737 doc-IP swap for the maintainer’s home IP).cowrie-heartbeat-missing and haproxy-heartbeat-missing (15-min window, treat_missing_data: breaching). 9 ADRs documenting the design trade-offs.345gs5662d34), SSH-key implant persistence, crypto-mining reconnaissance, and automated Go / libssh scanners. Top origins: Netherlands, Uzbekistan, United States (374 IPs), Hong Kong, Germany. Raw events archived to S3; correlated + GeoIP-enriched in DynamoDB.Portfolio + design case study for Tokyo Zero. Astro static frontend, palette + typography writeup at /process. Underneath: a multi-region serverless AWS stack — CloudFront with origin-group failover, hourly Puppeteer canary, nightly digest Lambda writing live JSON to /status and /insights. All Terraform, one apply.
// case study · cloud
user
│
▼
┌────────────┐ ┌────────────────┐
│ cloudflare │ │ acm (us-east-1) │
│ dns │ │ wildcard cert │
└──────┬──────┘ └───────┬────────┘
│ │
▼ ▼
┌───────────────────────────────────────┐
│ cloudfront (us-west-2) │
│ · origin group (failover on 5xx/403) │
│ · viewer-request rewrite fn │
│ · security-headers policy │
└────┬─────────────────────────┬───────┘
│ │
GET * │ │ POST /contact
▼ ▼
┌──────────────┐ ┌────────────────┐
│ s3 primary │ │ http api v2 │
│ us-west-2 │ │ api gateway │
└──────┬───────┘ └───────┬───────┘
│ crr (async) │
▼ ▼
┌──────────────┐ ┌────────────────┐
│ s3 dr │ │ lambda │
│ us-east-1 │ │ (node 20) │
└──────────────┘ └──┬────────┬────┘
│ │
▼ ▼
┌────────┐ ┌────────────┐
│ ses │ │ dynamodb │
│ send │ │ audit │
└────────┘ └────────────┘
observability plane
────────────────────
synthetics canary ─ 3 endpoints, hourly, us-west-2 ─▶ cloudwatch alarms
x-ray tracing ─ lambda + api gw + digest lambda ─▶ trace map
eventbridge sched ─ nightly 03:00 utc ─▶ digest lambda
digest lambda ─ synthetics + athena
─▶ json → s3 (primary + dr) → /status /insights
Cloudflare DNS → CloudFront (OAC, security headers, viewer-request URL rewrite) → S3 primary in us-west-2, cross-region replicated to a DR bucket in us-east-1. Origin group flips to DR on 5xx/timeout — no DNS change. Contact form: API GW HTTP v2 → Node 20 Lambda → DynamoDB audit + SES send. Observability: hourly Synthetics canary + nightly EventBridge → digest Lambda → Athena over CloudFront logs → status.json + insights.json.
// services · purpose
| Service | Purpose | Why |
|---|---|---|
s3 | Origin bucket + DR replica + logs + Athena results. | Private, OAC-only reads. Cross-region replication to us-east-1 for a passive DR. |
cloudfront | HTTPS-terminating CDN + edge cache. | Origin group failover, security-headers policy, JS URL rewrite at the edge. |
acm | TLS cert in us-east-1 for CloudFront. | DNS-01 validated via a Cloudflare CNAME. |
api gateway v2 | Public POST /contact endpoint. | Lighter than REST. CORS enforced at the gateway so Lambda never sees preflights. |
lambda | Contact handler + nightly digest job. | Node 20 with X-Ray active tracing. IAM scoped tight per function. |
ses | Sends contact submissions to the owner. | Policy condition on ses:FromAddress blocks impersonation. |
dynamodb | Contact audit table + Terraform state lock. | Pay-per-request + PITR + encryption at rest. |
athena + glue | Analytics over CloudFront access logs. | Workgroup capped at 1 GB scanned per query. Saved queries in Terraform. |
synthetics | Puppeteer canary hitting 3 pages hourly. | Screenshots + timing + alarm on SuccessPercent < 100. |
eventbridge sched | Nightly cron for the digest Lambda. | Cleaner IAM model than legacy CloudWatch Events. |
x-ray | Distributed tracing across Lambda + API GW. | Request path shows up in the trace map when something breaks. |
cloudwatch logs | Lambda + HTTP API access logs. | 30-day retention on every group so nothing quietly creeps up. |
// stack
Self-hosted homelab environment, services platform, and continuous-deployment target — used to deepen hands-on networking, security, and infrastructure skills beyond what cloud-only environments offer.