Expose multiple services on a single hostname with HTTP and TCP on different ports
Multi-port tunneling allows you to expose multiple services (HTTP, TCP, databases, APIs) under a single tunnel hostname. This is perfect for full-stack applications where you need to expose both your web frontend and backend services like databases.
All HTTP services share one tunnel. Path-based routing happens server-side.
Key Benefits:
| Protocol | Tunnel Counting |
|---|---|
| HTTP | All ports share 1 parent tunnel |
| WebSocket | Shares the HTTP parent tunnel |
| TCP | Each port = 1 child tunnel |
| UDP | Each port = 1 child tunnel |
Example: 1 multiport tunnel with 20 HTTP services (1 tunnel) + 3 TCP ports (3 tunnels) = 4 tunnels toward your limit.
# Start your services locally
$ npm run dev # HTTP server on port 3000
$ docker run -p 5432:5432 postgres # PostgreSQL on port 5432
# Create multi-port tunnel
$ stunl -id myapp -ports "web:3000:http,db:5432:tcp"
● SIMPLETUNNEL
╭── ◎ ── HTTP web
│ HTTPS https://myapp.stunl.io
│ HTTP http://myapp.stunl.io
│ Local localhost:3000
╭── ⇄ ── TCP db
│ Connect telnet myapp.stunl.io 15432
│ Local localhost:5432
Add multiple services by extending the -ports comma-separated list:
# Start your services
$ npm run dev # Port 3000
$ docker run -p 5432:5432 postgres
$ docker run -p 6379:6379 redis
# Create tunnel with multiple TCP ports
$ stunl -id myapp -ports "web:3000:http,db:5432:tcp,cache:6379:tcp"
● SIMPLETUNNEL
╭── ◎ ── HTTP web
│ HTTPS https://myapp.stunl.io
│ HTTP http://myapp.stunl.io
│ Local localhost:3000
╭── ⇄ ── TCP db
│ Connect telnet myapp.stunl.io 15432
│ Local localhost:5432
╭── ⇄ ── TCP cache
│ Connect telnet myapp.stunl.io 16379
│ Local localhost:6379
# 1. Start all services locally
$ npm run dev # Next.js on 3000
$ docker compose up postgres redis # DB on 5432, Redis on 6379
# 2. Create multi-port tunnel with custom hostname
$ stunl -id myapp -ports "app:3000:http,db:5432:tcp,cache:6379:tcp"
● SIMPLETUNNEL
╭── ◎ ── HTTP app
│ HTTPS https://myapp.stunl.io
│ HTTP http://myapp.stunl.io
│ Local localhost:3000
╭── ⇄ ── TCP db
│ Connect telnet myapp.stunl.io 15432
│ Local localhost:5432
╭── ⇄ ── TCP cache
│ Connect telnet myapp.stunl.io 16379
│ Local localhost:6379
# 3. Update your .env to use public endpoints
DATABASE_URL="postgresql://user:pass@myapp.stunl.io:15432/mydb"
REDIS_URL="redis://myapp.stunl.io:16379"
# 4. Share with your team
Frontend: https://myapp.stunl.io
Database: myapp.stunl.io:15432
Cache: myapp.stunl.io:16379
Reserved Ports: Keep Your Port Numbers
Notice those port numbers (15432, 16379)? By default, TCP/UDP ports are randomly assigned from range 10001-19999 each time you connect. With reserved ports, you lock in specific port numbers that persist across reconnects.
# Use @port syntax to request a reserved port
$ stunl -ports "web:3000:http,db:5432:tcp@15432,cache:6379:tcp@16379"
Why reserve ports?
Pro includes 2 reserved ports free (max 10). Reserve ports at portal.stunl.com first, then use them with @port syntax.
Once your tunnel is running, connect to your TCP services using the assigned public port:
# Using psql
$ psql -h myapp.stunl.io -p 15432 -U myuser -d mydb
# Connection string
postgresql://myuser:mypass@myapp.stunl.io:15432/mydb
# In your app (Node.js)
const { Pool } = require('pg');
const pool = new Pool({
host: 'myapp.stunl.io',
port: 15432,
user: 'myuser',
password: 'mypass',
database: 'mydb'
});
# Using mysql client
$ mysql -h myapp.stunl.io -P 13306 -u root -p
# Connection string
mysql://root:password@myapp.stunl.io:13306/mydb
# Using redis-cli
$ redis-cli -h myapp.stunl.io -p 16379
# Connection string
redis://myapp.stunl.io:16379
# Using mongosh
$ mongosh "mongodb://myapp.stunl.io:17017/mydb"
# Connection string
mongodb://myapp.stunl.io:17017/mydb
Share your entire application stack (frontend + backend + database) with one URL.
Let remote developers connect to your local database for debugging without VPN.
Expose multiple microservices on different TCP ports for integration testing.
Show clients a complete working application with real data and database connections.
Pro Tip: HTTP Password Protection
Add password protection to your HTTP services:
$ stunl -ports "web:3000:http" -password mySecret123
Note: Password protection applies to HTTP/WebSocket only. TCP/UDP ports rely on application-level authentication (e.g., database credentials).
| Feature | Pro |
|---|---|
| Total tunnels | 10 |
| HTTP services per multiport tunnel | Unlimited |
Custom hostname (-id) |
✓ |
| Monthly bandwidth | 25 GB |
| Reserved TCP ports | 2 included |
How Tunnel Counting Works