Ghostwire
Anti-censorship reverse tunnel with RSA-encrypted auth and AES-256-GCM end-to-end encryption. Bypasses outbound blocking in censored countries.
Install / Use
/learn @FrenchToblerone54/GhostwireREADME
GhostWire - Anti-Censorship Reverse Tunnel
GhostWire is a WebSocket-based reverse tunnel system designed to help users in censored countries access the internet freely. It uses secure WebSocket connections over TLS, making it difficult to detect and block.
Features
- Multiple protocol support - WebSocket, HTTP/2, and gRPC transports
- RSA-encrypted authentication - Token invisible to TLS-terminating proxies (CloudFlare-proof)
- End-to-end AES-256-GCM encryption - All tunnel data encrypted with random 256-bit session keys
- Reverse tunnel architecture - Client connects TO server (bypasses outbound blocking)
- Mode selection -
reverse(default) anddirect - Bidirectional streaming - Single persistent connection over TLS
- Flexible TCP port forwarding - Port ranges, IP binding, custom mappings
- Built-in heartbeat - Transport and application-layer keepalive
- CloudFlare compatible - Works behind TLS-terminating proxies (with WebSocket/HTTP/2)
- Web management panel - Real-time system monitoring, tunnel config, logs, service control
- nginx reverse proxy - Production-ready setup with Let's Encrypt
- Compiled binaries - Linux amd64 (Ubuntu 22.04+ compatible)
- systemd services - Automated start, restart, logging
- Auto-update - Configurable automatic binary updates via GitHub releases
- Easy installation - One-command setup scripts with interactive configuration
Quick Start
Step 1: Install Server (Censored Country - e.g., Iran)
The server runs in the censored country with a public IP that can receive incoming connections.
wget https://raw.githubusercontent.com/frenchtoblerone54/ghostwire/main/scripts/install-server.sh -O install-server.sh
chmod +x install-server.sh
sudo ./install-server.sh
Note: Save the authentication token - you'll need it for the client!
Step 2: Install Client (Uncensored Country - e.g., Netherlands, USA)
The client runs on a VPS in an uncensored country with unrestricted internet access.
wget https://raw.githubusercontent.com/frenchtoblerone54/ghostwire/main/scripts/install-client.sh -O install-client.sh
chmod +x install-client.sh
sudo ./install-client.sh
Enter:
- Server URL pointing to your Iran server (e.g.,
wss://iran-server.com/ws) - Authentication token from server
- The client will connect TO the Iran server
Step 3: Use the Tunnel (In Iran)
Users in Iran connect to the server's local ports (e.g., localhost:8080) and traffic is tunneled through to the NL client which makes the actual internet requests.
Documentation
- Installation Guide - Detailed setup instructions for server and client
- Configuration Reference - Complete configuration options
- Troubleshooting - Common issues and solutions
- Security - Encryption details and security considerations
Architecture
Reverse Tunnel for Bypassing Outbound Blocking:
Designed for scenarios where censored countries block outbound connections to foreign servers (e.g., Iran blocks connections to international websites).
Setup:
- Server: Runs in censored country (Iran) with public IP
- Client: Runs in uncensored country (Netherlands) with unrestricted internet
Why This Works:
- Iran blocks outbound connections to foreign servers
- But Iran server has public IP and can receive inbound WebSocket connections
- NL client connects TO Iran server (inbound to Iran = allowed ✅)
- Once tunnel is established, traffic flows bidirectionally
Data Flow:
[User in Iran] → [Server localhost:8080] → [Server Iran]
↓ WebSocket Tunnel
[Client NL] → [Internet: Port 80/443]
Step-by-Step:
- Client (NL) initiates WebSocket connection TO server (Iran)
- Server (Iran) listens on local ports (e.g., 8080) for users
- User in Iran connects to
localhost:8080 - Traffic tunnels through WebSocket to NL client
- NL client makes actual connection to blocked websites
- Response travels back through tunnel to user in Iran
CloudFlare/DNS: Points to Iran server IP (where WebSocket server listens for client connections)
Modes and Use Cases
GhostWire now supports:
mode="reverse"(default)mode="direct"
Behavior Matrix
reverse: server listens on[tunnels], client connects out and dials remote targetsdirect: client listens on[tunnels], server dials remote targets
Your Two Scenarios
- Host website on your own computer (client side) and expose it from server public IP/domain: use
mode="reverse"(server-side[tunnels]). - Connect to a VPN that is running on the server side through GhostWire encryption: use
mode="direct"(client-side[tunnels]).
WebSocket Pool in Direct Modes
- WebSocket pool (
ws_pool_enabled,ws_pool_children,ws_pool_min) works in direct mode too. - In
direct, pool channels are used by client-side direct listeners. - Scope: pool applies to WebSocket transports (
protocol="websocket"andprotocol="aiohttp-ws"), not HTTP/2 or gRPC.
Port Mapping Syntax
The server supports flexible port mapping configurations (server listens, client connects):
ports=[
"443-600", # Listen on all ports 443-600, forward to same port on remote
"443-600:5201", # Listen on all ports 443-600, forward all to remote port 5201
"443-600=1.1.1.1:5201", # Listen on all ports 443-600, forward all to 1.1.1.1:5201
"443", # Listen on local port 443, forward to remote port 443
"4000=5000", # Listen on local port 4000, forward to remote port 5000
"127.0.0.2:443=5201", # Bind to 127.0.0.2:443, forward to remote port 5201
"443=1.1.1.1:5201", # Listen on local port 443, forward to 1.1.1.1:5201
"127.0.0.2:443=1.1.1.1:5201", # Bind to 127.0.0.2:443, forward to 1.1.1.1:5201
]
Configuration
Server Configuration (/etc/ghostwire/server.toml)
Location: Censored country (Iran) - has public IP, listens for client connections
[server]
protocol="websocket" # "websocket" (default), "http2", or "grpc"
listen_host="0.0.0.0"
listen_port=8443
mode="reverse" # "reverse" (default) or "direct"
listen_backlog=4096 # TCP listen queue depth
websocket_path="/ws" # Only used for websocket protocol
ping_interval=30 # Application-level ping interval (seconds)
ping_timeout=60 # Connection timeout (seconds)
direct_http_proxy="" # optional: proxy for direct-mode outbound CONNECT
direct_https_proxy="" # optional: proxy for direct-mode outbound CONNECT
ws_pool_enabled=true # Enable child channel pooling (default: true)
ws_pool_children=8 # Max child channels (default: 8)
ws_pool_min=2 # Min always-connected channels (default: 2)
ws_pool_stripe=false # Stripe packets across channels (unstable, default: false)
udp_enabled=true # Also listen for UDP on tunnel ports (default: true)
ws_send_batch_bytes=65536 # Max bytes per WebSocket frame (default: 65536)
auto_update=true
update_check_interval=300
update_check_on_startup=true
[auth]
token="V1StGXR8_Z5jdHi6B-my"
[tunnels]
ports=["8080=80", "8443=443"]
[panel]
enabled=true
host="127.0.0.1"
port=9090
path="aBcDeFgHiJkLmNoPqRsT"
threads=4 # HTTP server worker threads
[logging]
level="info"
file="/var/log/ghostwire-server.log"
Web Management Panel: The server includes an optional web-based management panel for:
- Real-time system monitoring (CPU, RAM, disk, network usage)
- Tunnel configuration and management
- Log viewing
- Service control (restart/stop)
- Configuration editor
The panel is accessible at http://127.0.0.1:9090/{path}/ where path is a randomly generated nanoid. Access is restricted to localhost by default for security. The threads parameter (default: 4) controls the number of worker threads for the panel's HTTP server - increase for high traffic.
Performance Tuning for High Concurrency:
For web browsing with hundreds of concurrent connections (typical modern websites load 50-200+ resources):
-
ws_pool_enabled(server only, default: true): Enable dynamic multi-connection pool to mitigate TCP-over-TCP meltdown under heavy load -
ws_pool_children(server only, default: 8): Max parallel WebSocket connections- 2-4: Light usage (< 50 concurrent connections)
- 8: Default, good for most deployments
- 16-32: Heavy usage (multiple simultaneous users)
-
ws_pool_min(server only, default: 2): Minimum always-connected channels; pool scales between min and max based on load -
ws_pool_stripe(server only, default: false): Stripe individual packets across channels for higher throughput — disabled by default as it requires sequence reordering and is unstable under packet loss -
udp_enabled(server only, default: true): Also listen on the configured tunnel ports via UDP; set tofalseto disable UDP tunneling -
ws_send_batch_bytes(both, default: 65536): Max bytes batched into a single WebSocket frame- Lower values reduce latency under high load (speedtest, video) by preventing large frames from blocking smaller packets
- 65536 (64KB): Default, best balance for most use cases
- 262144 (256KB): Higher throughput, some latency increase under load
- 16384 (16KB): Lowest latency, slightly lower throughput
-
ping_intervalandping_timeout: Critical for CloudFlare stability (configure on both server and client)- For low latency (< 50ms):
ping_interval=10,ping_timeout=10 - For high latency (> 200ms, CloudFlare):
ping_interval=30,ping_timeout=60 - Aggressive timeouts (< 15s) cause co
- For low latency (< 50ms):
Related Skills
node-connect
328.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
81.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
328.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
81.0kCommit, push, and open a PR
