Start in the pool field on the VPN server, not in a spreadsheet. Whatever you type there becomes the inner address space for every client that connects afterwards, and it has to coexist with the LAN those clients are reaching, the routed sites behind it, and whatever address the client already holds at home. Connect one client as soon as the pool is saved, because that first connection tells you whether the value works in practice. From there the walkthrough moves outward: the address the client received, the path a reply takes, and the record you leave behind.

Start at the pool field, before any client connects

Each product exposes this differently, so find the object that actually assigns addresses. OpenVPN has a server-side pool directive that hands out the next free address, an IKEv2 gateway has a pool section bound to the peer configuration, and WireGuard has neither because each peer carries its own address in its configuration file. A pool directive and a per-peer address are not interchangeable, and editing the wrong one wastes the rest of the walkthrough.

Once you have the field, list the ranges that already exist: the office LAN, every routed site, the cloud VPC, and any other pool still in service. Overlap is decided by prefix arithmetic, not by whether the host numbers look familiar, so compare the aggregate against each of those ranges. Two ranges that both look like 10.x are harmless when their aggregates do not intersect and a support incident when they do.

Then decide whether the address is a function of who connects or of when they connect. Dynamic assignment hands out whatever is free, while per-identity assignment binds a fixed address to a credential. Write the choice down, because it changes what a reconnect should look like later.

Read the address the client actually received

Connect one client and read what the tunnel reports, not what the pool promised. The client shows its inner address in the connection status, and on Linux the interface carries it directly.

Compare that address with the range you saved. If it sits outside the range, you are looking at a different assignment path than the one you edited. Check the prefix length as well, since a client holding a /32 has no on-link peer and sends every destination through its default route.

ip -4 addr show tun0
ip route get 192.168.50.20

A client that connects from a home router using the same range will connect and then reach almost nothing. The client keeps its local route for that prefix, so the tunnel address collides with the network behind it and traffic leaves by the wrong interface. That case cannot be repaired on the server; the documented remedy is renumbering the home network or choosing a pool range remote enough that collisions stay rare. Record both the failure and the remedy, because the help desk will meet it again.

Reconnect the same client and watch the address. A dynamic pool may return the same value or a different one and either is correct, while a per-identity pool that changes the address is not honouring the binding. That check takes seconds and settles whether the mode you recorded in the first section is the mode in force.

Follow a reply back from the service

The pool only works when replies can travel back to it. A service on the LAN answers the inner address, so its gateway needs a route for the pool or a translation in front of the service. When a request arrives through the tunnel and the reply leaves by a different path, a stateful firewall or a reverse-path check drops it, and the client sees a service that connects and then hangs. Put the pool into the routing design as one summarisable block instead of adding per-host routes.

Translation changes what the rest of the system sees. When the source is rewritten, the address in the host firewall and in the application log is the translated one, so a rule written against the pool address matches nothing and a log line cannot be traced back to a client. The strongSwan forwarding documentation covers the server-side half of that path for an IKEv2 gateway. DNS carries the same constraint, because a name that resolves to an address the client cannot reach fails later and somewhere else.

Two clients, then one revocation

Connect two clients at the same time and read both addresses. They must be distinct, usable, and inside the pool, and each must reach the service it is meant to reach. A pool that hands out duplicate addresses usually shows up here rather than in the first single-client test.

Revoke one credential while the other client stays connected, then try the service from the surviving client. A revocation that disturbs the other session points at shared state, most often one credential or one address reused across devices. Reconnect the revoked client and confirm it is refused rather than handed the freed address.

Finish with a destination that should be denied. A client that reaches everything has been connected, not tested.

Write the four values where the next change will find them

The record is short: the pool range and prefix, the assignment mode, the return path or translation in use, and the DNS scope that answers for those destinations. Put it next to the server configuration rather than in a ticket, and date it. Anyone who changes one of the four later needs the other three in front of them, because a pool resize breaks the route and a route change breaks the DNS answer.

Keep the ownership note with it: the tunnel range belongs to the VPN server, and a reservation made in the LAN DHCP scope reserves nothing for a client inside the tunnel. That single line prevents the most common rework, where someone adds a reservation and expects the tunnel address to follow it.

Nuŋlɔɖi siwo ku ɖe eŋu