Someone asks for a service that only VPN users can reach, and the obvious implementation is to allow a list of exit addresses. The list does something real: it restricts who can connect. It does not establish that a tunnel was used, because the address belongs to whoever operates the egress and that operator can forward anyone's traffic. The gap between those statements is the whole design problem.

The server sees one address per connection

A connection arrives with a source address and a destination port, and that is the extent of what the network layer reports. When a client uses a tunnel, the packets reaching your listener come from the exit or from the translation in front of it. The client's own address, usually private, never appears. A firewall rule written for the client's LAN range therefore does nothing at all.

Everything after that source address is application data, and the application can trust it only as far as it authenticates it.

Test what your egress looks like

Look at the path from both ends before writing a rule. The client's view of its egress and the server's view of the connection are the two facts that matter.

curl -sS https://api.ipify.org; echo
ss -tn state established '( sport = :443 )' | head

The first command reports the public address the client appears as, which is the value any allowlist must contain. The second shows established connections on the server with their peer addresses, which is what the rule will actually match. If the two disagree with your mental model, fix the model before editing the policy. A cloud database firewall, an application allowlist and a load balancer can each see a different translation layer.

Only one of the two exit sets can be listed

One case is checkable at the moment of the request and the other is not, which produces very different guarantees.

curl -sS https://check.torproject.org/torbulkexitlist | wc -l

The published Tor exit list can be fetched and compared, subject to list age and each exit's own policy, so a refusal rule against known exits is enforceable and reviewable. There is no equivalent registry for commercial VPNs. Addresses rotate, many providers publish nothing, and a tunnel can run on a rented cloud address that never belonged to a VPN. A list you compile is a snapshot of observed addresses, and widening it to hosting ranges adds unrelated workloads without adding proof.

Use addresses as policy input, not as proof

Decide what the rule is for. A network restriction should stay narrow, record the observed address with its date and reason, and give legitimate users a recovery path when their egress changes. Access control needs an authenticated account or a signed token, because only those bind a request to an identity. Risk scoring can use the address as a single unreliable signal, accepting its false positives and its blind spots. Writing the rule as a product decision is honest; writing it as verification that a tunnel exists is not.

The mirror-image request, recovering the user's real address behind a VPN, fails for the same reason: one connection carries one address, and a change between sessions is consistent with several explanations. Treat the earlier value as history, not as truth.

Pennadoù liammet