> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# What a Tunnel Is

> A tunnel is a process within the user's network on one side, and the next hop of a route or the target of a service or hostname on the other. Each point below shows it on the Quick Start setup.

A tunnel has two sides. Within the user's network it is a process. Within Telnyx it is the next hop of a route on a [*Network*](https://developers.telnyx.com/docs/network/overview.md), or the target of a [private service](https://developers.telnyx.com/docs/network/tunnel/features/private-services.md) Preview or a [public hostname](https://developers.telnyx.com/docs/network/tunnel/features/public-hostnames.md) Preview. The examples on this page run on the [Quick Start](https://developers.telnyx.com/docs/network/tunnel/quick-start.md) setup.

## From the User's Network

### A Process on One Host

The tunnel process holds a long-lived TLS connection that it opened to Telnyx. An inbound connection would need a public address, a port forward on the router, and a firewall rule. An outbound connection needs none of them, because networks already let hosts open outbound connections. The router and the firewall stay as they are.

The tunnel host has only private addresses, and its one connection to Telnyx is one it opened:

```bash Tunnel host theme={null}
ip -brief address && ss -tn state established
```

```text Output theme={null}
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0@if55        UP             10.20.0.10/16
eth1@if57        UP             10.30.0.10/24
Recv-Q Send-Q Local Address:Port  Peer Address:Port
0      0         10.20.0.10:46826 64.16.236.14:8443
```

The one established connection is the tunnel's. The router forwards no port to the tunnel host.

### No Root

The tunnel process runs as a normal user. It creates no interface and changes no route, so it needs no administrator rights on the host:

```bash Tunnel host theme={null}
id && telnyx-edge tunnel run --token tnl_…
```

```text Output theme={null}
uid=1000(tunnel) gid=1000(tunnel) groups=1000(tunnel)
INF connected  site=tunnel-relay.telnyx.com:8443  conn=0  tunnel=6afe50f3-bcff-48e9-93e8-4a906a91067e  relay=tunnel-relay.telnyx.com:8443
```

### Streams on That Connection

The process sends its token as soon as it connects, and Telnyx confirms the token on the first stream of the connection. Telnyx then opens one more stream for each flow, and each stream opens with a connect request that names the destination. [Connections](https://developers.telnyx.com/docs/network/tunnel/concepts/connections.md) follows one flow through every step.

### A Client Like Any Other

The process dials each destination as any program on its host would, and copies bytes between the stream and that connection until the flow ends. On the web service, a request that `curl` makes on a tunnel host and requests from the function look the same:

```bash Tunnel host theme={null}
curl -s http://10.20.3.7:8080/from-curl
```

```text 10.20.3.7 access log theme={null}
10.20.0.10 - - "GET /from-curl HTTP/1.1" 200 -
10.20.0.10 - - "GET /from-function HTTP/1.1" 200 -
10.20.0.11 - - "GET /from-function HTTP/1.1" 200 -
```

The first line is the `curl` on `dc1-tunnel-a`. The other two are function requests, which arrived from `dc1-tunnel-a` and `dc1-tunnel-b`.

## From the *Network*

### The Next Hop of a Route

A route that names a tunnel hands each flow in its CIDR to the tunnel process. The route list shows the tunnel as the next hop for `10.20.0.0/16`:

```bash Workstation theme={null}
telnyx-edge network route list acme-prod
```

```text Output theme={null}
ID                                     CIDR            NEXT HOP                                                   ORIGIN       STATUS
------------------------------------   -------------   --------------------------------------------------------   ----------   ------
1a826484-8bfe-4346-b9fc-26aa70a22ccc   10.20.0.0/16    tunnel chicago-dc                                          static       active
03aefa24-609b-4fce-b88a-0dc9afeed95d   172.27.0.0/24   wireguard_interface 03aefa24-609b-4fce-b88a-0dc9afeed95d   attachment   active
```

### Telnyx Terminates the Client's Connection

Telnyx terminates the client's connection itself and opens a stream to the process for it. When the destination refuses, the process reports the refusal and Telnyx resets the client's connection. A request to a closed port shows it:

```ts Function theme={null}
await env.PRIVATE_NET.fetch("http://10.20.3.7:9999/");
```

The fetch rejects with `TypeError: fetch failed`, and its cause is `ECONNRESET`. Run with `-v`, the tunnel process that received the connect request logs the refusal:

```text Tunnel host theme={null}
{"time":"2026-10-26T14:28:17.99189773Z","level":"INFO","msg":"tunnel: dial failed","dest":"10.20.3.7:9999","error":"dial tcp 10.20.3.7:9999: connect: connection refused"}
```

[Connections](https://developers.telnyx.com/docs/network/tunnel/concepts/connections.md) follows one request through every step.
