Skip to main content

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)
  1. An admin creates a tunnel resource pointing to a private target (e.g., 10.0.1.50:5432)
  2. EntryGuard allocates a permanent TCP port on edge.entryguard.io (e.g., port 41234)
  3. The agent in the private network connects outbound to the edge via WebSocket
  4. When a user starts a session, their IP is allowed on that tunnel port
  5. The user connects to edge.entryguard.io:41234 — traffic is proxied through the agent to the target
  6. When the session expires, the IP is revoked and all active connections are terminated
Same access control as everything else

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:connect scope

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"
One agent, flexible capabilities

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:

  1. Go to Resources → Add Resource
  2. Select provider: AGENT
  3. Select resource type: Tunnel
  4. Select your agent credential
  5. Enter a name (e.g., production-db)
  6. 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)
  7. 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:

  1. Go to Roles → Edit Role
  2. Add the tunnel resource
  3. 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:

  1. The IP is immediately removed from the tunnel's allowlist
  2. All active TCP connections from that IP are terminated — the user sees a connection reset
  3. 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

LayerProtection
IP allowlistOnly IPs with active sessions can connect to tunnel ports
Role-based accessUsers only see tunnels assigned to their roles
Agent target allowlistThe agent only dials targets configured as tunnels — prevents network scanning
TLSAgent ↔ Edge communication is encrypted (WebSocket over TLS)
Forced terminationActive connections are killed on session expiry
User ↔ Edge is raw TCP

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_url in config (must be wss://, not https://)

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