Port lists for VPN services get copied between comparison pages without the detail that decides whether they matter: who starts the connection. A rule that permits outbound TCP 443 says nothing about whether another host can reach a listener on your machine. Write three separate requirements before you compare a single plan, and mark which ones your task actually needs. Most comparisons collapse into one short question once that sheet exists.

Split the requirement before you read any port list

Three lines cover almost every case: reaching a destination beyond the tunnel, publishing something so others can connect in, and carrying the tunnel itself. Each line fails for a different reason, and a provider policy that satisfies one can leave the other two untouched. Sorting your task into the right line takes five minutes and saves an argument later.

LineWho starts itWhat can block itQuestion for the provider
Outbound destinationYour applicationEgress filter on the exit nodeIs this protocol and port allowed to that destination?
Inbound publishingA remote peerNo mapping, no public address, short lifetimeWhich protocol, which external port, and how long does the mapping last?
Tunnel transportYour client to the gatewayThe access network drops that protocolDoes the client offer a fallback the local network permits?

Marketing statements blur the three lines on purpose. A P2P allowance describes a destination policy, a dedicated address describes an address, and a claim of no port restrictions usually means the plan does not enumerate them. None of those phrases answers the others.

Pick one concrete flow and write it as a sentence: initiator, transport, port, address family, direction. A nightly backup client uploading to a remote host is outbound only. A game server on your desk that friends join is inbound. Running both through one tunnel means the sheet needs both lines, not a compromise between them.

Outbound access fails on destination policy, not on the tunnel

Outbound traffic through a translating gateway creates state. The first packet from an internal address and port builds a translation entry, and replies match it, which is the mapping behaviour described in RFC 3022. That mechanism is why a browser tab usually works without any port request at all.

Two things still break it. The exit node may filter destinations or port numbers it considers abusable, and the application may be listening on a port that the exit policy never expected. Ask about the destination pair rather than about inbound rules, and expect different answers for TCP and UDP.

Measure before you argue. Run these on the machine that will sit behind the tunnel, once with the tunnel down and once with it up:

ss -lntup | sort
nc -vz -w 3 203.0.113.10 443
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://example.com

Same commands, same destination, two tunnel states, gives an operator a before-and-after they can act on. Replace the documentation address with the host you actually need; what matters is that the comparison repeats, not that any number looks impressive.

Inbound publishing needs a mapping, an address and a lifetime

Nothing outside can start a connection to your listener unless something on the public side knows where to deliver it. A static port reservation held by the operator, a client-requested mapping through UPnP, NAT-PMP or PCP, and a routed public address are three different products with three different limits.

Ask five questions of any of them: which protocol, which external port, whether the external port may differ from the local one, which address family it covers, and how long the mapping survives a reconnect. A reservation tied to an active session disappears when that session ends, whatever the plan page says.

Confirm the local half first, because a dead listener and a blocked inbound path look identical from outside:

ss -lntup | grep -E ':(8080|51820)\b'
python3 -m http.server 8080 --bind 0.0.0.0
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080

When the local request returns 200 and a request from a network you do not control still times out, the gap sits on the public side. That is the moment to quote protocol and external port to the operator instead of describing the app by name.

The tunnel's own transport is a separate question

Carrier ports are the smallest part of the problem and the easiest to look up. Defaults differ by protocol, and what the client can negotiate matters more than any plan description.

ClientOuter transportDefault portWhen it helps
OpenVPNUDP1194Default mode; needs outbound UDP to pass
OpenVPNTCP443UDP is dropped and TCP 443 is not
WireGuardUDP51820Short handshake; there is no TCP mode
IKEv2/IPsecUDP500 and 4500Mobile clients; 4500 carries NAT traversal

A network that drops outbound UDP will accept a TCP 443 tunnel and refuse a UDP one, so a fallback mode belongs on the requirement sheet. Changing the carrier does not move an application port inside the tunnel, and it does not widen a destination policy; those stay on their own lines.

Fragmentation deserves one probe while you are there, because a tunnel that connects and then stalls on large transfers usually has the wrong MTU rather than a closed port:

ping -M do -s 1400 203.0.113.10
ping -M do -s 1372 203.0.113.10

On Windows the same probe is ping -f -l 1400 203.0.113.10. Set the tunnel MTU below the largest size that passes, then retest the transfer that failed.

Verify the three lines before you pay for a plan

Put the three lines on one page and fill each cell with a measured result instead of a promise. These commands produce the local half of that page in about a minute:

ss -lntup | sort
nc -vz -w 3 203.0.113.10 443
python3 -m http.server 8080 --bind 0.0.0.0
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080
ping -M do -s 1400 203.0.113.10

Read the output as a checklist. Outbound works when the destination answers with the tunnel up. Inbound works only when a host outside your network reaches the listener on the external port. The carrier works when the handshake completes on a protocol your access network permits.

Two habits keep the sheet honest. Record the date and the client version beside each result, since provider policies and client defaults both move. Then ask for the narrowest mapping that serves the flow, because a request to open everything tends to earn a refusal or an upsell rather than a technical answer.

Erthyglow kevrennek