Your Personal "Invisible" Proxy: VLESS + WebSocket + Cloudflare in 20 Minutes
Hey there, fellow tinkerers and internet escape artists! Today we're building a proxy so sneaky that your ISP will think you're binge-watching cat videos, while you're actually doom-scrolling through banned Twitter memes. No fluff—just the goods, a few killer tweaks, and a dash of humor because IT without laughs is just sad.
What you'll get at the end:
- A VLESS proxy with TLS encryption
- A WebSocket tunnel through Cloudflare (your VPS IP stays hidden)
- Masquerade as a regular website (NGINX serves a plain HTML page)
- Bypass DPI and IP-based blocking
Let's roll!
Step 1: VPS – Our Warhorse
Pick any VPS provider (DigitalOcean, Vultr, Hetzner – no sponsors here). Go with Ubuntu 22.04 or 24.04 LTS (skip older versions – they're a pain).
ssh root@<your-server-IP>
# Enter password or use key-based auth
Update everything that moves:
apt update && apt upgrade -y
apt install curl wget unzip nginx -y
Firewall (UFW) setup:
Open only the essentials – 22 (SSH), 80 (HTTP), 443 (HTTPS). Block the rest.
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status
You'll see something like:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
Now your server is ready for adventure.
Step 2: Cloudflare – Masking & Protection
Cloudflare sits between the user and your server, hiding the real IP. It also proxies WebSocket – exactly what we need.
- Go to dash.cloudflare.com, add your domain (update NS records at your registrar).
- Create an A record: your_domain.com → VPS IP, enable proxy (orange cloud).
- Under SSL/TLS, set mode to Full (strict) – end-to-end encryption.
- Enable Always Use HTTPS.
- Under Network, ensure WebSockets are on (they are by default).
- Create a Page Rule for the secret path (e.g.,
/secret-ws/*):- URL: your_domain.com/secret-ws/*
- Settings: Cache Level – Bypass, Security Level – Medium, WebSockets – On.
This path is used exclusively for proxying; all other requests go to our decoy site.
Certificate:
You can use free Let's Encrypt (we'll set it up later) or generate an Origin CA in Cloudflare. I recommend Let's Encrypt – simpler and auto-renews.
Step 3: X-Ray – The Heart of Our Proxy
X-Ray is a V2Ray fork that supports VLESS and other goodies. Install with a single command:
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
(Note: the PDF had a typo – Xray- install – we fixed it; don't repeat others' mistakes!)
Generate a UUID for your client:
xray uuid
# Save the output, e.g., d342d11e-d424-4583-b36e-524ab1f0afa4
Now edit the config /usr/local/etc/xray/config.json. Stop the service before editing:
systemctl stop xray
Paste the following corrected and complete JSON:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "YOUR-UUID-HERE",
"level": 0
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "tls",
"wsSettings": {
"path": "/secret-ws"
},
"tlsSettings": {
"certificates": [
{
"certificateFile": "/etc/letsencrypt/live/your_domain.com/fullchain.pem",
"keyFile": "/etc/letsencrypt/live/your_domain.com/privkey.pem"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
Critical points:
port: 8443– X-Ray listens locally on this port; NGINX will proxy to it from port 443.path: "/secret-ws"– must match the Page Rule. You can add?ed=2048for early data (speeds up handshake) – but that's configured on the client side.security: "tls"– without it, your traffic is an open book to DPI.
Save, start, and enable auto-start:
systemctl start xray
systemctl enable xray
systemctl status xray # should show active (running)
Step 4: Let's Encrypt Certificate – Play by the Rules
Install certbot and obtain a certificate for your domain:
apt install certbot python3-certbot-nginx -y
certbot --nginx -d your_domain.com
Follow the prompts (enter email, agree). After success, certbot will update your NGINX config and add the certificate paths.
Update the paths in config.json (if they differ) and restart X-Ray:
systemctl restart xray
Step 5: NGINX – Masquerade as a Real Website
NGINX will serve a plain HTML page to anyone visiting your domain, and only proxy traffic to X-Ray on the secret path /secret-ws.
Create a dummy site (so you don't show an empty page):
mkdir -p /var/www/html
echo '<!DOCTYPE html><html><body><h1>Hey, this is my cat blog</h1><p>Your ad could be here, but I'm proxying traffic instead.</p></body></html>' > /var/www/html/index.html
Now edit /etc/nginx/sites-available/default (or create a new one, but we'll keep it simple). Insert this config:
server {
listen 80;
server_name your_domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your_domain.com;
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
# Main decoy site
location / {
root /var/www/html;
index index.html;
try_files $uri $uri/ =404;
}
# WebSocket proxy to X-Ray
location /secret-ws {
proxy_pass http://127.0.0.1:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
}
Test the syntax and reload NGINX:
nginx -t
systemctl reload nginx
Now if you open your browser to https://your_domain.com – you'll see the cat blog page. But if you connect via client on /secret-ws – proxy traffic flows.
Step 6: Nekoray Client – Set Up in 2 Minutes
Download Nekoray (Windows, Linux, Android) from GitHub. Unzip and run.
Add a new configuration:
- Group → Add → VLESS
- Address: your_domain.com
- Port: 443
- UUID: the one generated in Step 3
- Encryption: none
- Transport: ws
- Path:
/secret-ws?ed=2048(early data speeds up the first packet, but optional) - Host: your_domain.com
- TLS: enable, Allow Insecure – off (to verify certificate)
Or just copy the ready-made link (replace with your data):
vless://<UUID>@your_domain.com:443?type=ws&path=%2Fsecret-ws%3Fed%3D2048&host=your_domain.com&security=tls#MyCloudflareProxy
Import it via Import from Clipboard.
Connect – and voilà! Check your IP at whatismyipaddress.com – it should be a Cloudflare IP, not your VPS.
Step 7: Testing & Anti-Blocking Tricks
- Open a blocked site (e.g., Twitter) – it should work.
- Speed test: run speedtest.net through the proxy – expect 50–200 Mbps (depends on your VPS).
- Locally, test via SOCKS5: Nekoray sets up a proxy on 127.0.0.1:1080 – run
curl -x socks5://127.0.0.1:1080 http://ipinfo.io.
Extra hardening:
- Add
fallbacksto X-Ray config – if incoming traffic isn't VLESS, it gets forwarded to port 80 (NGINX), so even port scanning won't reveal the proxy.
Example snippet inside inbounds:
"fallbacks": [
{ "dest": 80, "xver": 0 }
]
- Increase NGINX timeouts (we already set 86400 seconds – 24 hours).
- Disable buffering by adding
proxy_buffering off;inside the/secret-wslocation – helps with long-lived connections.
Log monitoring:
- X-Ray:
journalctl -u xray -f - NGINX:
tail -f /var/log/nginx/error.log
If you see errors like upstream timed out – bump the timeouts even higher.
Conclusion: What Did We Build?
We've assembled a fully working, obfuscated proxy that:
- Hides your real IP behind Cloudflare
- Encrypts traffic with TLS
- Masquerades as a plain website
- Uses WebSocket – harder to detect
Your ISP sees only HTTPS connections to Cloudflare, inside which is a WebSocket chat with your server. Nobody will guess you're watching forbidden content instead of cat videos.
Final tips:
- If you use Cloudflare Origin CA instead of Let's Encrypt, don't forget to set SSL/TLS mode to Full (strict).
- Certificates auto-renew with certbot – keep it that way.
- For extra anonymity, add
"flow": "xtls-rprx-vision"to both client and server settings – it's a new XTLS feature that makes traffic look even more like regular HTTPS.
That's all, folks. If something goes wrong – re-read the guide, you probably forgot a comma in the JSON.
Good luck evading censorship, and remember: the internet should be free, and ISPs should be oblivious! 🚀