On a headless box there is no browser to open and no padlock to look at, so the check has to be a request whose answer you can read. That sounds trivial until you notice a single exit-address result being used to certify a device that runs a dozen services, two address families and a proxy. The walkthrough below builds one bounded piece of evidence at a time, in the same context the workload actually runs in.

Decide what the test must prove

Before running anything, write the expectation in one line: which flow, through which interface, to which destination, and what should be observed at the far end. A test without a stated expectation produces a number nobody can interpret.

The most useful version names an approved endpoint that reports the source address it saw.

That endpoint is the only part you have to arrange. Everything else is a client-side observation, and client-side observations go wrong in interesting ways.

Run the observation in the right context

An administrator's shell is not the workload's environment. It can carry a different proxy variable, a different routing table in another namespace, or a different user's environment file. Run the test in the same host, container, namespace or service context as the thing you are checking. Otherwise you are measuring your shell.

On a normal host that means the same user and the same unit. In a container estate it means entering the container's network namespace rather than testing from the host. On a systemd service it can mean a transient unit with the same settings.

The request that follows is only meaningful once you are in the right context.

Check address families separately

Ask for each family explicitly, because a successful IPv4 request does not exercise an IPv6 path at all. The --ipv4 and --ipv6 selectors force the choice, and the difference between the two results is itself information.

curl --ipv4 https://probe.example/observed-source
curl --ipv6 https://probe.example/observed-source

A failed IPv6 request is not proof of an effective block. It can mean the endpoint has no IPv6 address, that DNS returned nothing usable, or that the device has no IPv6 route at all. Read the failure before drawing a conclusion from it. A successful IPv6 request through the tunnel is the only result that proves the IPv6 path is covered.

Record both answers side by side. One of them alone is half a fact.

Add the four things an exit check misses

An exit address answers one question. Four more decide whether the tunnel behaves as designed.

CheckWhat it provesWhat it does not
Included and excluded destinationsThe split behaves as designed for those flowsCoverage of any other destination
Resolver pathWhere a fresh lookup actually travelledWhere a cached answer came from
Tunnel-down behaviourThe failure policy for a new requestWhat an already open connection does
Reconnect and restartThe requirement survives the lifecycle eventBehaviour under load or partial failure

Destination policy comes first: test a flow that should be included and one that should be excluded, when the design has a split. Then DNS, where you inspect the actual resolver path rather than the configured value, because a cached answer or a printed setting says nothing about where a new lookup went.

Failure behaviour needs a plan and a preserved recovery path. Observe a new request while the tunnel is unavailable, and remember that an old open connection is not evidence about the failure policy. Lifecycle comes last: repeat the observation after a reconnect or a service restart if those events affect the requirement.

Record evidence, not a verdict

For each result keep the process context, the destination, the address family, the time and the observed source. That set is bounded evidence about the flows you exercised, and it is defensible precisely because it says what it covered.

It is not an audit of the VPN operator's records, and not a certificate for every future application on the device.

Write the limits next to the result. A test that states what it did not cover survives review, while one claiming the device is verified does not. Keep the curl manual next to the family selectors you used, and keep the four-row table with the results.

Sɛbɛn minnu bɛ tali kɛ