> ## 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 Not

> A tunnel is not an interface, a link, or a route, seen from either side. Each point below shows it on the Quick Start setup.

A tunnel carries flows from a [*Network*](https://developers.telnyx.com/docs/network/overview.md) to hosts behind it. It never joins the two networks. A VPN joins two networks, so that hosts on each side can send packets to the other, subject to firewalls. A tunnel carries only the flows that Telnyx hands it, and only to the destinations declared for it:

* From the *Network*, to the CIDRs that routes send to the tunnel, and to its [private services](https://developers.telnyx.com/docs/network/tunnel/features/private-services.md) Preview.
* From the internet, to its [public hostnames](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

### Not an Interface, a Link, or a Route

Starting the tunnel process adds no interface and no route to the tunnel host. The host's interfaces and routing table read the same before and after `telnyx-edge tunnel run`:

```bash Tunnel host theme={null}
ip -brief address && ip route
```

```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
default via 10.20.0.1 dev eth0
10.20.0.0/16 dev eth0 proto kernel scope link src 10.20.0.10
10.30.0.0/24 dev eth1 proto kernel scope link src 10.30.0.10
```

### No Route Back to Telnyx

Hosts behind the tunnel need no route to Telnyx either. Every connection reaches them from the tunnel host, so their replies stay within the user's network. The web service's routing table holds only its own subnet and the site's default route:

```bash 10.20.3.7 theme={null}
ip route
```

```text Output theme={null}
default via 10.20.0.1 dev eth0
10.20.0.0/16 dev eth0 proto kernel scope link src 10.20.3.7
```

A request from the function at the same moment returned `200`, through the tunnel host `10.20.0.11`.

### No Listening Port

The tunnel opens no port within the user's network, so there is nothing to scan or attack, from the internet or from the site's other hosts. A scan of `dc1-tunnel-a` from `dc1-tunnel-b`, while both run the tunnel process, finds every port closed:

```bash Another host theme={null}
nmap -n -p- 10.20.0.10
```

```text Output theme={null}
...
Nmap scan report for 10.20.0.10
Host is up (0.0000010s latency).
All 65535 scanned ports on 10.20.0.10 are in ignored states.
Not shown: 65535 closed tcp ports (reset)
...
```

### No Way Into Telnyx

No host within the user's network, the tunnel host included, can open a connection through the tunnel toward the *Network*. A WireGuard peer is a host on the *Network*. It sends packets for the function's address, `172.27.0.2`, into its WireGuard interface:

```bash WireGuard peer theme={null}
ip route get 172.27.0.2
```

```text Output theme={null}
172.27.0.2 dev wg0 src 172.27.0.4 uid 0
    cache
```

A tunnel host is not on the *Network*. It sends packets for the same address to the site's default gateway, where they lead nowhere:

```bash Tunnel host theme={null}
ip route get 172.27.0.2
```

```text Output theme={null}
172.27.0.2 via 10.20.0.1 dev eth0 src 10.20.0.10 uid 0
    cache
```

Both answers were taken while the function reached `10.20.3.7` through the tunnel.

### No Address of Its Own

The tunnel has no IP address. Only the tunnel host has one. On the *Network*, the route names the tunnel as its next hop, where an attachment's route names the attachment:

```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
```

## From the *Network*

### No IP Packets

The tunnel process re-originates each TCP connection. No packet from the *Network* crosses the tunnel, so routing protocols, other IP protocols, and multicast never reach the hosts behind it. A capture on the web service during two function requests shows two connections from the tunnel hosts, and no packet from the *Network*'s subnet:

```bash 10.20.3.7 theme={null}
tcpdump -n -i eth0 'tcp port 8080 or net 172.27.0.0/24'
```

```text Output theme={null}
14:27:07.448515 IP 10.20.0.10.35280 > 10.20.3.7.8080: Flags [S], seq 3418263517, win 64240, options [mss 1460,sackOK,TS val 1627743448 ecr 0,nop,wscale 7], length 0
...
14:27:08.255506 IP 10.20.0.11.39900 > 10.20.3.7.8080: Flags [S], seq 838061873, win 64240, options [mss 1460,sackOK,TS val 3644785740 ecr 0,nop,wscale 7], length 0
...
26 packets captured
```

Each `[S]` line opens a connection from a tunnel host. None of the 26 packets comes from `172.27.0.0/24`.

### Not the Client's Address

The destination sees the tunnel host, never the client's address on the *Network*. The function is `172.27.0.2` on `acme-prod`, and the web service logs its request from the tunnel host `10.20.0.10`:

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

A firewall rule that admits the tunnel host therefore admits every flow through the tunnel.

### Nothing That Is Not Declared

Telnyx asks the tunnel process to dial only the destinations declared for the tunnel. The tunnel host reaches `10.30.0.7:8080`:

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

```json Output theme={null}
{"service": "site-other", "address": "10.30.0.7:8080", "client": "10.30.0.10", "path": "/"}
```

No route sends `10.30.0.0/24` to the tunnel, so the function cannot reach it:

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

The fetch rejects with `TypeError: fetch failed` once its connect timeout passes. Telnyx never sends it to the tunnel, so neither tunnel process receives it.
