Nahan (Persian for Hidden/Concealed) is a secure, lightweight, and highly customizable reverse proxy that runs entirely on the edge. It transforms your Cloudflare Worker into a powerful, obfuscated gateway using VLESS or Trojan protocols, managed via a beautiful, self-contained Web UI.
- Why Nahan?
- Key Features
- Prerequisites
- Step-by-Step Deployment Guide
- Dashboard Guide
- Advanced Configuration
- Applying Configuration Changes
- File Structure
- FAQ & Troubleshooting
- Contributing
- License
Nahan isn't just a proxy script — it's a complete management solution designed for stealth, speed, and ease of use.
- 🛡️ Hidden in Plain Sight: Unauthorized access attempts are proxied to legitimate sites (e.g.,
ubuntu.comordocker.com), making your gateway look like a regular website to network scanners. - ⚡ Zero Server Cost: Runs entirely on Cloudflare's free plan. No VPS, no server maintenance.
- 🎨 Modern Dashboard: A fully embedded, mobile-friendly dashboard with Dark/Light modes and dual-language support (English / فارسی).
- 🤖 Telegram Bot Integration: Manage your gateway, check usage, and receive login alerts directly via Telegram.
- 📡 Multi-User & Multi-IP: Generate dedicated subscription links for different users and automatically combine them with clean IP lists.
- 💾 D1 SQLite Storage: Configuration persists in Cloudflare D1 database, eliminating KV write limitations.
| Feature | Description |
|---|---|
| 🔐 Dual Protocol | Switch instantly between VLESS (Alpha), Trojan (Beta), or Both simultaneously |
| 📱 QR Code Generation | Modal-based QR codes for instant mobile client configuration |
| 👥 Multi-User Profiles | Create separate profiles (uuid:name) with unique subscription links per user |
| 🌍 Clean IP Multiplexer | Input a list of clean Cloudflare IPs — Nahan auto-generates configs for all of them |
| ⚙️ Real-Time Metrics | View Origin IP, Edge Node location, and run browser-side latency diagnostics |
| 💾 D1 SQLite Storage | All configuration persists in Cloudflare D1 even after code updates |
| 🚨 Kill Switch | Immediately pause all proxy traffic with one click from the dashboard or Telegram |
| 📊 Bandwidth Management | Track per-user upload/download with TB/GB limits and pause/resume controls |
| 📋 Activity Logs | Full history of login attempts and configuration changes |
| 🔒 ECH Support | Toggle Encrypted Client Hello (ECH) parameters in generated client configs |
| 📦 Backup & Restore | Export/import your full configuration as a .json file |
- A Cloudflare account (free tier is sufficient) — sign up here
- Access to Workers & Pages and D1 SQLite Database in your Cloudflare Dashboard
- A modern web browser
- (Optional) A Telegram Bot Token and Chat ID for bot integration
Follow these steps to get your Nahan gateway running in under 5 minutes.
Nahan stores all configuration in a Cloudflare D1 SQLite database. You must create this first.
- Log in to the Cloudflare Dashboard.
- In the left sidebar, go to Storage and databases → D1 SQLite Database.
- Click Create database.
- Enter a name for your database — the suggested name is
iot_db(the exact name doesn't matter). - Click Create to confirm.
✅ Your D1 database is now ready. Keep this page open — you'll need it in Step 3.
- In the Cloudflare Dashboard, navigate to Workers & Pages → Overview.
- Click Create application → Create Worker.
- Enter a name for your worker (e.g.,
nahan-core). - Click Deploy to create the worker with placeholder code.
- On the confirmation screen, click Edit code to open the online editor.
- Select all existing placeholder code and delete it.
- Open the Nahan repository and go to
_worker.js. - Click Raw, then select all and copy the full contents.
- Paste the copied code into the Cloudflare editor.
- Click Save and Deploy.
✅ Your worker is deployed. It will not function fully until the D1 database is bound in the next step.
This step connects your D1 database to the worker so Nahan can read and write its configuration.
- From the Workers & Pages overview, click on your worker (e.g.,
nahan-core). - Go to the Settings tab.
- Scroll to the Bindings section and click Add binding.
- Select D1 database as the binding type.
- Fill in the two fields:
- Variable name:
IOT_DB← this must be exact, regardless of your database's actual name - D1 Database: Select the database you created in Step 1
- Variable name:
- Click Save.
- Return to the worker overview and click Deploy (or Redeploy) to apply the binding.
✅ Nahan can now read and write persistent configuration data.
-
From your worker's overview page, copy the worker URL — it looks like:
https://nahan-core.<your-subdomain>.workers.dev -
In a browser, navigate to:
https://<your-worker-domain>/sync/dashNote: Visiting the root URL (
/) or/syncwithout/dashintentionally shows a camouflage page (e.g., Ubuntu or Docker) to fool network scanners. This is expected behavior. -
You should see the Nahan login screen.
-
Enter the default master key and click Authenticate:
admin⚠️ If you see⚠️ IOT_DB namespace missing!— your D1 database binding is not set up correctly. Return to Step 3. -
You are now inside the Nahan dashboard.
-
Immediately go to the System tab and:
- Change the Master Key from
adminto a strong, private passphrase. - Change the API Route from
syncto a secret keyword (e.g.,my-secret-path). Your dashboard will move to/<new-route>/dash. - Set your Device UUID or leave it blank to auto-generate one.
- Change the Master Key from
-
Click Update Config to save.
✅ Your gateway is now live and secured.
The dashboard has 5 sections accessible via the top navigation tabs.
Retrieve your connection strings to import into a proxy client (e.g., v2rayN, Hiddify, Shadowrocket, Nekoray).
- Profile Cards: Each configured profile (Default + Multi-User) appears as a card.
- Show QR Code: Tap Show QR Code on any card to display a scannable QR — great for mobile setup.
- Cloud Sync URL: The subscription URL for your client app. Use the copy button to grab it.
Live diagnostics about the Cloudflare edge node processing your requests.
- Live Profile Usage: Active connection counts and last activity timestamps per profile (resets on worker restart).
- Network Cards: Origin IP, executing Edge Node (Colo), and regional metadata.
- Latency Diagnostics: Click Run Diagnostics to measure real-time latency to your configured Clean IPs.
Core gateway configuration:
| Setting | Description |
|---|---|
| Primary Display Mode | Toggle between Alpha (VLESS), Beta (Trojan), or both |
| Device UUID | Connection identifier/password. Leave blank to auto-generate |
| API Route | Change from sync to a secret keyword — moves the dashboard to /<keyword>/dash |
| Master Key | Login password. Change from admin immediately |
| Backup & Restore | Export all settings to .json or restore from a previous backup |
Fine-tune transport and integrations:
| Setting | Description |
|---|---|
| Clean IPs | Comma/line-separated Cloudflare clean IPs — subscription auto-multiplies configs for each |
| Multi-User Profiles | uuid:Name format entries for per-user subscription links |
| Telegram Bot | Bot Token + Chat ID for login alerts and remote management |
| Cloudflare Analytics | Account ID + API Token to monitor daily request usage (100k/day free limit) |
| Kill Switch | Instantly pause all proxy traffic without deleting the worker |
| Secure Hello (ECH) | Toggle Encrypted Client Hello in generated configs |
Timestamped history of all login attempts and configuration changes for auditing.
- Go to the Advanced tab.
- In the Multi-User Profiles field, add entries (one per line) in this format:
Example:
<uuid>:Username550e8400-e29b-41d4-a716-446655440000:Alice 6ba7b810-9dad-11d1-80b4-00c04fd430c8:Bob - Each user accesses their config by appending
?sub=Usernameto the Sync URL:https://<your-worker-domain>/sync/sub?sub=Alice
- Go to the Advanced tab.
- In Clean IPs, enter one IP or hostname per line (or comma-separated):
1.2.3.4 5.6.7.8 cleanip.example.com - Click Update Config. The subscription output will include a separate config entry for each IP.
- Create a bot via @BotFather and copy the Bot Token.
- Get your Chat ID from @userinfobot.
- In the Advanced tab, enter your Bot Token and Chat ID.
- Click Update Config.
Available Telegram commands:
/status— Check gateway status/pause— Activate the Kill Switch
To immediately suspend all proxy traffic:
- Go to the Advanced tab.
- Toggle Kill Switch to ON.
- Click Update Config.
Or send /pause to your Telegram bot. To re-enable, toggle it OFF and save.
After adjusting anything in System or Advanced:
- Click Update Config at the bottom of the screen.
- The indicator shows "Syncing..." then the page auto-reloads.
- If you changed the API Route, the page will redirect to
/<new-route>/dash— bookmark the new URL.
nahan/
├── _worker.js # Main Cloudflare Worker script (the entire gateway)
├── HELP.md # English dashboard walkthrough
├── HELP_FA.md # Persian (فارسی) dashboard walkthrough
├── README.md # This file (English)
├── README_FA.md # Persian (فارسی) version of README
└── version # Current version indicator
Q: I see ⚠️ IOT_DB namespace missing! after logging in.
The D1 database is not bound to your worker. Go back to Step 3, add the
IOT_DBD1 binding, and redeploy.
Q: My worker's root URL shows a random website instead of the dashboard.
This is intentional — Nahan camouflages itself. Always use
https://<your-worker-domain>/sync/dash.
Q: I changed the API Route and can't find the dashboard anymore.
Your dashboard moved to
https://<your-worker-domain>/<new-route>/dash. If you've forgotten the route, check the D1 database via the Cloudflare Dashboard → D1 → your database → browse thekv_storetable.
Q: I forgot my Master Key.
In the Cloudflare Dashboard, go to D1 → your database → Console, and run:
SELECT * FROM kv_store WHERE key = 'masterKey';You can also
UPDATEorDELETEthe row to reset it.
Q: How do I update to a newer version of Nahan?
Repeat Step 2: open the Worker code editor, replace the code with the latest
_worker.js, and save. Your D1 configuration is preserved.
Q: How many requests can I handle on the free tier?
Cloudflare Workers free tier allows 100,000 requests/day. Monitor usage via the Cloudflare Analytics integration in the Advanced tab.
- Fork the repository.
- Create a branch:
git checkout -b feature/my-feature - Make your changes to
_worker.js. - Commit:
git commit -m "Add my feature" - Push:
git push origin feature/my-feature - Open a Pull Request.
This project is licensed under the MIT License. See the LICENSE file for details.
Made with ❤️ by the Open Source Community