Self-Hosted Ngrok Alternative in 200 Lines of Node.js
Source: Dev.to
Problem
Need to tunnel multiple local services, but the free tier of Ngrok only provides a single tunnel.
Solution
A self‑hosted tunnel written in ~200 lines of Node.js. It can create multiple public URLs with a single command.
liptunnel http 3000,8080,5000 --multi
This command creates three public URLs on your domain, routing traffic as:
User → yourdomain.com → VPS → WebSocket → Your PC → localhost
Core concept
Server (forward HTTP via WebSocket)
// server.js (Express middleware)
app.use((req, res) => {
const subdomain = req.headers.host.split('.')[0];
tunnels[subdomain].ws.send(JSON.stringify(req));
// Wait for response, then send it back to the client
});
Client (receive, proxy, respond)
// client.js
ws.on('message', (data) => {
const request = JSON.parse(data);
const proxy = http.request(
{
hostname: 'localhost',
port: request.port,
path: request.path,
method: request.method,
headers: request.headers,
},
(response) => {
let body = '';
response.on('data', (chunk) => (body += chunk));
response.on('end', () => {
ws.send(
JSON.stringify({
statusCode: response.statusCode,
headers: response.headers,
body,
})
);
});
}
);
proxy.end(request.body);
});
The rest of the implementation handles error cases, connection management, and cleanup.
Features
- Privacy – Traffic never leaves your infrastructure.
- Cost – Only the expense of your VPS (free beyond that).
- Branding – Use your own domain for tunnel URLs.
- Control – Full customization of routing and handling.
Performance
- Memory: ~25 MB per tunnel
- Latency: ~5 ms overhead
- Throughput: 100+ requests/second
Use cases
- Quick setup of microservices locally
- Testing webhooks (Stripe, GitHub, etc.) without deploying
- Demonstrations with client‑branded URLs
- Compliance‑sensitive environments (healthcare, finance) where third‑party services are prohibited
Setup
# Clone the repository
git clone https://github.com/ibrahimpelumi6142/liptunnel
cd liptunnel
# Install dependencies
npm install
# Run the server on your VPS
node server/server.js # <-- start on the remote machine
# Start a tunnel from your local machine
liptunnel http 3000 # <-- replace 3000 with the port you want to expose
Technology stack
- Node.js – runtime
- WebSocket – tunnel transport
- Express – optional dashboard (no heavy frameworks)
All code resides in a single ~200‑line project.
Roadmap (coming soon)
- HTTPS support via Let’s Encrypt
- Fixed subdomains
- Authentication tokens for tunnel access
- Request inspector UI
Contributing
If you find the project useful, consider starring it on GitHub:
Feel free to open issues or submit pull requests for improvements.