Skip to content

Commit 58051a5

Browse files
authored
Merge pull request #1 from Whispergate/dev
[0.2.0] Native Cloud Support
2 parents 925136e + 384839d commit 58051a5

25 files changed

Lines changed: 860 additions & 21 deletions

README.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ InfraGuard sits between the internet and your C2 teamserver, validating every in
77
![Mythic Callbacks Xenon](/images/xenon_callback.png)
88
![InfraGuard Dashboard](/images/infraguard_dashboard.png)
99

10+
## Architecture
11+
12+
![Architecture Diagram](/images/InfraGuard%20Infrastructure%20Diagram.drawio.png)
13+
1014
## Features
1115

1216
- **Multi-domain proxying** -- proxy multiple domains simultaneously, each with independent C2 profiles, upstreams, and rules
@@ -25,6 +29,7 @@ InfraGuard sits between the internet and your C2 teamserver, validating every in
2529
- **Webhook alerts** -- built-in plugins for Discord (embeds), Slack (Block Kit), and generic webhook (Rocket.Chat, Mattermost, Teams)
2630
- **Plugin system** -- event-driven architecture with `on_event` hooks, per-plugin config, event filtering (only_blocked, min_score, domain include/exclude)
2731
- **Backend config generation** -- generate Nginx, Caddy, or Apache configs with full operator customization (TLS, IP filtering, header checks, aliases, custom headers)
32+
- **Edge proxies** -- lightweight Cloudflare Worker and AWS Lambda for domain fronting through CDN infrastructure, edge country blocking, and host rewriting
2833
- **Docker deployment** -- Dockerfile + docker-compose with optional Let's Encrypt, GeoIP downloader, and PwnDrop payload server
2934
- **GeoIP support** -- all three GeoLite2 databases (City, ASN, Country) with Docker auto-download
3035
- **Self-signed TLS fallback** -- auto-generates certificates when configured paths don't exist
@@ -637,6 +642,56 @@ When running with `infraguard dashboard`, the following REST API is available:
637642

638643
All API endpoints require an `Authorization: Bearer <token>` header when `auth_token` is configured.
639644

645+
## Cloudflare Worker Deployment
646+
647+
InfraGuard includes a lightweight Cloudflare Worker that acts as an edge reverse proxy, providing domain fronting through Cloudflare's CDN.
648+
649+
```
650+
Internet → [Cloudflare Edge Worker] → [InfraGuard Server on VPS] → [C2 Teamserver]
651+
```
652+
653+
From a network observer's perspective, all traffic goes to Cloudflare's IPs -- your server is never exposed.
654+
655+
```bash
656+
cd workers/infraguard-edge
657+
npm install -g wrangler
658+
wrangler login
659+
660+
# Edit wrangler.toml with your InfraGuard backend URL and domains
661+
npx wrangler deploy
662+
```
663+
664+
The Worker handles:
665+
- **Domain fronting** -- traffic appears to go to Cloudflare
666+
- **Edge country blocking** -- drop requests from banned countries at the edge
667+
- **Host rewriting** -- map Cloudflare domains to C2 profile Host headers
668+
- **Client IP injection** -- `X-Real-IP` / `X-Forwarded-For` with the real client IP
669+
670+
See [workers/infraguard-edge/README.md](workers/infraguard-edge/README.md) for full configuration.
671+
672+
## AWS Lambda Deployment
673+
674+
InfraGuard also includes an AWS Lambda edge proxy for domain fronting through CloudFront or Lambda Function URLs.
675+
676+
```bash
677+
cd workers/infraguard-lambda
678+
679+
# Deploy with SAM CLI
680+
sam build
681+
sam deploy --guided \
682+
--parameter-overrides \
683+
InfraGuardBackend=https://your-server:443 \
684+
AllowedHosts=cdn.example.com \
685+
BlockedCountries=CN,RU,KP
686+
```
687+
688+
Supports three deployment modes:
689+
- **Lambda Function URL** -- standalone HTTPS endpoint, simplest setup
690+
- **CloudFront + Lambda@Edge** -- full CDN with global edge distribution
691+
- **API Gateway + Lambda** -- HTTP API endpoint
692+
693+
Zero external dependencies (stdlib only). See [workers/infraguard-lambda/README.md](workers/infraguard-lambda/README.md) for full configuration.
694+
640695
## Docker Deployment
641696

642697
### Quick start
@@ -680,7 +735,7 @@ Requirements for Let's Encrypt:
680735
# Download all three GeoLite2 databases (City, ASN, Country)
681736
docker compose --profile geoip up geoip-update
682737

683-
# Then start normally databases are mounted at /app/geoip/
738+
# Then start normally - databases are mounted at /app/geoip/
684739
docker compose up -d proxy dashboard
685740
```
686741

@@ -768,6 +823,7 @@ infraguard/
768823
| Anti-replay | SQLite hash | In-memory with configurable window |
769824
| Drop actions | redirect, reset, proxy | redirect, reset, proxy, tarpit |
770825
| TLS management | Manual only | Auto self-signed + Let's Encrypt integration |
826+
| Edge deployment | None | Cloudflare Worker + AWS Lambda edge proxies with domain fronting |
771827
| Deployment | Manual | Docker Compose with health checks |
772828
| Logging | Custom colored output | Structured JSON (structlog) |
773829
| Async | Tornado callbacks | Native async/await (ASGI + uvicorn) |

config/pwndrop.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
;
44
; NOTE: The [setup] section below is consumed on FIRST RUN only.
55
; PwnDrop will automatically remove it from this file after creating
6-
; the admin account. This is normal do not add it back, or you'll
6+
; the admin account. This is normal - do not add it back, or you'll
77
; see "already exists" errors on restart.
88

99
[pwndrop]

images/InfraGuard Infrastructure Diagram.drawio

Lines changed: 106 additions & 0 deletions
Large diffs are not rendered by default.
352 KB
Loading

images/infraguard_icon.svg

Lines changed: 24 additions & 0 deletions
Loading

infraguard/core/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async def health_check(request: Request) -> Response:
4242
@asynccontextmanager
4343
async def lifespan(app: Starlette):
4444
await db.connect()
45-
# Start plugins (isolated one failure doesn't stop others)
45+
# Start plugins (isolated - one failure doesn't stop others)
4646
for p in plugins:
4747
try:
4848
await p.on_startup()

infraguard/core/content_router.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
"""Content route resolver matches request URIs to content delivery backends.
1+
"""Content route resolver - matches request URIs to content delivery backends.
22
33
Supports three pattern types:
4-
- Exact: ``/file.exe`` string equality
5-
- Prefix: ``/downloads/*`` startswith, captures remainder after prefix
6-
- Regex: ``~^/d/[a-f0-9]+`` leading ``~`` indicates regex
4+
- Exact: ``/file.exe`` - string equality
5+
- Prefix: ``/downloads/*`` - startswith, captures remainder after prefix
6+
- Regex: ``~^/d/[a-f0-9]+`` - leading ``~`` indicates regex
77
"""
88

99
from __future__ import annotations

infraguard/core/router.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def _build_filters(self) -> list:
114114
def _build_fingerprint_filters(self) -> list:
115115
"""Build a filter chain WITHOUT ProfileFilter and ReplayFilter.
116116
117-
Used for content route conditional delivery catches bots and
117+
Used for content route conditional delivery - catches bots and
118118
scanners without requiring C2 profile conformance.
119119
"""
120120
pc = self.config.pipeline
@@ -302,7 +302,7 @@ async def _handle_content_route(
302302
filter_score = fp_result.total_score
303303

304304
if filter_score >= content_config.conditional.score_threshold:
305-
# Scanner/bot detected serve decoy or redirect
305+
# Scanner/bot detected - serve decoy or redirect
306306
log.info(
307307
"content_blocked",
308308
domain=route.domain,

infraguard/core/tls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def resolve_tls_paths(
105105
log.info("tls_loaded", cert=str(cert_path))
106106
return str(cert_path), str(key_path)
107107

108-
# Certs not found generate self-signed
108+
# Certs not found - generate self-signed
109109
domain = domains[0] if domains else "localhost"
110110
log.warning(
111111
"tls_certs_not_found",

infraguard/intel/geoip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def __init__(
6565
except Exception:
6666
log.exception("geoip_load_error", type="country", path=country_db)
6767

68-
# ASN DB (separate provides ASN + org)
68+
# ASN DB (separate - provides ASN + org)
6969
if asn_db and Path(asn_db).exists():
7070
try:
7171
self._asn_reader = maxminddb.open_database(asn_db)

0 commit comments

Comments
 (0)