VPN Architecture
Introduction: Why Another VPN?
Most VPNs are slow, detectable, and easily blocked by modern censorship systems (GFW, DPI). Commercial VPNs log your data, while self‑hosted WireGuard or OpenVPN stand out like a sore thumb in network traffic.
Project Mirage changes the game. It’s a stealth‑first, high‑performance VPN that:
- Uses VLESS + XTLS‑Reality – steals TLS certificates from real websites (Microsoft, Google) to appear as normal HTTPS traffic.
- Implements packet fragmentation – breaks TLS handshakes into random‑sized chunks to evade deep‑packet inspection.
- Runs in a hardened Docker container – with rootless mode, read‑only filesystem, and minimal Linux capabilities.
- Automates everything – from key generation and target selection to kernel tuning (BBR, TCP Fast Open).
This guide walks you through deploying Mirage on your own VPS, from zero to a fully operational stealth VPN.
Prerequisites
- A VPS with a public IPv4 address (Debian 12 / Ubuntu 22.04+ recommended).
- Docker and Docker Compose installed.
- Basic familiarity with the command line.
Security Note: Always run your VPN behind a firewall. The setup script will configure kernel parameters, but you should also restrict SSH access and enable fail2ban.
Step 1 – Clone the Repository
git clone https://github.com/banfen321/Mirage.git
cd mirage
If you don’t have Git, download the archive directly:
curl -L https://github.com/banfen321/Mirage/archive/refs/heads/main.tar.gz | tar -xz
cd mirage-main
Step 2 – One‑Command Deployment
Mirage includes a deployment script that handles dependencies, generates keys, and starts the services.
chmod +x deploy.sh
./deploy.sh
What the script does:
- Checks for Docker and installs it if missing.
- Builds the custom Sing‑box Docker image.
- Runs the auto‑target selector to pick the best TLS decoy for your region.
- Generates Reality key pairs and short IDs.
- Applies kernel hardening (BBR, TCP Fast Open) via a privileged container.
- Launches the VPN container in host‑network mode.
If you prefer manual control, follow the step‑by‑step instructions below.
Step 3 – Manual Configuration (Optional)
3.1 Docker Compose Overview
The core of Mirage is defined in docker‑compose.yml. It orchestrates three services:
- mirage – the main VPN container (Sing‑box).
- setup – a one‑time utility that generates keys and client profiles.
- sysctl – applies kernel TCP/IP optimizations.
Let’s examine the key security settings:
services:
mirage:
build: ./docker
image: mirage-vpn:latest
container_name: mirage-vpn
restart: always
network_mode: "host"
volumes:
- ./config/config.json:/etc/sing-box/config.json:ro
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /var/run
cap_drop:
- ALL
cap_add:
- NET_ADMIN
- NET_BIND_SERVICE
devices:
- /dev/net/tun:/dev/net/tun
read_only: true– the container’s filesystem is immutable.cap_drop: ALL+ selectivecap_add– least privilege principle.no‑new‑privileges:true– prevents privilege escalation.
3.2 Generate Keys and Config
Run the setup container to create everything needed:
docker compose run --rm setup
This executes scripts/generate_docker.py, which:
- Calls
auto_target.pyto select the optimal TLS decoy (e.g.,www.microsoft.com). - Generates a Reality key pair with
sing‑box generate reality‑keypair. - Creates
config/config.json(server configuration) andconfig/client‑*.json(client profiles). - Outputs the connection details (UUID, public key, short ID, server IP, port, SNI).
Example output:
[+] Selected target: www.microsoft.com (TLS 1.3, 34.2 ms)
[+] Public key: abc123def456...
[+] Short ID: 6b8b4567
[+] Server IP: 132.147.36.250
[+] Port: 10443
[+] UUID: 123e4567-e89b-12d3-a456-426614174000
3.3 Kernel Hardening
The sysctl container runs scripts/sysctl_hardening.sh to enable:
- BBR – congestion control for higher throughput on lossy networks.
- TCP Fast Open – reduces TLS handshake latency.
- Increased buffer sizes – better performance for high‑speed links.
These changes are applied to the host kernel and persist until reboot. To make them permanent, add the same settings to /etc/sysctl.conf.
Step 4 – Start the VPN
Launch the stack:
docker compose up -d
Verify the container is running:
docker ps --filter "name=mirage-vpn"
Check logs for any errors:
docker logs mirage-vpn
You should see a line like:
[INFO] [vless-in] listening on :::10443
Your stealth VPN server is now live.
Step 5 – Client Configuration
Mirage generates ready‑to‑use client profiles in the config/ folder:
config/client‑android.json– for v2rayNG, NekoBox.config/client‑windows.json– for NekoRay, Hiddify Next.config/client‑ios.json– for Shadowrocket, FoXray.
Each profile includes:
- VLESS with
xtls‑rprx‑visionflow. - Reality settings (public key, short ID, decoy SNI).
- uTLS fingerprint (Chrome, Firefox, or randomized).
- Packet fragmentation rules to bypass DPI.
- Split tunneling – only route traffic that needs anonymity.
5.1 Importing on Android (v2rayNG)
- Install v2rayNG from Google Play or GitHub.
- Transfer
client‑android.jsonto your device. - In v2rayNG, tap + → Import config from file.
- Select the JSON file, then tap the V icon to connect.
5.2 Importing on Windows (NekoRay)
- Download NekoRay from its GitHub releases.
- Open NekoRay, click Servers → Import → From file.
- Choose
client‑windows.json. - Right‑click the new server and select Activate.
5.3 Manual Client Configuration
If you prefer to configure clients manually, here are the essential parameters:
| Parameter | Example Value |
|---|---|
| Protocol | VLESS |
| Address | 132.147.36.250 (your server IP) |
| Port | 10443 |
| UUID | 123e4567‑e89b‑12d3‑a456‑426614174000 |
| Flow | xtls‑rprx‑vision |
| Encryption | none |
| TLS Type | reality |
| SNI | www.microsoft.com |
| Public Key | abc123def456... |
| Short ID | 6b8b4567 |
| Fingerprint | chrome |
Step 6 – Testing and Verification
6.1 Connectivity Test
Use curl through the VPN (if you have a CLI client) or visit ipleak.net to confirm your exit IP matches your server’s IP.
6.2 Stealth Test
Run a Wireshark or tcpdump capture on your local machine while connecting. You should see only fragmented TLS 1.3 packets destined to port 443 of the decoy domain—no recognizable VPN signatures.
6.3 Performance Test
# On the server, install iperf3
apt install iperf3 -y
iperf3 -s
# On your client (through the VPN)
iperf3 -c YOUR_SERVER_IP -P 4
Expect throughput close to your VPS’s uplink speed, thanks to BBR and the efficient VLESS protocol.
Technical Deep Dive
How Reality Works
Reality (“Re‑ality”) hijacks the TLS certificate of a legitimate website (the “target”). When a censor inspects the traffic, it sees a valid TLS handshake with, say, www.microsoft.com—not a VPN server. The magic happens during the TLS key exchange, where the server presents a fake certificate that only the client can distinguish from the real one.
Mirage’s auto_target.py intelligently selects the best target based on:
- Geographic proximity – lower latency.
- TLS 1.3 support – mandatory for Reality.
- HTTP/2 or HTTP/3 – indicates a modern, high‑performance server.
Packet Fragmentation
Deep‑packet inspection (DPI) looks for specific byte patterns in the first few packets of a connection. Mirage fragments the TLS ClientHello into random‑sized chunks (e.g., 1440, 900, 1200 bytes) before sending them. The receiving side reassembles them transparently. To the DPI, the traffic looks like ordinary, jumbled TLS—not a VPN handshake.
The fragmentation rules are defined in the client configuration’s transport section:
"transport": {
"type": "tcp",
"fragment": {
"enabled": true,
"interval": "30-100",
"length": "1200-1600"
}
}
Security Hardening
- Rootless container: The Sing‑box binary is granted
CAP_NET_ADMINandCAP_NET_BIND_SERVICEviasetcap, so it can run as a non‑root user (mirage). - Read‑only root filesystem: Prevents persistence attacks.
- Minimal capabilities: Only the two required Linux capabilities are added; all others are dropped.
- Temporary filesystems:
/tmpand/var/runare mounted astmpfsto avoid disk writes. - No new privileges: The container cannot gain additional privileges during runtime.
Troubleshooting
“Connection refused” or timeout
- Check that the server firewall allows the VPN port (default
10443):ufw allow 10443/tcp - Verify the container is bound to the correct interface:
docker exec mirage-vpn netstat -tlnp | grep 10443 - Ensure your VPS provider isn’t blocking outbound TLS (some cheap providers block port 443 for residential IPs).
Slow speeds
- Confirm BBR is active:
sysctl net.ipv4.tcp_congestion_controlShould output
bbr. - Check for CPU/RAM limits on your VPS.
- Consider upgrading to a VPS with a better network (e.g., Hetzner, OVH, AWS).
Client cannot handshake
- Verify the UUID, public key, and short ID match between server and client configs.
- Ensure the decoy target is still reachable (run
scripts/auto_target.pyagain). - Try a different uTLS fingerprint (
chrome,firefox,randomized).
Appendix: Full Configuration Files
docker‑compose.yml
version: "3.3"
services:
mirage:
build:
context: ./docker
dockerfile: Dockerfile
image: mirage-vpn:latest
container_name: mirage-vpn
restart: always
network_mode: "host"
volumes:
- ./config/config.json:/etc/sing-box/config.json:ro
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /var/run
cap_drop:
- ALL
cap_add:
- NET_ADMIN
- NET_BIND_SERVICE
devices:
- /dev/net/tun:/dev/net/tun
depends_on:
sysctl:
condition: service_completed_successfully
stop_grace_period: 5s
setup:
image: mirage-vpn:latest
container_name: mirage-setup
profiles: ["setup"]
user: root
volumes:
- .:/app
working_dir: /app/scripts
network_mode: "host"
cap_add:
- NET_ADMIN
- NET_BIND_SERVICE
command: python3 generate_docker.py
sysctl:
image: alpine:latest
container_name: mirage-sysctl
privileged: true
network_mode: "host"
volumes:
- ./scripts:/scripts
command: /bin/sh -c "apk add --no-cache iptables && /bin/sh /scripts/sysctl_hardening.sh --yes"
Dockerfile
# Dockerfile for Project Mirage
# Base: Alpine Linux (Minimal ~5MB)
# Role: Sing-box Server with Network Debug Tools
# Stage 1: Get Sing-box Binary
FROM ghcr.io/sagernet/sing-box:latest AS fetcher
# Stage 2: Final Runtime
FROM alpine:latest
LABEL maintainer="Mirage Project"
LABEL description="High-End OpSec VPN Node"
# Install Essential Debug Tools & Security Dependencies
# - libcap: for setcap (to avoid running as root)
RUN apk add --no-cache \
curl \
bind-tools \
iproute2 \
openssl \
jq \
ca-certificates \
tzdata \
tini \
libcap \
iptables \
python3
# Create unprivileged user
RUN addgroup -S mirage && adduser -S mirage -G mirage
# Copy binary
COPY --from=fetcher /usr/local/bin/sing-box /usr/local/bin/sing-box
# Grant capabilities to the binary so it can run as non-root
# cap_net_admin: for TUN interface
# cap_net_bind_service: for binding to port 443
RUN setcap 'cap_net_admin,cap_net_bind_service=+ep' /usr/local/bin/sing-box
# Setup environment
WORKDIR /etc/sing-box
RUN chown -R mirage:mirage /etc/sing-box
# Switch to non-root user
USER mirage
ENV CONFIG_PATH=/etc/sing-box/config.json
# Entrypoint via Tini for proper signal handling
ENTRYPOINT ["/sbin/tini", "--"]
# Default command
CMD ["sing-box", "run", "-c", "/etc/sing-box/config.json"]
Example Server Config (config/config.json)
{
"log": {
"level": "warn",
"timestamp": true
},
"dns": {
"servers": [
{
"tag": "local",
"type": "local"
}
]
},
"inbounds": [
{
"type": "vless",
"tag": "vless-in",
"listen": "::",
"listen_port": 10443,
"users": [
{
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"flow": "xtls-rprx-vision"
}
],
"tls": {
"enabled": true,
"server_name": "www.microsoft.com",
"reality": {
"enabled": true,
"handshake": {
"server": "www.microsoft.com",
"server_port": 443
},
"private_key": "REPLACE_ME_PRIVATE_KEY",
"short_id": ["6b8b4567"]
}
}
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
},
{
"type": "block",
"tag": "block"
}
]
}
Kernel Hardening Script (scripts/sysctl_hardening.sh)
#!/bin/sh
# Project Mirage – Kernel TCP/IP Hardening
# Enables BBR, TCP Fast Open, and optimizes buffers for high‑speed VPN.
set -e
if [ "$1" = "--yes" ]; then
AUTO_YES=1
fi
apply_sysctl() {
local key="$1"
local value="$2"
if sysctl -w "$key=$value" >/dev/null 2>&1; then
echo "[OK] $key = $value"
else
echo "[WARN] Failed to set $key"
fi
}
echo "[*] Applying Mirage kernel tuning..."
# BBR congestion control
apply_sysctl net.ipv4.tcp_congestion_control bbr
apply_sysctl net.core.default_qdisc fq
# TCP Fast Open
apply_sysctl net.ipv4.tcp_fastopen 3
# Increase TCP buffer sizes
apply_sysctl net.core.rmem_max 134217728
apply_sysctl net.core.wmem_max 134217728
apply_sysctl net.ipv4.tcp_rmem "4096 87380 134217728"
apply_sysctl net.ipv4.tcp_wmem "4096 65536 134217728"
# Other performance tweaks
apply_sysctl net.ipv4.tcp_mtu_probing 1
apply_sysctl net.ipv4.tcp_slow_start_after_idle 0
apply_sysctl net.ipv4.tcp_notsent_lowat 16384
echo "[+] Kernel tuning completed."
Conclusion
Project Mirage delivers a production‑grade stealth VPN that is:
- Undetectable – looks like ordinary HTTPS traffic.
- Fast – leverages BBR and modern TCP optimizations.
- Secure – runs in a hardened, least‑privilege container.
- Automated – from deployment to client‑profile generation.
By following this guide, you now have a private VPN that can bypass even the most advanced censorship systems. Remember to keep your server updated, monitor logs for unusual activity, and rotate keys periodically for added security.
For updates, bug reports, and community support, visit the Mirage GitHub repository.