Secure Tunnels to Private Networks
Tunnels let you access databases, APIs, and services that are behind NAT, in private subnets, or otherwise unreachable from the internet — without a VPN, without exposing public IPs.
How It Works
You (public IP)
│
│ TCP connection to edge.entryguard.io:41234
▼
Edge Service (public)
│ 1. Check your IP against active sessions
│ 2. Find the agent WebSocket for this tunnel
│ 3. Open a multiplexed stream
▼
Agent (customer's private network)
│ 4. Dial the local target (10.0.1.50:5432)
│ 5. Bidirectional byte proxying
▼
Target Service (10.0.1.50:5432)
- An admin creates a tunnel resource pointing to a private target (e.g.,
10.0.1.50:5432) - EntryGuard allocates a permanent TCP port on
edge.entryguard.io(e.g., port 41234) - The agent in the private network connects outbound to the edge via WebSocket
- When a user starts a session, their IP is allowed on that tunnel port
- The user connects to
edge.entryguard.io:41234— traffic is proxied through the agent to the target - When the session expires, the IP is revoked and all active connections are terminated
Tunnels use the exact same session model as cloud firewall resources. Time-bounded access, role-based permissions, automatic cleanup, full audit trail.
Prerequisites
- EntryGuard Starter plan or above (Free plan: 0 tunnels, Starter: 3, Team: 10, Business: unlimited)
- Agent version v0.5.3 or later (earlier versions have a stream registration bug that causes connections to drop)
- An agent running in the private network with tunnel mode enabled
- An API key with the
agent:connectscope
Setup
1. Install and Initialize the Agent
Follow the standard Agent Installation & Setup to install eg-agent and run eg-agent init.
2. Configure the Agent
The agent supports three modes depending on your use case. Edit the config file at /etc/eg-agent/config.yml (Linux) or C:\eg-agent\config.yml (Windows).
Tunnels only (no scripts)
Use this when you only need to access private network resources through tunnels:
server:
url: "https://app.entryguard.io/api/v1"
api_key: "eg_..."
agent:
name: "prod-agent"
tunnel:
enabled: true
edge_url: "wss://edge.entryguard.io"
Scripts only (no tunnels)
Use this when you only need custom IP whitelisting scripts (iptables, ufw, etc.):
server:
url: "https://app.entryguard.io/api/v1"
api_key: "eg_..."
agent:
name: "prod-agent"
scripts:
apply: "/etc/eg-agent/scripts/apply.sh"
revoke: "/etc/eg-agent/scripts/revoke.sh"
Both tunnels and scripts
Use this when the same agent needs to both run scripts and proxy tunnel connections:
server:
url: "https://app.entryguard.io/api/v1"
api_key: "eg_..."
agent:
name: "prod-agent"
scripts:
apply: "/etc/eg-agent/scripts/apply.sh"
revoke: "/etc/eg-agent/scripts/revoke.sh"
tunnel:
enabled: true
edge_url: "wss://edge.entryguard.io"
A single agent handles both modes concurrently. Script commands are polled from EntryGuard, while tunnel streams flow through a WebSocket connection to the edge service. Each mode operates independently.
3. Restart the Agent
sudo systemctl restart eg-agent
You should see in the logs:
[tunnel] connecting to edge at wss://edge.entryguard.io
[tunnel] connected to edge at wss://edge.entryguard.io
[tunnel] targets updated: [10.0.1.50:5432]
4. Create a Tunnel Resource in EntryGuard
In the dashboard:
- Go to Resources → Add Resource
- Select provider: AGENT
- Select resource type: Tunnel
- Select your agent credential
- Enter a name (e.g.,
production-db) - Fill in the config:
- Target Host: The private IP or hostname (e.g.,
10.0.1.50) - Target Port: The port to connect to (e.g.,
5432)
- Target Host: The private IP or hostname (e.g.,
- Click Create
EntryGuard will allocate a permanent TCP port on edge.entryguard.io. The connection string appears in the resource list:
edge.entryguard.io:41234 → 10.0.1.50:5432
5. Assign to a Role
Add the tunnel resource to a role so users can access it through sessions:
- Go to Roles → Edit Role
- Add the tunnel resource
- Assign users to the role
6. Connect
Start a session (dashboard, CLI, or API), then connect to the tunnel:
# Start a session
eg session start --duration 4
# Connect to the tunnel
psql -h edge.entryguard.io -p 41234 -U myuser -d mydb
The CLI shows tunnel connection details:
✓ Session started
Tunnel resources:
production-db edge.entryguard.io:41234
Session expires in 4h 0m
One Agent, Multiple Tunnels
A single agent can serve multiple tunnels. Each tunnel gets its own port:
Private network 10.0.1.0/24
├── PostgreSQL 10.0.1.50:5432 → edge.entryguard.io:41234
├── Redis 10.0.1.51:6379 → edge.entryguard.io:41235
└── Internal API 10.0.1.100:8080 → edge.entryguard.io:41236
▲
│
Single Agent ── WebSocket ──→ Edge Service
Each tunnel is a separate resource — assign them to different roles to control who can access what.
Connection String Never Changes
The port allocated to a tunnel is permanent. It stays the same regardless of agent restarts, edge restarts, or configuration changes. Your connection strings and tooling configs are stable.
Session Expiry Behavior
When a session expires or is stopped:
- The IP is immediately removed from the tunnel's allowlist
- All active TCP connections from that IP are terminated — the user sees a connection reset
- New connections from that IP are silently rejected
This matches EntryGuard's promise of time-bounded access. Database clients handle disconnections gracefully — start a new session and reconnect.
Security
| Layer | Protection |
|---|---|
| IP allowlist | Only IPs with active sessions can connect to tunnel ports |
| Role-based access | Users only see tunnels assigned to their roles |
| Agent target allowlist | The agent only dials targets configured as tunnels — prevents network scanning |
| TLS | Agent ↔ Edge communication is encrypted (WebSocket over TLS) |
| Forced termination | Active connections are killed on session expiry |
The connection between the user and the edge service is raw TCP. Encryption is the application's responsibility (e.g., PostgreSQL sslmode=require, Redis TLS, HTTPS for APIs).
Troubleshooting
Agent can't connect to edge
Check that the agent can reach edge.entryguard.io:443 outbound:
curl -v https://edge.entryguard.io/health
Common issues:
- Corporate proxy blocking WebSocket upgrades
- Firewall blocking outbound port 443
- Incorrect
edge_urlin config (must bewss://, nothttps://)
Connection refused on tunnel port
- Verify the agent is connected (check agent status in the dashboard)
- Verify you have an active session
- Check your public IP matches the session IP
Connection resets immediately
- Agent version too old — versions before v0.5.3 have a race condition where the first data packet is dropped, causing the connection to fail silently. Upgrade to v0.5.3+
- Session may have expired — check remaining time
- The target service may be down — agent logs will show dial failures