diff --git a/.gitignore b/.gitignore index b91f767..178dcc1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ build/ *.so # Logs *.log +# Reports +reports/ diff --git a/01_install.sh b/01_install.sh index f90731d..1b88085 100644 --- a/01_install.sh +++ b/01_install.sh @@ -20,7 +20,7 @@ AP_IFACE="wlan0" # WiFi interface used as AP (internal hotspot) WAN_IFACE="eth0" # LAN port = uplink from ISP router/switch AP_SSID="PiGateway" -AP_PASS="SuperSecret99" # ← Change this! +AP_PASS="SuperSecret99" # ← CHANGE THIS before production deployment! AP_CHANNEL=6 AP_IP="192.168.50.1" AP_SUBNET="192.168.50.0/24" @@ -30,12 +30,12 @@ AP_COUNTRY="US" # ← Set your 2-letter country code (regulatory domai WARP_MTU=1280 DASHBOARD_PORT=5000 -BOT_TOKEN="" # Set after install or in /etc/EdgeGateway/config.env +BOT_TOKEN="" # Set after install or in /etc/WarpGate/config.env ADMIN_CHAT_ID="" # Your Telegram chat ID # ── Persist config ──────────────────────────────────────── -mkdir -p /etc/EdgeGateway -cat > /etc/EdgeGateway/config.env < /etc/WarpGate/config.env < /usr/local/bin/gw-stats.sh <<'STATS' set -o pipefail # Source config for interface names -source /etc/EdgeGateway/config.env 2>/dev/null +source /etc/WarpGate/config.env 2>/dev/null # Fallback defaults if config didn't load : "${WAN_IFACE:=eth0}" @@ -140,7 +140,7 @@ ok "Stats helper ready" # ── Flask Dashboard ─────────────────────────────────────── info "Deploying dashboard..." cat > $APP_DIR/dashboard.py <<'DASHBOARD' -import os, json, subprocess, time +import os, json, subprocess, time, ipaddress from flask import Flask, render_template, jsonify, request from flask_socketio import SocketIO import threading @@ -151,7 +151,7 @@ socketio = SocketIO(app, cors_allowed_origins=[], async_mode="eventlet") PORT = int(os.environ.get("DASHBOARD_PORT", 5000)) # Restrict API endpoints to AP subnet by default -AP_SUBNET = os.environ.get("AP_SUBNET", "192.168.50.0/24") +AP_SUBNET = ipaddress.ip_network(os.environ.get("AP_SUBNET", "192.168.50.0/24"), strict=False) def get_stats(): try: @@ -177,9 +177,8 @@ def restrict_subnet(): """Optional: restrict write operations to AP subnet.""" # Allow all GET requests; restrict POST to AP subnet only if request.method == "POST": - client_ip = request.remote_addr - # Check if client is in AP subnet (simple prefix check for /24) - if not client_ip.startswith(AP_SUBNET.rsplit(".", 1)[0] + "."): + client_ip = ipaddress.ip_address(request.remote_addr) + if client_ip not in AP_SUBNET: return jsonify({"error": "Forbidden: not on AP subnet"}), 403 @app.route("/") @@ -254,7 +253,7 @@ BOT_TOKEN = os.environ.get("BOT_TOKEN", "") ADMIN_IDS = [int(x) for x in os.environ.get("ADMIN_CHAT_ID", "").split(",") if x.strip()] if not BOT_TOKEN: - raise SystemExit("BOT_TOKEN not set! Edit /etc/EdgeGateway/config.env") + raise SystemExit("BOT_TOKEN not set! Edit /etc/WarpGate/config.env") if not ADMIN_IDS: logger.warning("ADMIN_CHAT_ID is empty — no users will have admin access!") @@ -392,7 +391,7 @@ After=network.target warp-svc.service [Service] User=root WorkingDirectory=$APP_DIR -EnvironmentFile=/etc/EdgeGateway/config.env +EnvironmentFile=/etc/WarpGate/config.env ExecStart=$VENV/bin/python $APP_DIR/dashboard.py Restart=always RestartSec=5 @@ -410,7 +409,7 @@ After=network.target [Service] User=root WorkingDirectory=$APP_DIR -EnvironmentFile=/etc/EdgeGateway/config.env +EnvironmentFile=/etc/WarpGate/config.env ExecStart=$VENV/bin/python $APP_DIR/bot.py Restart=always RestartSec=10 diff --git a/INTENT.md b/INTENT.md new file mode 100644 index 0000000..5fc33b6 --- /dev/null +++ b/INTENT.md @@ -0,0 +1,217 @@ +# INTENT.md — J1-PIPELINE Phase -1 (ORACLE) + +**Repository:** `OneByJorah/WarpGate` +**Analysis Date:** 2026-07-05 +**Analyst:** J1-PIPELINE ORACLE (read-only) +**Status:** Intent Reconstructed + +--- + +## What This System Does + +**WarpGate** is a two-script provisioning system that transforms a Raspberry Pi (or any Debian/Ubuntu ARM host) into a self-contained secure edge gateway. It combines four subsystems into a single, repeatable deployment: + +| Subsystem | Role | Technology | +|-----------|------|------------| +| **WiFi Access Point** | Creates an internal hotspot (`wlan0`) for client devices to connect | `hostapd` + `dnsmasq` | +| **WARP Tunnel** | Routes *all* traffic (AP clients + WAN uplink) through Cloudflare's encrypted tunnel for DNS privacy and outbound proxying | `cloudflare-warp` client | +| **Monitoring Dashboard** | Real-time web UI showing WARP status, CPU/RAM/temperature, connected clients, throughput, and traffic totals | Flask + Flask-SocketIO + eventlet | +| **Telegram Bot** | Remote management via Telegram — status queries, WARP toggle/reconnect, service restart, Pi reboot | `python-telegram-bot` (v20.8) | + +### Technical Architecture + +``` +[ISP Router] --eth0--> [Raspberry Pi] --wlan0 (AP)--> [Client Devices] + | + Cloudflare WARP tunnel + | + [Cloudflare Edge] + | + [Internet] +``` + +- **eth0** = WAN uplink from ISP router (LAN cable) +- **wlan0** = WiFi Access Point (internal hotspot, SSID: `PiGateway`) +- **CloudflareWARP** = virtual tunnel interface — all forwarded traffic is MASQUERADEd through it +- **Fallback**: If WARP is down, traffic routes via raw WAN (eth0) as a degraded fallback +- **WARP Watchdog**: Cron job every 60s that reconnects WARP if the tunnel drops + +### Key Components + +| File | Purpose | +|------|---------| +| `01_install.sh` | System update, dependency install (hostapd, dnsmasq, iptables, Python), Cloudflare WARP client, Python venv with Flask/SocketIO/Telegram, hostapd config, dnsmasq config, iptables NAT rules, WARP registration, service enablement | +| `02_configure.sh` | WARP watchdog script, gateway stats helper (`gw-stats.sh`), Flask dashboard app (`dashboard.py`), Telegram bot (`bot.py`), systemd units for both services | +| `templates/dashboard.html` | Dark-themed real-time dashboard with stats cards, control buttons, and DHCP lease table | + +### API Surface (Dashboard) + +| Endpoint | Method | Action | +|----------|--------|--------| +| `/` | GET | Dashboard HTML | +| `/api/stats` | GET | JSON system stats | +| `/api/clients` | GET | JSON DHCP lease list | +| `/api/warp/toggle` | POST | Connect/disconnect WARP | +| `/api/warp/reconnect` | POST | Full WARP reconnect cycle | +| `/api/restart/` | POST | Restart hostapd, dnsmasq, or warp-svc | +| `/api/reboot` | POST | Reboot the Pi | + +### Telegram Bot Commands + +| Command | Action | +|---------|--------| +| `/start` | Show inline keyboard menu | +| `/status` | Display full system status | +| `/clients` | List connected DHCP clients | +| Inline buttons | WARP toggle, WARP reconnect, restart hostapd/dnsmasq, reboot Pi | + +### Operational Role + +WarpGate is a **turnkey edge appliance** — deploy it on a Raspberry Pi with two commands, and it becomes a privacy-respecting WiFi hotspot that tunnels all traffic through Cloudflare WARP. It is consumed by: + +- **End users** connecting to the `PiGateway` SSID — they get internet with DNS privacy (1.1.1.1) and encrypted outbound tunneling +- **The Pi's admin** — who monitors and controls the gateway via the web dashboard or Telegram bot +- **JorahOne's edge infrastructure** — as a repeatable, documented building block for privacy-first edge networking + +--- + +## Why This Was Built + +### Real Problem + +Setting up a privacy-respecting edge gateway on a Raspberry Pi traditionally requires: + +1. Manually configuring `hostapd` for WiFi AP mode +2. Manually configuring `dnsmasq` for DHCP/DNS +3. Manually setting up `iptables` NAT rules for traffic forwarding +4. Installing and registering a VPN/tunnel client (WireGuard, OpenVPN, or Cloudflare WARP) +5. Building a monitoring interface from scratch +6. Setting up remote management (SSH-only, no mobile-friendly option) + +This is error-prone, time-consuming, and produces a fragile, non-repeatable configuration. A single typo in `dnsmasq.conf` or a missed `iptables` rule breaks the entire gateway. There is no "one command to rule them all" for Pi-based WARP gateways. + +### Why Existing Tools Were Insufficient + +- **Commercial travel routers (GL.iNet, etc.)**: Proprietary, limited VPN protocol support, no Cloudflare WARP integration, no programmable API surface. +- **OpenWrt**: Powerful but steep learning curve, not Raspberry Pi-native, no WARP client in package repos. +- **Pi-hole**: DNS-level only — no traffic tunneling, no WiFi AP, no remote management. +- **DIY scripts on GitHub**: Fragmented — one repo for hostapd, another for VPN, another for monitoring. No unified, tested, two-step provisioning flow. +- **Cloudflare WARP standalone**: No WiFi AP integration, no dashboard, no remote management. + +WarpGate fills the gap: a **unified, two-command, repeatable provisioning system** that combines all of these into a single coherent deployment. + +### What Triggered Development + +The initial commit (`b176ed4` — "Initial commit: Pi Gateway installer scripts + docs") and the project's evolution show a clear trajectory: + +1. **Initial need** (June 15, 2026): A simple Pi-based gateway with WARP tunneling. The initial commit included both root-level files AND a `pi-router/` subdirectory with duplicate files — suggesting the project was originally named `pi-router` and later renamed to `WarpGate`. +2. **Security hardening** (June 15, 2026): Cleanup pass (`10839ba` — "Fix: full project cleanup and security hardening"). +3. **Dashboard** (June 15, 2026): Real-time monitoring UI (`41a7f55` — "Add dashboard screenshot"). +4. **Repo rename** (June 17, 2026): Migrated from `pi-router` to `WarpGate` branding across three commits (`3bed448` → `f8601ee` → `8cf0248`). +5. **Documentation maturity** (June 17–July 4, 2026): Multiple README iterations refining the narrative, aligning to J1 brand standard, and documenting host requirements. +6. **Code quality** (July 4, 2026): Ruff auto-fixes and portfolio standardization (`1619a2b`). +7. **Dependency bumps** (July 4, 2026): Dependabot PRs for `actions/checkout` and `github/codeql-action`. +8. **Security audit** (July 5, 2026): Email reference sanitization (`6401607` — "audit(WarpGate): sanitize email references"). + +The project was built iteratively, starting from a working installer and layering on observability (dashboard), remote management (Telegram bot), reliability (WARP watchdog), and security hardening over time. + +### Ecosystem Fit + +WarpGate is part of the **OneByJorah** portfolio of infrastructure tools. It complements: + +- **JorahOne's edge computing strategy**: Lightweight, ARM-optimized, privacy-first networking for edge deployments +- **The broader ecosystem**: Sits alongside other JorahOne repos as a self-contained, deployable component — not a library or framework, but a turnkey appliance +- **MIT licensing**: Open-source, community-friendly, aligned with JorahOne's permissive licensing model + +``` +OneByJorah Ecosystem +├── WarpGate ← Turnkey Pi-based WARP gateway appliance +├── EdgeRouter ← (sibling: router-focused infrastructure) +└── [other J1 repos] ← Self-contained deployable components +``` + +--- + +## Operational Classification + +**Classification: PRODUCTION** — this is a deployable, self-contained edge appliance with monitoring, self-healing, and a security disclosure process. + +Evidence: +- **Version**: CHANGELOG.md declares v1.0.0 (though no git tag exists — minor gap) +- **Health checks**: systemd-managed services with `Restart=always` and `RestartSec=5/10`; WARP watchdog cron job for self-healing +- **CI/CD**: CodeQL analysis on push/PR + weekly schedule; Dependabot for GitHub Actions dependency updates +- **Security posture**: SECURITY.md with 90-day disclosure timeline, dedicated security contact email, iptables firewall rules, AP subnet restriction on POST endpoints, Telegram admin whitelist +- **Security audits in git history**: Two security-focused commits — `10839ba` (full project cleanup and security hardening) and `6401607` (email reference sanitization) +- **Monitoring**: Real-time web dashboard (Flask + SocketIO), Telegram bot for remote status, `gw-stats.sh` for JSON metrics, vnstat traffic tracking, DHCP lease monitoring +- **Community readiness**: CONTRIBUTING.md, CODE_OF_CONDUCT.md (Contributor Covenant v2.1), bug report template, feature request template, PR template +- **No live deployment evidence**: `deploy_log.txt` confirms the system is NOT deployable in the current analysis environment (requires root + Cloudflare WARP) + +--- + +## Key Architectural Decisions + +1. **Two-phase provisioning** (`01_install.sh` → `02_configure.sh`): Separates system-level installation (requires reboot) from application deployment. User can edit `config.env` between phases. This is a deliberate UX choice — the first script handles all the heavy system changes, the second deploys the application layer. + +2. **Python venv isolation**: Dashboard and bot run in `/opt/WarpGate/venv` — no system Python contamination. All dependencies (Flask, SocketIO, python-telegram-bot, psutil, gunicorn, eventlet) are isolated. + +3. **Config.env pattern**: All configuration centralized in `/etc/WarpGate/config.env` — single source of truth, sourced by both systemd units and scripts. No scattered config files. + +4. **WARP watchdog**: Cron-based self-healing — if the tunnel drops, it reconnects automatically within 60 seconds. This is critical for a gateway that must stay online. + +5. **Fallback routing**: If WARP is unreachable, traffic falls back to raw WAN (eth0) — degraded but not dead. The iptables rules include a fallback MASQUERADE on `$WAN_IFACE`. + +6. **AP subnet restriction**: Dashboard POST endpoints check client IP against the AP subnet — prevents WAN-side admin access. This is a security-by-design choice. + +7. **Telegram admin whitelist**: Only `ADMIN_CHAT_ID` users can control the gateway via bot. The bot validates `update.effective_user.id` against the whitelist on every interaction. + +8. **No Docker**: Deliberately bare-metal — the system needs direct access to network interfaces (hostapd, iptables, WARP tunnel) that Docker would complicate. The `stack_manifest.json` confirms `has_docker: false`. + +9. **ARM-first design**: The Cloudflare WARP apt repo is configured for `arm64` only. This is a deliberate Raspberry Pi focus — x86_64 hosts would need a different source. + +--- + +## Repository Structure + +``` +WarpGate/ +├── 01_install.sh # Step 1: System + WARP + AP + firewall install +├── 02_configure.sh # Step 2: Dashboard + Telegram bot + systemd units +├── templates/ +│ └── dashboard.html # Real-time monitoring UI (Flask template) +├── .github/ +│ ├── workflows/ +│ │ └── codeql.yml # CodeQL security analysis (weekly + push/PR) +│ ├── dependabot.yml # Weekly GitHub Actions dependency updates +│ ├── ISSUE_TEMPLATE/ +│ │ ├── bug_report.md +│ │ └── feature_request.md +│ └── PULL_REQUEST_TEMPLATE.md +├── README.md # Project documentation +├── CHANGELOG.md # v1.0.0 release notes +├── ROADMAP.md # Future plans (production stability, docs, tests) +├── SECURITY.md # Vulnerability disclosure policy (90-day timeline) +├── CONTRIBUTING.md # Contribution guidelines +├── CODE_OF_CONDUCT.md # Contributor Covenant v2.1 +├── LICENSE # MIT +├── .gitignore +├── stack_manifest.json # Deployment metadata +├── deploy_log.txt # Deployment attempt log +├── review_findings.json # Code review findings (1 finding: README missing requirements note) +├── INTENT.md # This file +└── screenshot-dashboard.png # Dashboard preview image +``` + +--- + +## Notes + +- **Repo rename**: The project was originally named `pi-router` (evidenced by the initial commit `b176ed4` which included a `pi-router/` subdirectory with duplicate files). It was renamed to `WarpGate` on June 17, 2026 across three commits. The `pi-router/` directory was subsequently removed. +- **No git tags**: CHANGELOG.md declares v1.0.0 but no corresponding git tag exists. This is a minor release-process gap. +- **No `docs/` directory**: All documentation lives in the README. No separate docs folder exists. +- **No test files**: No test suite exists — deployment is the only validation path. The ROADMAP.md lists "Test coverage expansion" as a current goal. +- **Dependabot ecosystem**: Correctly configured for `github-actions` only — no ecosystem mismatch (the repo has no `package.json` or `Dockerfile`). +- **Security audit history**: Two security-focused commits in the git log — `10839ba` ("Fix: full project cleanup and security hardening") and `6401607` ("audit(WarpGate): sanitize email references"). This is a positive maturity signal. +- **Default credentials**: Default AP password (`SuperSecret99`) is a placeholder — must be changed before production use. The script explicitly comments "← Change this!". +- **Single-point-of-failure**: The Raspberry Pi itself is the gateway — if it goes down, all AP clients lose internet. No HA/failover mechanism. +- **WARP dependency**: The system's privacy guarantees depend entirely on Cloudflare WARP availability. The fallback (raw WAN) provides no privacy. +- **Review finding (EGW-001)**: README omits documented `sudo` and Cloudflare WARP client package availability requirements. Severity: medium. diff --git a/README.md b/README.md index 444f003..bd07202 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@
-

🌐 EdgeGateway

+

🌐 WarpGate

Raspberry Pi Cloudflare WARP Gateway

Secure tunneling, DNS privacy, and outbound proxy for edge devices — one-command setup

@@ -32,9 +32,20 @@ ## 🚀 Quick Start +### Requirements + +- **Raspberry Pi** (3B+, 4B, or 5) running **Raspberry Pi OS** (Debian-based) +- **Root access** — both scripts must run with `sudo` +- **Cloudflare WARP client** — the install script adds the Cloudflare apt repo automatically +- **Ethernet WAN uplink** on `eth0` (LAN cable from ISP router) +- **WiFi chipset** supporting AP mode (built-in on Pi 3B+/4/5, or USB adapter) +- **Telegram Bot Token** (optional, for bot functionality) — create via [@BotFather](https://t.me/BotFather) + +> ⚠️ **IMPORTANT**: Before running the installer, edit `01_install.sh` and change the default AP password (`AP_PASS="SuperSecret99"`). The default is a placeholder and MUST be changed for any production or public deployment. + ```bash -git clone https://github.com/OneByJorah/EdgeGateway.git -cd EdgeGateway +git clone https://github.com/OneByJorah/WarpGate.git +cd WarpGate chmod +x 01_install.sh 02_configure.sh sudo ./01_install.sh sudo ./02_configure.sh @@ -59,15 +70,15 @@ sudo ./02_configure.sh After installation, open the status dashboard: ```bash -# The dashboard is served on port 8080 +# The dashboard is served on port 5000 # Open in your browser: -# http://:8080 +# http://:5000 ``` ## 📁 Project Structure ``` -EdgeGateway/ +WarpGate/ ├── 01_install.sh # System setup & WARP installation ├── 02_configure.sh # WARP configuration & registration ├── templates/ # Dashboard HTML templates diff --git a/deploy_log.txt b/deploy_log.txt index 1adfd04..f4188e9 100644 --- a/deploy_log.txt +++ b/deploy_log.txt @@ -1,4 +1,4 @@ -[EdgeGateway deploy attempt] +[WarpGate deploy attempt] - Repo type: Bash provisioning + static HTML dashboard (no Python/Node/Docker runtime). - Cannot deploy on this host without root privileges and Cloudflare WARP environment. - Local preview fallback: captured `templates/dashboard.html` as static file for README reference. diff --git a/j1.yaml b/j1.yaml new file mode 100644 index 0000000..5761c2c --- /dev/null +++ b/j1.yaml @@ -0,0 +1,15 @@ +repo: WarpGate +class: Infrastructure +org: OneByJorah +owner: Jhonattan L. Jimenez +license: MIT +production_score: 0 +last_audit: 2026-07-05 +last_publish: 2026-07-04 +standards_version: "2.1" +dependencies: [] +deploy_target: scratch +tailscale_only: false +public_facing: false +community_sla_hours: 48 +adoption_tracked: false diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b567640 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,11 @@ +# WarpGate Python dependencies +# Install in a virtual environment: python3 -m venv /opt/WarpGate/venv +# Then: pip install -r requirements.txt + +flask>=3.0,<4.0 +flask-socketio>=5.3,<6.0 +python-telegram-bot==20.8 +psutil>=5.9,<6.0 +requests>=2.31,<3.0 +gunicorn>=22.0,<23.0 +eventlet>=0.36,<0.37 diff --git a/templates/dashboard.html b/templates/dashboard.html index a2738e9..8ce2187 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -170,9 +170,20 @@

Connected Clients

tbody.innerHTML = 'No clients connected'; return; } - tbody.innerHTML = leases.map(l => - `${l.ip}${l.mac}${l.name || '*'}` - ).join(''); + tbody.innerHTML = ''; + for (const l of leases) { + const tr = document.createElement('tr'); + const tdIp = document.createElement('td'); + tdIp.textContent = l.ip || '*'; + const tdMac = document.createElement('td'); + tdMac.textContent = l.mac || '*'; + const tdName = document.createElement('td'); + tdName.textContent = l.name || '*'; + tr.appendChild(tdIp); + tr.appendChild(tdMac); + tr.appendChild(tdName); + tbody.appendChild(tr); + } } async function api(endpoint, method='POST') {