A VPN migration is finished when the users, destinations, name resolution and failure behaviour are all still correct, not when the new client shows a green icon. Old PPP-based deployments carry assumptions that were never written down: a shared secret that doubled as the only identity check, a fixed address pool the firewall allowlists, a DNS suffix pushed by the server. Replacing the protocol without inventorying those assumptions produces a tunnel that handshakes and a boundary that does not exist. The walkthrough below is the order I use, and the last step is the one teams skip.

Step 1: inventory what the old connection provides

The inventory is written rather than remembered. Record the supported clients, the authentication roles, the address pools, the protected networks, the DNS requirements and the service permissions each user population needs.

For L2TP/IPsec, separate the two layers explicitly. The IPsec peer identity authenticates the machines; PPP authenticates the user, usually with CHAP or MSCHAPv2.

That separation is where old deployments hide their assumptions. A pre-shared key shared by every client authenticates a group rather than a device, and it is often the only thing that was ever rotated. If the PPP account is the real per-user control, say so, because the replacement has to reproduce that control with something that is not a shared string. Note fixed source addresses and local-network exceptions as well, since those are the dependencies nobody documents until they break.

Step 2: design the replacement deliberately

Choosing the replacement is a requirement-by-requirement mapping: a protocol and a maintained client the organisation supports, with each identity and access requirement landing in an actual mechanism. A shared secret is not automatically equivalent to a per-device key or certificate, and a per-user PPP account is not equivalent to a device certificate.

Coordinate address ranges before anything else, because a replacement pool that overlaps a home or office LAN creates a failure that has nothing to do with cipher strength. Check the pool against the same list you built for the old service, plus whatever the new client assumes by default. Confirm the return routing for the protected networks, and confirm that the new client can push or document the DNS suffix the old one pushed. Those two items cause more migration tickets than the protocol change itself.

Step 3: stage it and verify both allow and deny

Stage with one representative user and one representative application. Include private DNS resolution in the test, because a tunnel that reaches an address but cannot resolve an internal name is only half migrated. Include the expected unavailable state as well: what should happen when the tunnel drops, and whether the client enforces it.

Then test a destination that should remain denied. A broad temporary allow rule can make the new tunnel look healthy while quietly removing the authorization boundary the old service enforced, and nobody notices until an audit. Compare allow and deny results side by side, from the same client, in the same session. Keep the old service running until both columns match the design.

Before you move administrator access, confirm you have an authorised recovery path that does not depend on the tunnel you are changing.

Step 4: retire the old identity

Retiring the old identity properly means revoking obsolete users and device credentials through the service that owns them, then removing old profiles and listeners once no dependency remains. Deleting a local file does not revoke a copy somewhere else, and an old listener that still accepts the old shared secret is an unmonitored door.

That point is worth slowing down for. A decommissioned client profile on a laptop is not a revoked credential; the credential lives on the server and stays valid until the server stops accepting it. Check for other copies of the old configuration — test devices, a forgotten phone, an installer someone kept — and treat the listener shutdown as the moment the old service actually ends. Until then, the migration has two front doors.

The acceptance record is the inventory from step one with a column added: what the new design does for each row, and how you verified it. That turns a protocol upgrade into a service requirement with evidence.

Keep the outcome tied to what the service needs rather than to the protocol name, because a modern protocol with the old assumptions copied into it is the same risk with better framing. RFC 3193 describes how L2TP is carried over IPsec, which is a useful reminder that the two layers were always separate decisions. If the inventory has a row you cannot explain, stop and find out what depends on it. The migration is done when the list is boring.

Sɛbɛn minnu bɛ tali kɛ