Skip to content

Latest commit

 

History

History
174 lines (127 loc) · 7.13 KB

File metadata and controls

174 lines (127 loc) · 7.13 KB

Multi-Server Architecture

Overview

Extending from a single Helsinki server to multiple exit nodes in different regions. Each server runs the same stack independently; clients switch between them via Hiddify auto-fallback.

Server Inventory

Tag Location Provider IP Key Protocols Enabled
helsinki Finland Hetzner <HEL_IP> VLESS Reality, Hysteria2, CDN-WS, XHTTP-CDN, gRPC-CDN, XrayHTTP, SS2022, DNS Tunnel, NaiveProxy, MTProto Yes
oracle-madrid Madrid Oracle Cloud (Free) <ORC_IP> VLESS Reality, Hysteria2, CDN-WS, XHTTP-CDN, gRPC-CDN, XrayHTTP, SS2022, DNS Tunnel, NaiveProxy, MTProto Yes
gcp-middle-east Middle East (Dammam) Google Cloud ($300 credit) <GCP_IP> VLESS Reality, Hysteria2, CDN-WS, XHTTP-CDN, gRPC-CDN, XrayHTTP, SS2022, MTProto Yes
scaleway-london London Scaleway <SCW_IP> VLESS Reality, Hysteria2, CDN-WS, XHTTP-CDN, gRPC-CDN, XrayHTTP, SS2022, DNS Tunnel, NaiveProxy, Cloak+SS2022, MTProto Yes

Shared vs Per-Server Credentials

Credential Shared? Why
UUID YES User identity — same user authenticates on all servers
Reality private key NO Generated per sing-box instance
Reality public key NO Per-server, clients need each server's key
Reality short-id NO Per-server
Hy2 cert SHA256 NO Self-signed cert per server
DNSTT pubkey NO Per dnstm install
Slipstream FP NO Per tunnel
WARP config NO Each server gets its own WARP identity

Key principle: UUID is the only shared credential. Everything else is per-server. This means client configs need separate entries per server.

Deployment Variables (Per Server)

All servers use the same UUID. Per-server credentials are generated during deployment.

Variable Description How to Get
Reality public key Per-server Reality public key Generated by reality-ezpz.sh
Reality short ID Per-server Reality short ID Generated by reality-ezpz.sh
Hy2 cert SHA256 Per-server Hysteria2 cert hash openssl x509 -in hy2.crt -noout -fingerprint -sha256
WARP config Per-server WireGuard identity Generated by sing-box WARP setup
SS2022 server key Per-server Shadowsocks 2022 key Generated by deploy-ss2022.sh

Setup: Adding a New Server

Prerequisites

  • VPS provisioned (Ubuntu 24.04, SSH key added) from any provider
  • Same SSH key as Helsinki for convenience

Steps

  1. Base setup — Follow server-setup.md steps 1-7 (SSH, Docker, UFW, fail2ban, unattended-upgrades)

  2. Deploy reality-ezpz — Follow server-setup.md step 8

    • Use same UUID as Helsinki
    • SNI: diversify per server (google.com, dl.google.com, microsoft.com, etc.)
    • WARP: ON
    • Save generated keys
  3. Deploy Hysteria2 — Follow server-setup.md step 9

    • Generate new self-signed cert
    • Inject into engine.conf + docker-compose.yml
    • Same UUID as password
  4. Deploy xray-core sidecar — Deploy XrayHTTP, XHTTP, SS2022 via HAProxy

    • Use deploy scripts: deploy-xhttp.sh, deploy-ss2022.sh
  5. Deploy advanced protocols (optional per server):

    • Finalmask: deploy-finalmask.sh
    • Salamander+Hop: deploy-salamander-udphop.sh
    • ShadowTLS: deploy-shadowtls.sh (servers with direct access)
    • NaiveProxy: deploy-naiveproxy.sh (needs domain + Let's Encrypt)
    • Cloak: deploy-cloak.sh (wraps SS2022)
    • DNS tunnel: deploy-dnstunnel-expand.sh (needs NS delegation)
  6. Automated backups — Follow server-setup.md step 13

  7. DNS records — Add to Cloudflare:

    • CDN record (Proxied): cdn<N>.<DOMAIN> → <SERVER_IP> for XHTTP-CDN
    • NaiveProxy A record (DNS only): web<N>.<DOMAIN> → <SERVER_IP>
    • DNS tunnel NS delegation (if applicable)
  8. Update smart-sub worker — Add server config to worker.js, redeploy to CF Pages

Verify

# On target server
docker compose ps
ss -tlnp | grep 443
ss -ulnp | grep 8443

# From outside
curl -I https://<SERVER_IP>:443 -k
nc -zuv <SERVER_IP> 8443

Client Configuration (Multi-Server)

Smart Subscription (Recommended)

Users import a single subscription URL that includes all servers and protocols:

https://sub.example.com/sub/<UUID>

Backup (Vercel Edge): https://sub.example.net/sub/<UUID>

This returns ~190 configs across all 4 servers and 15+ protocol types. Hiddify auto-tests latency and falls back between them.

Fallback Priority (v5.9)

  1. XHTTP-CDN → CDN-fronted + no WS headers + anti-detection
  2. XHTTP-CDN + Clean CF IPs → When default CF IPs throttled
  3. Finalmask XDNS/XICMP → UDP-based, looks like DNS/game traffic
  4. XrayHTTP → Direct TCP with fake HTTP to whitelisted domains
  5. VLESS Reality → Direct TLS to Google-mimicking
  6. Hysteria2 → UDP/QUIC, fast
  7. Hy2 Salamander+Hop → Obfuscated QUIC + port cycling
  8. ShadowTLS v3 → Real TLS handshake + SS2022 inner tunnel
  9. IPv6 Reality/Hy2 → When ISP blocks IPv4 only
  10. CDN-WS → CDN-fronted but WS detectable
  11. SS2022, NaiveProxy, Cloak → Plan B diverse protocols
  12. DNS Tunnel → Emergency, always works, slow
  13. EDtunnel (CF Pages) → Zero server IP exposure

DNS Tunnel Load Balancing (Optional)

When to Activate

Only activate dns-tun-lb when you need DNS tunnel traffic distributed across multiple servers. For just VLESS Reality + Hysteria2 exit diversity, dns-tun-lb is not needed.

If Needed

  1. Install dnstm on France server, create dnstt-socks tunnel

  2. On Helsinki, edit /opt/dns-tun-lb/lb.yaml:

    backends:
      - id: "local-dnstt"
        address: "127.0.0.1:5311"
      - id: "france-dnstt"
        address: "<SERVER2_IP>:5311"
  3. Run /opt/dns-tun-lb/activate-lb.sh activate

  4. Add NS record: additional servers already have tns2/tns4 nameserver records

Caveat: Activating dns-tun-lb disables dnstm router, which breaks slipstream tunnels (t. and s2. subdomains). Only dnstt tunnels work through dns-tun-lb. Slipstream support is on the dns-tun-lb roadmap.

Current DNS tunnel deployment:

  • Helsinki: Slipstream+SOCKS (t.), DNSTT+SOCKS, Slipstream+SSH — via tns nameserver
  • Oracle Madrid: DNSTT+SOCKS (t2.) — via tns2 nameserver
  • Scaleway London: DNSTT+SOCKS (s2.) — via tns4 nameserver

Removing a Server

  1. Remove server's entries from client configs / subscription
  2. Delete DNS records for that server in Cloudflare
  3. If dns-tun-lb was active, remove the backend from lb.yaml and restart
  4. Destroy the VPS (provider dashboard)
  5. Update server inventory table above

Operational Notes

  • Each server backs up independently (own cron, own /opt/vpn-backups/)
  • Download backups from each server separately: scp root@<IP>:/opt/vpn-backups/*.tar.gz ~/vpn-backups/<location>/
  • No cross-server state synchronization needed (stateless architecture)
  • UUID rotation requires updating all servers simultaneously
  • Monitor each server independently: ssh root@<IP> 'docker compose ps && ss -tulnp'