~bigbes/shroud

shroud/README.md -rw-r--r-- 7.6 KiB
32187908 — Eugene Blikh refactor: rename Go module to go.bigb.es/shroud a month ago

#shroud

Single-binary Go replacement for the Outline VPN server stack. Replaces the original 3-process deployment (Node.js shadowbox + outline-ss-server + Prometheus) with one Go binary that uses outline-ss-server as a library.

Supports three protocols: Shadowsocks, AmneziaWG (obfuscated WireGuard with HTTP/3 cover traffic), and VLESS+REALITY (TLS 1.3 camouflage proxy).

#Features

  • Single binary — no Node.js, no child processes, no sidecar Prometheus
  • Shadowbox-compatible REST API — drop-in replacement for existing Outline clients
  • Hot-reload — adding/removing keys swaps cipher lists and listeners without downtime
  • AmneziaWG — DPI-resistant WireGuard VPN with automatic TLS certificates and HTTP/3 cover server
  • VLESS+REALITY — TLS 1.3 camouflage proxy with auto-detection of decoy servers
  • Multi-protocol keys — each access key automatically gets credentials for all enabled protocols
  • Built-in metrics — Prometheus endpoint with optional node_exporter collectors (Linux)
  • GeoIP metrics — per-country and per-ASN traffic stats with auto-updating MMDB databases
  • CLI management — manage keys, server config, and VLESS targets without a running server
  • Atomic state persistence — single YAML file with safe write-via-rename

#Quick Start

#Install on Ubuntu/Debian

# Shadowsocks only
curl -fsSL https://bigbes.sourcecraft.dev/shroud/install.sh | sudo bash

# Shadowsocks + AmneziaWG
curl -fsSL https://bigbes.sourcecraft.dev/shroud/install.sh | sudo bash -s -- --awg --domain vpn.example.com

# Shadowsocks + VLESS+REALITY (auto-detects decoy server)
curl -fsSL https://bigbes.sourcecraft.dev/shroud/install.sh | sudo bash -s -- --vless

The installer builds from source, creates a systemd service, configures firewall rules, and prints the management API URL on completion.

#Build from source

go build ./cmd/shroud/
go build -ldflags='-X main.version=1.0.0' ./cmd/shroud/  # with version

#Run

./shroud -c config.example.yaml      # start the server
./shroud -c config.yaml -v           # with verbose logging

#CLI Usage

# Server management (no running server required)
shroud server info -c config.yaml
shroud server set-port 50000 -c config.yaml
shroud server set-hostname vpn.example.com -c config.yaml
shroud server set-name "My VPN" -c config.yaml

# Access key management (no running server required)
shroud key list -c config.yaml
shroud key add -n "user1" -c config.yaml
shroud key add -n "user2" -p 51234 --cipher chacha20-ietf-poly1305 -c config.yaml
shroud key remove 1 -c config.yaml
shroud key rename 1 "new-name" -c config.yaml

# VLESS+REALITY management
shroud vless info -c config.yaml
shroud vless keygen                                          # generate x25519 keypair
shroud vless share 0 -c config.yaml                          # generate share link
shroud vless scan --addr 203.0.113.0/24                      # scan for decoy targets
shroud vless autodetect --write -c config.yaml               # auto-detect best decoy

# Shell completions
shroud completion bash
shroud completion zsh

#Configuration

See config.example.yaml for the full configuration reference.

server:
  name: "My Outline Server"
  hostname: "example.com"

api:
  listen_addr: ":8081"

metrics:
  listen_addr: "127.0.0.1:8082"
  node_exporter_collectors:
    - cpu
    - meminfo
    - loadavg
    - filesystem
    - diskstats
    - netdev

shadowsocks:
  default_port: 0                      # 0 = pick random available port
  default_cipher: chacha20-ietf-poly1305
  replay_history: 10000

amneziawg:
  enabled: false
  listen_port: 443
  address: "10.14.0.0/24"
  domain: "vpn.example.com"            # for automatic Let's Encrypt certs

vless:
  enabled: false
  listen_addr: ":443"
  server_names:                        # SNIs accepted by REALITY handshake
    - www.microsoft.com
  dest: "www.microsoft.com:443"        # decoy forward target

state_file: state.yaml

#REST API

All management endpoints live under /<secret>/ prefix. The secret is auto-generated on first run and printed to the log.

Method Endpoint Description
GET /<secret>/server Server info
PUT /<secret>/name Rename server
GET /<secret>/access-keys List all keys
POST /<secret>/access-keys Create key
GET /<secret>/access-keys/{id} Get key
PUT /<secret>/access-keys/{id} Upsert key
DELETE /<secret>/access-keys/{id} Delete key
PUT /<secret>/access-keys/{id}/name Rename key
PUT /<secret>/access-keys/{id}/data-limit Set data limit
DELETE /<secret>/access-keys/{id}/data-limit Remove data limit
PUT /<secret>/server/port-for-new-access-keys Set default port
PUT /<secret>/server/hostname-for-access-keys Set hostname
PUT /<secret>/server/access-key-data-limit Set default data limit
DELETE /<secret>/server/access-key-data-limit Remove default data limit
GET /<secret>/metrics/enabled Check metrics status
PUT /<secret>/metrics/enabled Toggle metrics
GET /<secret>/metrics/transfer Per-key byte transfer
GET /<secret>/access-keys/{id}/awg-config Download AmneziaWG config
GET /<secret>/access-keys/{id}/outline-config Download Outline Smart Dialer config

Public endpoints (no auth):

Method Endpoint Server Description
GET /metrics Metrics Prometheus scrape target
GET /healthz Metrics Health check

#Architecture

cmd/shroud/main.go     CLI entry point, cobra commands, signal handling
        |
        +-> internal/config/    YAML config loading and validation
        +-> internal/store/     YAML file persistence (atomic write via rename)
        +-> internal/ssserver/  Wraps outline-ss-server as a library
        +-> internal/metrics/   Prometheus registry + TransferTracker
        +-> internal/api/       REST API handlers (shadowbox-compatible)
        +-> internal/awgserver/ AmneziaWG server + HTTP/3 QUIC cover
        +-> internal/vless/     VLESS+REALITY proxy server
        +-> internal/reality/   TLS scanner + auto-detection for REALITY decoys
        +-> internal/mmdb/      GeoIP database downloader with auto-update

The Shadowsocks proxy is imported as a Go library — not run as a subprocess. When keys change, SyncKeys() rebuilds cipher lists and hot-swaps listeners. The integration surface is ~100 lines in internal/ssserver/server.go.

#Main Dependencies

Dependency Version Purpose
outline-ss-server v1.9.3-rc2 Shadowsocks proxy (used as library)
outline-sdk v0.0.21 Outline transport primitives
amneziawg-go v1.0.4 DPI-resistant WireGuard implementation
xtls/reality latest REALITY protocol for TLS camouflage
quic-go v0.59.0 QUIC/HTTP3 for AWG cover traffic
prometheus/client_golang v1.23.2 Go Prometheus client and registry
prometheus/node_exporter v1.10.2 OS-level metrics collectors (Linux)

#Testing

go test ./...