diff --git a/Cargo.lock b/Cargo.lock index a428174..8be1da6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1599,6 +1599,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex" version = "0.4.3" @@ -2447,6 +2453,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "num_enum" version = "0.7.5" @@ -2795,6 +2811,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-src" +version = "300.5.4+3.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.111" @@ -2803,6 +2828,7 @@ checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -2889,6 +2915,7 @@ name = "ostp-guard" version = "0.1.0" dependencies = [ "libc", + "num_cpus", "rand 0.8.5", "tokio", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 331f1ff..ab78252 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,3 +57,5 @@ hyper = { version = "1.0", features = ["full"] } base64 = "0.21" qrcode = "0.14" image = { version = "0.24", default-features = false, features = ["png"] } +openssl = { version = "0.10", features = ["vendored"] } +reqwest = { version = "0.11", default-features = false, features = ["json"] } diff --git a/dist/linux-amd64/DEPLOY.md b/dist/linux-amd64/DEPLOY.md new file mode 100644 index 0000000..0602830 --- /dev/null +++ b/dist/linux-amd64/DEPLOY.md @@ -0,0 +1,110 @@ +# OSTP Linux Deployment Package + +## Contents + +- **ostp-server** (4.0 MB) - Stealth VPN Server Binary +- **oncp-master** (4.7 MB) - CDN Control Plane Binary +- **install.sh** - Automated installation script +- **README.md** - Complete deployment guide +- **SHA256SUMS** - Binary checksums for verification +- **ostp-server.service** - Systemd service file +- **oncp-master.service** - Systemd service file +- **server.json.example** - Server configuration template +- **server-enrollment.json.example** - Auto-enrollment config template + +## Quick Start + +### 1. Verify Checksums + +```bash +sha256sum -c SHA256SUMS +``` + +### 2. Run Installation Script + +```bash +sudo bash install.sh +``` + +### 3. Configure Server + +```bash +# Generate PSK +ostp-server gen-key + +# Edit config +sudo nano /etc/ostp/server.json +# Replace PSK with generated key + +# Start service +sudo systemctl enable ostp-server +sudo systemctl start ostp-server +sudo systemctl status ostp-server +``` + +## System Requirements + +- **OS**: Debian 13+ / Ubuntu 24.04+ / RHEL 9+ +- **Architecture**: x86_64 +- **glibc**: 2.41+ +- **Libraries**: libssl3, libcrypto3 +- **Privileges**: Root/sudo required + +## Build Information + +- **Date**: January 2, 2026 +- **Rust Version**: 1.85.0 +- **Target**: x86_64-unknown-linux-gnu +- **glibc**: 2.41 (Debian Trixie) +- **Profile**: Release (optimized) + +## Features + +### ostp-server +- ✅ AEAD encryption (ChaCha20-Poly1305) +- ✅ X25519 key exchange +- ✅ TLS mimicry +- ✅ Anti-DPI protection +- ✅ UDP-over-TCP framing +- ✅ Silent PSK validation +- ✅ Anti-debugging protection +- ✅ Auto-enrollment to CDN + +### oncp-master +- ✅ REST API for node management +- ✅ Node enrollment system (Pending→Approved→Active) +- ✅ CDN steering by country code +- ✅ User billing and quota tracking +- ✅ Dynamic SNI management +- ✅ Real-time dashboard CLI +- ✅ Network statistics +- ✅ SQLite backend + +## Deployment Scenarios + +### Standalone Server +Use `server.json.example` - manual PSK configuration + +### CDN Network Node +Use `server-enrollment.json.example` - automatic enrollment with master node + +## Security Considerations + +1. **PSK Protection**: Keep PSKs secure, never commit to version control +2. **Firewall**: Restrict master node API to known IPs +3. **TLS**: Use reverse proxy for API TLS termination +4. **Updates**: Keep binaries updated for security patches +5. **Monitoring**: Use systemd logs and `oncp-master dashboard` + +## Documentation + +Full documentation in [README.md](README.md) + +## Support + +- **GitHub**: https://github.com/ospab/ospab.network +- **Issues**: https://github.com/ospab/ospab.network/issues + +--- + +**Note**: ostp-server requires root privileges for TUN device creation and port binding. Anti-debugging protection (ostp-guard) is enabled in release builds. diff --git a/dist/linux-amd64/README.md b/dist/linux-amd64/README.md new file mode 100644 index 0000000..38ad0bd --- /dev/null +++ b/dist/linux-amd64/README.md @@ -0,0 +1,388 @@ +# OSTP Linux Server Binaries + +## Binaries + +- **ostp-server** (4.0 MB) - OSTP Stealth VPN Server +- **oncp-master** (4.7 MB) - CDN Control Plane Master Node + +## System Requirements + +- **OS**: Linux x86_64 (Debian 13+ / Ubuntu 24.04+ / RHEL 9+) +- **glibc**: 2.41+ (built on Debian Trixie) +- **Libraries**: libssl3, libcrypto3 +- **Privileges**: Root/sudo required for: + - Binding to privileged ports (< 1024) + - TUN device creation + - System DNS modification + +## Installation + +### 1. Install System Dependencies + +**Debian/Ubuntu:** +```bash +sudo apt update +sudo apt install -y libssl3 openssl ca-certificates +``` + +**RHEL/Rocky/AlmaLinux:** +```bash +sudo dnf install -y openssl-libs openssl ca-certificates +``` + +### 2. Deploy Binaries + +```bash +# Copy binaries +sudo cp ostp-server oncp-master /usr/local/bin/ +sudo chmod +x /usr/local/bin/{ostp-server,oncp-master} + +# Verify +ostp-server --version +oncp-master --version +``` + +## ostp-server Setup + +### Generate PSK + +```bash +ostp-server gen-key +``` + +Save the output securely - this is your Pre-Shared Key. + +### Configuration File + +Create `/etc/ostp/server.json`: + +```json +{ + "listen": "0.0.0.0:8443", + "psk": "YOUR_64_CHAR_HEX_PSK_HERE", + "max_connections": 1024, + "log_level": "info" +} +``` + +### Node Enrollment (Optional) + +For automatic CDN registration: + +```json +{ + "listen": "0.0.0.0:8443", + "psk": "AUTO", + "master_node_url": "https://master.ospab.internal:8080", + "node_name": "node-us-west-1", + "hardware_id": "unique-hardware-id", + "region": "us-west", + "country_code": "US", + "max_connections": 1024, + "log_level": "info" +} +``` + +When `psk: "AUTO"`, the server will: +1. Submit enrollment request to master node +2. Display Node ID +3. Wait for administrator approval +4. Update config with approved PSK + +### Systemd Service + +Create `/etc/systemd/system/ostp-server.service`: + +```ini +[Unit] +Description=OSTP Stealth VPN Server +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/ostp-server -c /etc/ostp/server.json +Restart=on-failure +RestartSec=10s +LimitNOFILE=65536 + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/etc/ostp + +[Install] +WantedBy=multi-user.target +``` + +Enable and start: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable ostp-server +sudo systemctl start ostp-server +sudo systemctl status ostp-server +``` + +## oncp-master Setup + +### Initialize Database + +```bash +# Create data directory +sudo mkdir -p /var/lib/oncp +cd /var/lib/oncp + +# Initialize (creates oncp.db) +oncp-master stats +``` + +### Configuration + +Create `/etc/oncp/config.env`: + +```bash +ONCP_DATABASE=/var/lib/oncp/oncp.db +ONCP_LISTEN=0.0.0.0:8080 +RUST_LOG=info +``` + +### Run API Server + +```bash +oncp-master serve --listen 0.0.0.0:8080 +``` + +### Systemd Service + +Create `/etc/systemd/system/oncp-master.service`: + +```ini +[Unit] +Description=ONCP Master Node - CDN Control Plane +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=oncp +Group=oncp +WorkingDirectory=/var/lib/oncp +EnvironmentFile=/etc/oncp/config.env +ExecStart=/usr/local/bin/oncp-master serve --listen 0.0.0.0:8080 --database /var/lib/oncp/oncp.db +Restart=on-failure +RestartSec=10s + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/oncp + +[Install] +WantedBy=multi-user.target +``` + +Create user and start: + +```bash +sudo useradd -r -s /bin/false oncp +sudo chown -R oncp:oncp /var/lib/oncp +sudo systemctl daemon-reload +sudo systemctl enable oncp-master +sudo systemctl start oncp-master +sudo systemctl status oncp-master +``` + +## Node Enrollment Workflow + +### On Master Node: + +```bash +# List pending enrollment requests +oncp-master node pending + +# Approve node (generates PSK) +oncp-master node approve + +# Copy the generated PSK +``` + +### On Server Node: + +Update `/etc/ostp/server.json` with approved PSK: + +```json +{ + "listen": "0.0.0.0:8443", + "psk": "APPROVED_PSK_FROM_MASTER_HERE", + "master_node_url": "https://master.ospab.internal:8080", + ... +} +``` + +Restart server: + +```bash +sudo systemctl restart ostp-server +``` + +## Management Commands + +### oncp-master CLI + +```bash +# Dashboard (live monitoring) +oncp-master dashboard + +# Node management +oncp-master node list +oncp-master node add -n "node-1" -a "1.2.3.4:8443" -c US +oncp-master node pending +oncp-master node approve +oncp-master node reject + +# User management +oncp-master user list +oncp-master user create -q 100 -d 30 +oncp-master user config + +# SNI management +oncp-master sni list +oncp-master sni add cloudflare.com -c US +oncp-master sni block example.com + +# Statistics +oncp-master stats +``` + +### ostp-server CLI + +```bash +# Generate PSK +ostp-server gen-key + +# Run with config +ostp-server -c /etc/ostp/server.json + +# Run with CLI args +ostp-server -l 0.0.0.0:8443 -p +``` + +## API Endpoints + +Master Node REST API (default port 8080): + +- `GET /health` - Health check +- `GET /api/v1/nodes` - List nodes +- `POST /api/v1/nodes` - Register node +- `POST /api/v1/nodes/:id/checkin` - Node heartbeat +- `GET /api/v1/nodes/best?country=US&limit=3` - CDN steering +- `POST /api/v1/enrollment/request` - Submit enrollment +- `GET /api/v1/enrollment/pending` - List pending +- `POST /api/v1/enrollment/:id/approve` - Approve node +- `GET /api/v1/users` - List users +- `POST /api/v1/users` - Create user +- `GET /api/v1/sni` - List SNIs +- `POST /api/v1/sni` - Update SNI +- `GET /api/v1/stats` - Network statistics + +## Firewall Configuration + +### ostp-server (Server Node) + +```bash +# Allow OSTP port +sudo ufw allow 8443/tcp comment 'OSTP Server' + +# Allow outbound to master node +sudo ufw allow out 8080/tcp comment 'ONCP Master' +``` + +### oncp-master (Master Node) + +```bash +# Allow API access +sudo ufw allow 8080/tcp comment 'ONCP API' + +# Restrict to server IPs only (recommended) +sudo ufw allow from to any port 8080 proto tcp +``` + +## Logs + +```bash +# ostp-server logs +sudo journalctl -u ostp-server -f + +# oncp-master logs +sudo journalctl -u oncp-master -f +``` + +## Troubleshooting + +### Check Binary Compatibility + +```bash +ldd ostp-server +ldd oncp-master +``` + +If you see "not found" errors, install missing libraries. + +### Check glibc Version + +```bash +ldd --version +``` + +Required: glibc 2.41+ (Debian 13+ / Ubuntu 24.04+) + +For older distributions, build from source: + +```bash +cargo build -p ostp-server -p oncp-master --release --target x86_64-unknown-linux-musl +``` + +### Permission Errors + +Ensure running as root or with appropriate capabilities: + +```bash +sudo setcap cap_net_bind_service,cap_net_admin+ep /usr/local/bin/ostp-server +``` + +### Network Connectivity + +Test master node API: + +```bash +curl http://localhost:8080/health +``` + +Expected: `{"status":"ok","version":"0.1.0","nodes_online":0}` + +## Security Notes + +1. **PSK Protection**: Never commit PSKs to version control +2. **TLS**: Use reverse proxy (nginx/caddy) for TLS termination on API +3. **Firewall**: Restrict master node API to known server IPs +4. **Updates**: Keep binaries updated for security patches +5. **Monitoring**: Use `oncp-master dashboard` for network health + +## Support + +- GitHub: https://github.com/ospab/ospab.network +- Issues: https://github.com/ospab/ospab.network/issues + +## Build Info + +- **Built**: January 2, 2026 +- **Rust**: 1.85.0 +- **Target**: x86_64-unknown-linux-gnu +- **glibc**: 2.41 (Debian Trixie) +- **Profile**: Release (optimized) diff --git a/dist/linux-amd64/SHA256SUMS b/dist/linux-amd64/SHA256SUMS new file mode 100644 index 0000000..9add7b7 --- /dev/null +++ b/dist/linux-amd64/SHA256SUMS @@ -0,0 +1,2 @@ +0987a1c45eb117f1bc447654a891755667276f76f032f7d1644318e913380f4a ostp-server +20f6418335e52873ab5c60afcb6468eaf2edd42d0c4174caf6875257fb643e16 oncp-master diff --git a/dist/linux-amd64/install.sh b/dist/linux-amd64/install.sh new file mode 100644 index 0000000..58305d6 --- /dev/null +++ b/dist/linux-amd64/install.sh @@ -0,0 +1,107 @@ +#!/bin/bash +set -e + +echo "========================================" +echo " OSTP Server Installation Script" +echo "========================================" +echo "" + +# Check for root +if [ "$EUID" -ne 0 ]; then + echo "❌ Please run as root or with sudo" + exit 1 +fi + +# Detect distro +if [ -f /etc/os-release ]; then + . /etc/os-release + OS=$ID + VERSION=$VERSION_ID +else + echo "❌ Cannot detect Linux distribution" + exit 1 +fi + +echo "✓ Detected: $PRETTY_NAME" + +# Install dependencies +echo "" +echo "📦 Installing dependencies..." +case $OS in + debian|ubuntu) + apt update + apt install -y libssl3 openssl ca-certificates + ;; + rhel|rocky|almalinux|centos) + dnf install -y openssl-libs openssl ca-certificates + ;; + *) + echo "⚠️ Unknown distribution. Please install libssl3 manually." + ;; +esac + +# Create directories +echo "" +echo "📁 Creating directories..." +mkdir -p /etc/ostp +mkdir -p /var/lib/oncp + +# Copy binaries +echo "" +echo "📋 Installing binaries..." +cp ostp-server oncp-master /usr/local/bin/ +chmod +x /usr/local/bin/ostp-server /usr/local/bin/oncp-master + +# Create oncp user +echo "" +echo "👤 Creating oncp user..." +if ! id -u oncp > /dev/null 2>&1; then + useradd -r -s /bin/false oncp +fi +chown -R oncp:oncp /var/lib/oncp + +# Copy config examples +echo "" +echo "⚙️ Copying configuration examples..." +if [ ! -f /etc/ostp/server.json ]; then + cp server.json.example /etc/ostp/server.json + echo " Created /etc/ostp/server.json" +fi + +# Copy systemd services +echo "" +echo "🔧 Installing systemd services..." +cp ostp-server.service /etc/systemd/system/ +cp oncp-master.service /etc/systemd/system/ +systemctl daemon-reload + +echo "" +echo "========================================" +echo " ✅ Installation Complete!" +echo "========================================" +echo "" +echo "📝 Next steps:" +echo "" +echo "1. Generate PSK:" +echo " ostp-server gen-key" +echo "" +echo "2. Edit config:" +echo " nano /etc/ostp/server.json" +echo " (Replace PSK with generated key)" +echo "" +echo "3. Start ostp-server:" +echo " systemctl enable ostp-server" +echo " systemctl start ostp-server" +echo " systemctl status ostp-server" +echo "" +echo "4. (Optional) Start oncp-master:" +echo " systemctl enable oncp-master" +echo " systemctl start oncp-master" +echo " systemctl status oncp-master" +echo "" +echo "5. View logs:" +echo " journalctl -u ostp-server -f" +echo " journalctl -u oncp-master -f" +echo "" +echo "📖 Full documentation: README.md" +echo "" diff --git a/dist/linux-amd64/oncp-master b/dist/linux-amd64/oncp-master index 07edc7d..5a4571f 100644 Binary files a/dist/linux-amd64/oncp-master and b/dist/linux-amd64/oncp-master differ diff --git a/dist/linux-amd64/oncp-master.service b/dist/linux-amd64/oncp-master.service new file mode 100644 index 0000000..80a9c91 --- /dev/null +++ b/dist/linux-amd64/oncp-master.service @@ -0,0 +1,23 @@ +[Unit] +Description=ONCP Master Node - CDN Control Plane +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=oncp +Group=oncp +WorkingDirectory=/var/lib/oncp +ExecStart=/usr/local/bin/oncp-master serve --listen 0.0.0.0:8080 --database /var/lib/oncp/oncp.db --log-level info +Restart=on-failure +RestartSec=10s + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/oncp + +[Install] +WantedBy=multi-user.target diff --git a/dist/linux-amd64/ostp-server b/dist/linux-amd64/ostp-server index 4dc5a60..c8cf3de 100644 Binary files a/dist/linux-amd64/ostp-server and b/dist/linux-amd64/ostp-server differ diff --git a/dist/linux-amd64/ostp-server.service b/dist/linux-amd64/ostp-server.service new file mode 100644 index 0000000..3445061 --- /dev/null +++ b/dist/linux-amd64/ostp-server.service @@ -0,0 +1,23 @@ +[Unit] +Description=OSTP Stealth VPN Server +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=root +WorkingDirectory=/etc/ostp +ExecStart=/usr/local/bin/ostp-server -c /etc/ostp/server.json +Restart=on-failure +RestartSec=10s +LimitNOFILE=65536 + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/etc/ostp + +[Install] +WantedBy=multi-user.target diff --git a/dist/linux-amd64/server-enrollment.json.example b/dist/linux-amd64/server-enrollment.json.example new file mode 100644 index 0000000..f21b6b8 --- /dev/null +++ b/dist/linux-amd64/server-enrollment.json.example @@ -0,0 +1,11 @@ +{ + "listen": "0.0.0.0:8443", + "psk": "AUTO", + "master_node_url": "http://master.ospab.internal:8080", + "node_name": "ostp-node-1", + "hardware_id": "server-unique-id", + "region": "us-west", + "country_code": "US", + "max_connections": 1024, + "log_level": "info" +} diff --git a/dist/linux-amd64/server.json.example b/dist/linux-amd64/server.json.example new file mode 100644 index 0000000..167a02c --- /dev/null +++ b/dist/linux-amd64/server.json.example @@ -0,0 +1,6 @@ +{ + "listen": "0.0.0.0:8443", + "psk": "REPLACE_WITH_GENERATED_PSK_FROM_gen-key_COMMAND", + "max_connections": 1024, + "log_level": "info" +} diff --git a/dist/ostp-linux-amd64.zip b/dist/ostp-linux-amd64.zip new file mode 100644 index 0000000..3c017f6 Binary files /dev/null and b/dist/ostp-linux-amd64.zip differ diff --git a/dist/ostp-windows-amd64.zip b/dist/ostp-windows-amd64.zip new file mode 100644 index 0000000..9149be5 Binary files /dev/null and b/dist/ostp-windows-amd64.zip differ diff --git a/dist/windows-amd64/README.md b/dist/windows-amd64/README.md new file mode 100644 index 0000000..f43f2cc --- /dev/null +++ b/dist/windows-amd64/README.md @@ -0,0 +1,220 @@ +# OSTP Windows Binaries + +## Contents + +- **ostp-server.exe** (3.52 MB) - OSTP Stealth VPN Server +- **oncp-master.exe** (4.02 MB) - CDN Control Plane Master Node +- **SHA256SUMS.txt** - Binary checksums + +## System Requirements + +- **OS**: Windows 10/11 (x64) +- **Privileges**: Administrator required for TUN device and system DNS + +## Installation + +### 1. Verify Checksums + +```powershell +Get-FileHash ostp-server.exe -Algorithm SHA256 +Get-FileHash oncp-master.exe -Algorithm SHA256 +``` + +Compare with values in `SHA256SUMS.txt` + +### 2. Place Binaries + +```powershell +# Create directory +New-Item -Path "C:\Program Files\OSTP" -ItemType Directory -Force + +# Copy binaries +Copy-Item ostp-server.exe,oncp-master.exe "C:\Program Files\OSTP\" + +# Add to PATH (optional) +[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\OSTP", "Machine") +``` + +## ostp-server Usage + +### Generate PSK + +```powershell +ostp-server.exe gen-key +``` + +### Create Configuration + +Create `C:\Program Files\OSTP\server.json`: + +```json +{ + "listen": "0.0.0.0:8443", + "psk": "YOUR_64_CHAR_HEX_PSK_HERE", + "max_connections": 1024, + "log_level": "info" +} +``` + +### Run Server + +```powershell +# Run directly (Administrator required) +ostp-server.exe -c "C:\Program Files\OSTP\server.json" + +# Or with CLI args +ostp-server.exe -l 0.0.0.0:8443 -p YOUR_PSK_HEX +``` + +### Install as Windows Service + +```powershell +# Using NSSM (Non-Sucking Service Manager) +nssm install OSTP-Server "C:\Program Files\OSTP\ostp-server.exe" -c "C:\Program Files\OSTP\server.json" +nssm set OSTP-Server AppDirectory "C:\Program Files\OSTP" +nssm set OSTP-Server DisplayName "OSTP Stealth VPN Server" +nssm set OSTP-Server Description "OSTP stealth transport protocol server" +nssm set OSTP-Server Start SERVICE_AUTO_START + +# Start service +nssm start OSTP-Server + +# Check status +nssm status OSTP-Server +``` + +Download NSSM: https://nssm.cc/download + +## oncp-master Usage + +### Initialize Database + +```powershell +# Create data directory +New-Item -Path "C:\ProgramData\ONCP" -ItemType Directory -Force +cd "C:\ProgramData\ONCP" + +# Initialize database +oncp-master.exe stats +``` + +### Run API Server + +```powershell +oncp-master.exe serve --listen 0.0.0.0:8080 --database "C:\ProgramData\ONCP\oncp.db" +``` + +### Management Commands + +```powershell +# Dashboard +oncp-master.exe dashboard + +# Node management +oncp-master.exe node list +oncp-master.exe node pending +oncp-master.exe node approve + +# User management +oncp-master.exe user create -q 100 -d 30 +oncp-master.exe user list + +# SNI management +oncp-master.exe sni list +oncp-master.exe sni add cloudflare.com -c US +``` + +### Install as Windows Service + +```powershell +nssm install ONCP-Master "C:\Program Files\OSTP\oncp-master.exe" serve --listen 0.0.0.0:8080 --database "C:\ProgramData\ONCP\oncp.db" +nssm set ONCP-Master AppDirectory "C:\ProgramData\ONCP" +nssm set ONCP-Master DisplayName "ONCP Master Node" +nssm set ONCP-Master Start SERVICE_AUTO_START + +nssm start ONCP-Master +``` + +## Firewall Configuration + +```powershell +# Allow OSTP server port +New-NetFirewallRule -DisplayName "OSTP Server" -Direction Inbound -LocalPort 8443 -Protocol TCP -Action Allow + +# Allow ONCP API port +New-NetFirewallRule -DisplayName "ONCP Master API" -Direction Inbound -LocalPort 8080 -Protocol TCP -Action Allow +``` + +## Features + +### ostp-server.exe +- ✅ AEAD encryption (ChaCha20-Poly1305) +- ✅ X25519 key exchange +- ✅ TLS mimicry +- ✅ UDP-over-TCP framing +- ✅ Silent PSK validation +- ✅ Anti-debugging protection (ostp-guard) +- ✅ Auto-enrollment to CDN + +### oncp-master.exe +- ✅ REST API for node/user management +- ✅ Node enrollment system +- ✅ CDN steering by country +- ✅ Real-time dashboard +- ✅ SQLite backend + +## Logging + +View logs using: +- Event Viewer (if running as service) +- Console output (if running directly) +- Set `RUST_LOG=debug` environment variable for verbose logging + +## Troubleshooting + +### "Access Denied" Error + +Run PowerShell as Administrator: +```powershell +Start-Process powershell -Verb RunAs +``` + +### Port Already in Use + +Check what's using the port: +```powershell +Get-NetTCPConnection -LocalPort 8443 +``` + +### Binary Signature Warning + +Windows may show SmartScreen warning. Click "More info" → "Run anyway" + +Or bypass with: +```powershell +Unblock-File ostp-server.exe +Unblock-File oncp-master.exe +``` + +## Build Information + +- **Date**: January 2, 2026 +- **Rust Version**: 1.85.0 +- **Target**: x86_64-pc-windows-msvc +- **Profile**: Release (optimized) + +## Security Notes + +1. **PSK Protection**: Never share or commit PSKs +2. **Admin Rights**: Required for TUN/TAP and system operations +3. **Firewall**: Configure Windows Firewall rules +4. **Updates**: Keep binaries updated + +## Support + +- **GitHub**: https://github.com/ospab/ospab.network +- **Issues**: https://github.com/ospab/ospab.network/issues + +--- + +**Note**: Anti-debugging protection (ostp-guard) is active in release builds. Running under debugger will cause immediate exit. diff --git a/dist/windows-amd64/SHA256SUMS.txt b/dist/windows-amd64/SHA256SUMS.txt new file mode 100644 index 0000000..42b52eb --- /dev/null +++ b/dist/windows-amd64/SHA256SUMS.txt @@ -0,0 +1,2 @@ +ce4d83f11534bef16008e4064b13f883124948af4773fa78e94da54ededa2bd2 ostp-server.exe +2238e11fe7293c6211b32ee1883b6d9edf2b58618afd053904ea12d600f15641 oncp-master.exe diff --git a/dist/windows-amd64/oncp-master.exe b/dist/windows-amd64/oncp-master.exe new file mode 100644 index 0000000..c7965bd Binary files /dev/null and b/dist/windows-amd64/oncp-master.exe differ diff --git a/dist/windows-amd64/ostp-server.exe b/dist/windows-amd64/ostp-server.exe new file mode 100644 index 0000000..e25f098 Binary files /dev/null and b/dist/windows-amd64/ostp-server.exe differ diff --git a/ostp-guard/Cargo.toml b/ostp-guard/Cargo.toml index d5b8b18..761fad5 100644 --- a/ostp-guard/Cargo.toml +++ b/ostp-guard/Cargo.toml @@ -8,6 +8,7 @@ description = "OSTP Anti-Reverse Engineering & Protection Module" rand.workspace = true tokio.workspace = true tracing.workspace = true +num_cpus = "1.16" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["debugapi", "processthreadsapi", "winnt", "sysinfoapi", "libloaderapi"] } diff --git a/ostp-guard/src/anti_debug.rs b/ostp-guard/src/anti_debug.rs index 3da2fd1..bbf4cc0 100644 --- a/ostp-guard/src/anti_debug.rs +++ b/ostp-guard/src/anti_debug.rs @@ -1,7 +1,7 @@ -//! Anti-Debugging Detection Module +//! Anti-Debugging Detection Module - Redesigned //! -//! Detects if the process is being traced/debugged -//! and takes evasive action without obvious crashes. +//! Detects if the process is being actively debugged +//! Focuses on active debugging, not passive analysis /// Check if any debugger is attached #[inline(never)] @@ -22,16 +22,16 @@ pub fn is_debugger_present() -> bool { } } -/// Multiple Windows anti-debug techniques +/// Windows anti-debug - only active debugging #[cfg(windows)] fn windows_debugger_check() -> bool { unsafe { - // Method 1: IsDebuggerPresent API + // IsDebuggerPresent - reliable for active debugging if winapi::um::debugapi::IsDebuggerPresent() != 0 { return true; } - // Method 2: CheckRemoteDebuggerPresent + // CheckRemoteDebuggerPresent - detects remote debuggers let mut is_debugged: i32 = 0; let process = winapi::um::processthreadsapi::GetCurrentProcess(); if winapi::um::debugapi::CheckRemoteDebuggerPresent(process, &mut is_debugged) != 0 { @@ -39,123 +39,16 @@ fn windows_debugger_check() -> bool { return true; } } - - // Method 3: NtGlobalFlag check (PEB) - // The NtGlobalFlag in PEB is set to 0x70 when debugged - if check_peb_being_debugged() { - return true; - } - - // Method 4: Timing check - debugger breakpoints cause delays - if timing_check() { - return true; - } } false } -#[cfg(windows)] -unsafe fn check_peb_being_debugged() -> bool { - // Access PEB through TEB - // This is a low-level check that many debuggers don't hide - #[cfg(target_arch = "x86_64")] - { - let peb: *const u8; - unsafe { - std::arch::asm!( - "mov {}, gs:[0x60]", - out(reg) peb, - options(nostack, nomem) - ); - } - - if !peb.is_null() { - // BeingDebugged flag at offset 0x2 - let being_debugged = unsafe { *peb.add(0x2) }; - if being_debugged != 0 { - return true; - } - - // NtGlobalFlag at offset 0xBC (x64) - let nt_global_flag = unsafe { *(peb.add(0xBC) as *const u32) }; - // FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS - if nt_global_flag & 0x70 != 0 { - return true; - } - } - } - - false -} - -#[cfg(windows)] -fn timing_check() -> bool { - use std::time::Instant; - - // Simple operation that should be instant - let start = Instant::now(); - - // Do some trivial work - let mut x: u64 = 0; - for i in 0..1000 { - x = x.wrapping_add(i); - } - - // Prevent optimization - std::hint::black_box(x); - - let elapsed = start.elapsed(); - - // If this takes more than 100ms, likely being single-stepped - elapsed.as_millis() > 100 -} - -/// Linux/Unix anti-debug techniques +/// Linux/Unix anti-debug - only /proc/self/status check #[cfg(unix)] fn unix_debugger_check() -> bool { - // Method 1: ptrace self-attach trick - if ptrace_check() { - return true; - } - - // Method 2: Check /proc/self/status for TracerPid - if proc_status_check() { - return true; - } - - // Method 3: Check parent process name - if parent_process_check() { - return true; - } - - // Method 4: Timing check - if timing_check_unix() { - return true; - } - - false -} - -#[cfg(unix)] -fn ptrace_check() -> bool { - // PTRACE_TRACEME = 0 - // If we're already being traced, this will fail - unsafe { - let result = libc::ptrace(libc::PTRACE_TRACEME, 0, 0, 0); - if result == -1 { - // Already being traced - return true; - } - // Detach from ourselves - libc::ptrace(libc::PTRACE_DETACH, 0, 0, 0); - } - false -} - -#[cfg(unix)] -fn proc_status_check() -> bool { - // Read /proc/self/status and check TracerPid + // Check /proc/self/status for TracerPid + // Non-invasive, works everywhere if let Ok(status) = std::fs::read_to_string("/proc/self/status") { for line in status.lines() { if line.starts_with("TracerPid:") { @@ -172,57 +65,16 @@ fn proc_status_check() -> bool { false } -#[cfg(unix)] -fn parent_process_check() -> bool { - // Check if parent is a known debugger - let debuggers = ["gdb", "lldb", "strace", "ltrace", "radare2", "r2", "ida", "x64dbg", "ollydbg"]; - - if let Ok(ppid_str) = std::fs::read_to_string("/proc/self/stat") { - let parts: Vec<&str> = ppid_str.split_whitespace().collect(); - if parts.len() > 3 { - if let Ok(ppid) = parts[3].parse::() { - let parent_exe = format!("/proc/{}/exe", ppid); - if let Ok(path) = std::fs::read_link(&parent_exe) { - let name = path.file_name() - .and_then(|n| n.to_str()) - .unwrap_or(""); - - for debugger in &debuggers { - if name.contains(debugger) { - return true; - } - } - } - } - } - } - false -} - -#[cfg(unix)] -fn timing_check_unix() -> bool { - use std::time::Instant; - - let start = Instant::now(); - let mut x: u64 = 0; - for i in 0..1000 { - x = x.wrapping_add(i); - } - std::hint::black_box(x); - - start.elapsed().as_millis() > 100 -} - -/// Continuous background monitor (call from separate thread) -pub fn start_background_monitor() -> std::thread::JoinHandle<()> { +/// Background monitoring thread +pub fn start_background_monitor() { std::thread::spawn(|| { loop { std::thread::sleep(std::time::Duration::from_secs(5)); if is_debugger_present() { - // Enter decoy mode silently - crate::decoy_loop(); + // Silent exit + std::process::exit(1); } } - }) + }); } diff --git a/ostp-guard/src/anti_vm.rs b/ostp-guard/src/anti_vm.rs index 2d41fa8..1e3847d 100644 --- a/ostp-guard/src/anti_vm.rs +++ b/ostp-guard/src/anti_vm.rs @@ -1,161 +1,30 @@ -//! Anti-VM and Sandbox Detection +//! Anti-VM and Sandbox Detection - Redesigned //! -//! Detects common virtualization artifacts to prevent -//! analysis in controlled environments. +//! Smart heuristic approach to detect analysis environments +//! without blocking production VPS servers -/// Check if running in a virtual machine or sandbox +/// Check if running in a sandbox/analysis environment +/// Uses weighted scoring to avoid false positives on production VPS #[inline(never)] pub fn is_virtual_machine() -> bool { - // Check multiple indicators - any single check might be bypassed - let checks = [ - check_vm_mac_addresses, - check_vm_hardware_ids, - check_vm_processes, - check_vm_files, - check_vm_registry, - check_low_resources, - ]; + let mut score = 0; - // If more than 2 checks trigger, likely a VM - let score: u32 = checks.iter() - .map(|check| if check() { 1 } else { 0 }) - .sum(); + // HIGH risk indicators (2 points each) + if check_analysis_tools() { score += 2; } + if check_sandbox_artifacts() { score += 2; } - score >= 2 + // MEDIUM risk (1 point each) + if check_low_resources() { score += 1; } + if check_suspicious_environment() { score += 1; } + + // Threshold: 4+ points = very likely sandbox + // Production VPS: max 1-2 points + // Analysis sandbox: 4+ points (2 HIGH or 1 HIGH + 2 MEDIUM) + score >= 4 } -/// Check for known VM MAC address prefixes -fn check_vm_mac_addresses() -> bool { - #[cfg(windows)] - { - // Get network adapter info and check MAC prefixes - // VMware: 00:0C:29, 00:50:56 - // VirtualBox: 08:00:27 - // Hyper-V: 00:15:5D - // Parallels: 00:1C:42 - - // Simplified check via ipconfig output patterns - if let Ok(output) = std::process::Command::new("ipconfig") - .arg("/all") - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - let vm_macs = ["00-0c-29", "00-50-56", "08-00-27", "00-15-5d", "00-1c-42"]; - for mac in &vm_macs { - if stdout.contains(mac) { - return true; - } - } - } - } - - #[cfg(unix)] - { - if let Ok(output) = std::process::Command::new("ip") - .args(["link", "show"]) - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - let vm_macs = ["00:0c:29", "00:50:56", "08:00:27", "00:15:5d", "00:1c:42"]; - for mac in &vm_macs { - if stdout.contains(mac) { - return true; - } - } - } - } - - false -} - -/// Check for VM-specific hardware IDs -fn check_vm_hardware_ids() -> bool { - #[cfg(windows)] - { - // Check WMI for VM indicators - let vm_indicators = [ - "vmware", "virtualbox", "vbox", "qemu", "xen", - "virtual", "hyperv", "parallels", "kvm" - ]; - - // Check computer name/model via WMI - if let Ok(output) = std::process::Command::new("wmic") - .args(["computersystem", "get", "model"]) - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for indicator in &vm_indicators { - if stdout.contains(indicator) { - return true; - } - } - } - - // Check BIOS - if let Ok(output) = std::process::Command::new("wmic") - .args(["bios", "get", "serialnumber"]) - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for indicator in &vm_indicators { - if stdout.contains(indicator) { - return true; - } - } - } - } - - #[cfg(unix)] - { - // Check /sys/class/dmi/id/ - let dmi_paths = [ - "/sys/class/dmi/id/product_name", - "/sys/class/dmi/id/sys_vendor", - "/sys/class/dmi/id/board_vendor", - ]; - - let vm_indicators = [ - "vmware", "virtualbox", "vbox", "qemu", "xen", - "virtual", "hyperv", "parallels", "kvm", "bochs" - ]; - - for path in &dmi_paths { - if let Ok(content) = std::fs::read_to_string(path) { - let lower = content.to_lowercase(); - for indicator in &vm_indicators { - if lower.contains(indicator) { - return true; - } - } - } - } - } - - false -} - -/// Check for VM-related processes -fn check_vm_processes() -> bool { - let vm_processes = [ - "vmtoolsd", "vmwaretray", "vmwareuser", // VMware - "vboxservice", "vboxtray", "vboxclient", // VirtualBox - "xenservice", // Xen - "qemu-ga", // QEMU - "prl_tools", "prl_cc", // Parallels - ]; - - #[cfg(windows)] - { - if let Ok(output) = std::process::Command::new("tasklist").output() { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for proc in &vm_processes { - if stdout.contains(proc) { - return true; - } - } - } - } - +/// HIGH: Check for reverse engineering tools in memory +fn check_analysis_tools() -> bool { #[cfg(unix)] { if let Ok(output) = std::process::Command::new("ps") @@ -163,8 +32,35 @@ fn check_vm_processes() -> bool { .output() { let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for proc in &vm_processes { - if stdout.contains(proc) { + let tools = [ + "gdb", "lldb", "strace", "ltrace", "radare2", "r2", + "ida", "ida64", "x64dbg", "ghidra", "binaryninja", + "frida-server", "rizin", "cutter", "hopper", + "qemu-user" // QEMU user-mode for cross-arch analysis + ]; + + for tool in &tools { + if stdout.contains(tool) { + return true; + } + } + } + } + + #[cfg(windows)] + { + if let Ok(output) = std::process::Command::new("tasklist") + .output() + { + let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); + let tools = [ + "x64dbg", "x32dbg", "ollydbg", "windbg", "ida", "ida64", + "ghidra", "binaryninja", "pestudio", "processhacker", + "procmon", "procexp", "wireshark", "fiddler" + ]; + + for tool in &tools { + if stdout.contains(tool) { return true; } } @@ -174,37 +70,14 @@ fn check_vm_processes() -> bool { false } -/// Check for VM-specific files -fn check_vm_files() -> bool { - #[cfg(windows)] - { - let vm_files = [ - r"C:\Windows\System32\drivers\vmmouse.sys", - r"C:\Windows\System32\drivers\vmhgfs.sys", - r"C:\Windows\System32\drivers\VBoxMouse.sys", - r"C:\Windows\System32\drivers\VBoxGuest.sys", - r"C:\Windows\System32\drivers\VBoxSF.sys", - ]; - - for file in &vm_files { - if std::path::Path::new(file).exists() { - return true; - } - } - } - +/// HIGH: Sandbox-specific artifacts +fn check_sandbox_artifacts() -> bool { #[cfg(unix)] { - let vm_files = [ - "/usr/bin/vmtoolsd", - "/usr/bin/VBoxService", - "/usr/bin/VBoxClient", - "/.dockerenv", - "/run/.containerenv", - ]; - - for file in &vm_files { - if std::path::Path::new(file).exists() { + // Wine (used for Windows malware analysis on Linux) + let wine_paths = ["/tmp/.wine-", "/tmp/.X11-unix"]; + for path in &wine_paths { + if std::fs::read_dir(path).is_ok() { return true; } } @@ -213,24 +86,20 @@ fn check_vm_files() -> bool { false } -/// Check Windows registry for VM indicators -fn check_vm_registry() -> bool { - #[cfg(windows)] - { - // Check via reg query - let registry_keys = [ - r"HKLM\SOFTWARE\VMware, Inc.\VMware Tools", - r"HKLM\SOFTWARE\Oracle\VirtualBox Guest Additions", - ]; - - for key in ®istry_keys { - if let Ok(output) = std::process::Command::new("reg") - .args(["query", key]) - .output() - { - if output.status.success() { - return true; - } +/// MEDIUM: Suspicious environment variables +fn check_suspicious_environment() -> bool { + let suspicious = [ + "WINE_", + "QEMU_", + "SANDBOX_", + "AFL_", // American Fuzzy Lop fuzzer + "ASAN_", // AddressSanitizer + ]; + + for (key, _) in std::env::vars() { + for pattern in &suspicious { + if key.starts_with(pattern) { + return true; } } } @@ -238,75 +107,44 @@ fn check_vm_registry() -> bool { false } -/// Check for suspiciously low resources (sandbox indicator) +/// MEDIUM: Very low resources (< 1GB RAM or 1 CPU) fn check_low_resources() -> bool { - // Sandboxes often have minimal resources - - // Check CPU count - let cpus = std::thread::available_parallelism() - .map(|n| n.get()) - .unwrap_or(1); - - if cpus < 2 { + // Single CPU = very suspicious + let cpu_count = num_cpus::get(); + if cpu_count < 2 { return true; } - // Check available disk space (simplified) - #[cfg(windows)] + // Check available memory + #[cfg(unix)] { - if let Ok(output) = std::process::Command::new("wmic") - .args(["logicaldisk", "get", "size"]) - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout); - // Very small disk = sandbox - if let Some(size_str) = stdout.lines().nth(1) { - if let Ok(size) = size_str.trim().parse::() { - // Less than 50GB - if size < 50_000_000_000 { - return true; + if let Ok(meminfo) = std::fs::read_to_string("/proc/meminfo") { + for line in meminfo.lines() { + if line.starts_with("MemTotal:") { + if let Some(kb_str) = line.split_whitespace().nth(1) { + if let Ok(kb) = kb_str.parse::() { + let mb = kb / 1024; + // Less than 1GB = sandbox + return mb < 1024; + } } } } } } - false -} - -/// Check for analysis tools -pub fn check_analysis_tools() -> bool { - let tools = [ - "wireshark", "fiddler", "burp", "charles", // Network - "x64dbg", "x32dbg", "ollydbg", "windbg", // Debuggers - "ida", "ida64", "ghidra", "radare2", "r2", // Disassemblers - "procmon", "procexp", "processhacker", // Process monitors - "pestudio", "die", "exeinfope", // PE analyzers - ]; - #[cfg(windows)] { - if let Ok(output) = std::process::Command::new("tasklist").output() { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for tool in &tools { - if stdout.contains(tool) { - return true; - } - } - } - } - - #[cfg(unix)] - { - if let Ok(output) = std::process::Command::new("ps") - .args(["aux"]) - .output() - { - let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase(); - for tool in &tools { - if stdout.contains(tool) { - return true; - } + use std::mem::MaybeUninit; + unsafe { + let mut mem_status = MaybeUninit::::uninit(); + let mem_status_ptr = mem_status.as_mut_ptr(); + (*mem_status_ptr).dwLength = std::mem::size_of::() as u32; + + if winapi::um::sysinfoapi::GlobalMemoryStatusEx(mem_status_ptr) != 0 { + let mem_status = mem_status.assume_init(); + let total_mb = mem_status.ullTotalPhys / (1024 * 1024); + return total_mb < 1024; } } } diff --git a/ostp-server/Cargo.toml b/ostp-server/Cargo.toml index 44688ac..f356989 100644 --- a/ostp-server/Cargo.toml +++ b/ostp-server/Cargo.toml @@ -21,4 +21,4 @@ hex.workspace = true serde.workspace = true serde_json.workspace = true rand.workspace = true -reqwest = { version = "0.11", features = ["json"] } +reqwest = { workspace = true, features = ["native-tls-vendored"] } diff --git a/ostp-server/src/main.rs b/ostp-server/src/main.rs index 420d867..86d0f48 100644 --- a/ostp-server/src/main.rs +++ b/ostp-server/src/main.rs @@ -94,20 +94,6 @@ fn generate_random_psk() -> String { #[tokio::main] async fn main() -> Result<()> { - // ============================================ - // SECURITY CHECK - Detect debuggers/VMs - // ============================================ - #[cfg(not(debug_assertions))] - { - if !ostp_guard::init_protection() { - eprintln!("0x{:08X}", ostp_guard::error_codes::E_NET_TIMEOUT); - std::process::exit(1); - } - - // Start background monitor - ostp_guard::anti_debug::start_background_monitor(); - } - let cli = Cli::parse(); // Handle subcommands @@ -204,6 +190,21 @@ async fn main() -> Result<()> { let config = ServerConfig::new(listen, psk); let server = OstpServer::new(config); + // ============================================ + // SECURITY CHECK - Detect analysis environment + // Smart heuristic: production VPS safe + // ============================================ + #[cfg(not(debug_assertions))] + { + if !ostp_guard::init_protection() { + tracing::error!("Security check failed: environment not suitable for production"); + std::process::exit(1); + } + + // Start background monitor for debugger attachment + ostp_guard::anti_debug::start_background_monitor(); + } + tracing::info!("Starting server..."); server.run().await?;