One SSH session, one web app and one name lookup can share a single VPN connection without fighting over ports. The client builds one encrypted flow to the gateway, and every application conversation travels inside it. Outside, only the tunnel's own transport and port are visible. Inside, each service keeps its own port and still needs its own permission.

What the outer flow carries, and what it hides

The client wraps every packet in the tunnel's transport before it leaves the machine. That outer flow has one destination port, fixed when the VPN was configured. Inside the wrapper, each original packet keeps the address and port of the service it targets. The gateway strips the wrapper and routes on the inner header, so the destination sees an ordinary client arriving from the network.

A capture on the WAN interface therefore shows one conversation, not three. The inner ports only appear after decapsulation. That is why a single firewall opening can carry SSH, HTTPS and DNS at the same time.

# WAN side: one outer tuple, whatever the inner services are
tcpdump -ni wan0 'udp port 443'
# tunnel side: the inner tuples appear after decapsulation
tcpdump -ni tun0

The TUN/TAP documentation covers the handoff where a routed TUN device passes IP packets between the kernel and a userspace process. That handoff is what makes the inner header visible to the gateway's routing and firewall code. It also explains why the outer port says nothing about which services are permitted.

The NAT forward belongs to the listener, not the applications

A self-hosted gateway behind IPv4 NAT needs one inbound translation: the public address and port mapped to the VPN listener. No rule is required for SSH, HTTPS or DNS just because tunnel users reach them. Publishing those ports would expose services the tunnel already protects. The forwarding rule describes reachability of the listener, not a permission for anything inside.

The converse holds as well. Opening the tunnel port exposes nothing else, so a service reachable only through the tunnel keeps its public surface closed. That separation is usually the reason to keep the service private in the first place.

Inner policy is where access is actually decided

Encryption protects the path; it does not authorize a destination. Client routes choose which prefixes enter the tunnel, gateway forwarding policy decides whether packets may leave it, and the destination's firewall plus login decide whether the service answers. DNS is the clearest case: carrying queries does not make a resolver accept them from your client pool. Each layer can say no independently.

Test each service on its own through the tunnel. A successful lookup says nothing about the web port, and a successful web request says nothing about SSH.

dig @10.40.0.53 app.corp.example
nc -vz 10.40.0.10 8443
ssh -p 2222 [email protected]

When the tunnel is up and everything fails, read the client's route table first. When one service fails while the others work, the fault sits at that destination. Those two observations point at different owners, and mixing them wastes time.

WireGuard draws the same line

WireGuard names its outer listener with ListenPort, and an inner application still uses whatever service port it needs. AllowedIPs is a set of routed prefixes, not a list of permitted service ports. Reading it as a port allowlist produces rules that do not match what the tunnel does. The naming is different; the layering is not.

Permit the service in local-input policy when it runs on the endpoint itself, or in forwarding policy when it sits behind that endpoint. The distinction decides which rule set sees the packet.

The general shape is one outer transport with many inner conversations. Products that need several outer exchanges, or a different IP protocol, are a reminder that the single-public-port pattern describes this design and not every VPN.

Akụkọ ndị metụtara ya