VPN Encrypted Tunnels
Lessons (11, study in order)
Lesson 1 - What problem does a VPN actually solve
Beginner · about 8 min
Goal: First work out what guarantees are needed to "send private data over an untrusted public network" -- IPsec's structure follows directly from this.
An untrusted public network causes four kinds of trouble
Two sites need to communicate, and the public internet sits in between. With no protection at all, four things can happen:
- Seen -> need confidentiality (encryption)
- Tampered with -> need integrity (a check value)
- Impersonated -> need authentication
- Recorded and replayed -> need anti-replay (sequence numbers)
Every part of IPsec maps to one of these -- remember these four, and you won't need to memorize the ESP packet structure later.
Private addresses have a further, practical problem
Both sites' internal networks use private addresses like 192.168.x.x, which aren't routable on the public internet -- ISPs drop them outright.
So beyond encryption, there's also "how do private addresses communicate across the public internet" to solve -- the answer is a tunnel: wrap the original packet whole inside a new packet addressed with public addresses.
This is the reason IPsec's tunnel mode exists.
Hands-on: watch a normal tunnel
Load the "Simplest site-to-site" scenario, go to the (2) Tunnel Config page to see both ends' policies, then go to the (3) Negotiation page and hit play to watch IKEv2's four packets bring the tunnel up.
Key takeaways
- An untrusted public network -> needs confidentiality/integrity/authentication/anti-replay
- Private addresses across the public internet -> needs tunnel encapsulation
- Every part of IPsec maps to one of these requirements
Lesson 2 - ESP / AH and the two encapsulation modes
Beginner · about 12 min
Goal: Four terms, explainable in two sentences -- but pick wrong and it won't connect.
ESP and AH: production only uses ESP
- ESP (protocol 50): both encrypts and authenticates.
- AH (protocol 51): authenticates only, no encryption, and it includes the entire IP header in its integrity check.
AH has a fatal problem: it always breaks across NAT. Because NAT's whole job is modifying the IP header, and once modified the check value no longer matches. And NAT is nearly everywhere in production.
The conclusion is simple: use ESP, not AH. Exams ask about AH; the job never uses it.
Tunnel mode vs. transport mode
- Tunnel mode: adds a new outer IP header (source/destination = the two gateways' public addresses), and the original IP packet is encrypted whole as the payload.
- Transport mode: adds no new IP header -- it just inserts an ESP header after the original IP header.
How to choose? Look at what's being protected:
- Protecting communication between two networks (site-to-site) -> must use tunnel mode. The original packet's addresses are private, and without a new outer header it can't reach the public internet.
- Protecting two hosts talking to each other directly (e.g. two servers with a direct encrypted link) -> transport mode works.
Configuring transport mode for site-to-site is a classic mistake -- the symptom is the tunnel negotiates fine but business traffic doesn't flow.
Hands-on: see the packet before and after encapsulation
Go to the (4) Packet & MTU page and send a packet, comparing the structure side by side before and after encapsulation: in tunnel mode you'll see "new IP header + ESP header + the encrypted original packet + ICV."
Then switch to transport mode and see what the hint says.
Key takeaways
- ESP both encrypts and authenticates; AH only authenticates and can't traverse NAT, so it's unused in production
- Site-to-site must use tunnel mode (a new outer IP header is required)
- Transport mode is only suitable for host-to-host
Lesson 3 - What IKE's two phases actually do
Advanced · about 15 min
Goal: Understand the division of labor between the two phases, and troubleshooting gets a map.
Why split into two phases
The encryption key for business traffic must be negotiated securely. But the negotiation itself also runs over the public internet -- if the key were negotiated in cleartext, a man-in-the-middle could hear the entire exchange, and the encryption would be pointless.
So IKE splits into two steps:
- Phase 1: first build a secure channel that protects the negotiation itself (the IKE SA). Derives a shared secret via DH, and mutually authenticates identity via PSK or certificates.
- Phase 2: under phase 1's protection, negotiates the SA that actually encrypts business traffic (the IPsec SA), and determines which traffic to encrypt.
Phase 1 doesn't encrypt business traffic -- it only protects the negotiation packets. This is the easiest point to confuse.
The elegance of DH
Phase 1 exchanges keys using Diffie-Hellman. Its magic:
Each side computes the same shared secret using "its own private key + the peer's public key", and this shared secret is never transmitted over the wire.
A man-in-the-middle who captures every packet still can't compute it.
The DH group (group2/5/14/19) determines the strength of this computation. group2 is 1024-bit and is already considered insecure (the Logjam attack) -- group14 (2048-bit) is the minimum for production.
Why IKEv2 only needs 4 packets
- IKEv1 main mode: phase 1 needs 6 packets (2 for algorithm negotiation + 2 for DH + 2 for authentication), and phase 2's quick mode needs another 3 packets.
- IKEv1 aggressive mode: phase 1 compresses to 3 packets, but identity is in cleartext. The benefit is it's the only option when the peer's address isn't fixed.
- IKEv2: done in 4 packets -- 2 for IKE_SA_INIT (algorithms + DH), 2 for IKE_AUTH (authentication + conveniently building the first Child SA at the same time).
New tunnels should always use IKEv2: fewer packets, supports EAP, better NAT traversal, simpler configuration.
Hands-on: watch it packet by packet
Go to the (3) Negotiation page and hit play. First watch IKEv2's 4 packets, then load the "IKEv1 main mode" scenario to compare the 6+3 packets -- note that main mode's 5th and 6th packets are encrypted, so identity information is protected.
Key takeaways
- Phase 1 builds the IKE SA, only protecting the negotiation itself; phase 2 builds the IPsec SA, encrypting business traffic
- DH's shared secret is never transmitted over the wire
- IKEv1 main mode is 6+3 packets, aggressive mode is 3+3; IKEv2 only needs 4
- Use group14 as the minimum DH group
Lesson 4 - Interesting traffic: must be strictly mirrored
Troubleshooting · about 14 min
Goal: One of IPsec's number one failures, with a very recognizable signature.
Interesting traffic decides "what gets encrypted"
Configuring IPsec doesn't mean all traffic gets encrypted. Only traffic matching the interesting-traffic ACL enters the tunnel; everything else follows ordinary routing.
So there are two typical mistakes:
- Written too narrow -> some traffic doesn't connect (a subnet was missed)
- Written too broad -> even browsing traffic gets stuffed into the tunnel, overloading the gateway
Must be strictly mirrored, not containment
Each end configures its own policy, and the interesting traffic must be mutually mirrored:
- End A: local 192.168.1.0/24 -> peer 192.168.2.0/24
- End B: local 192.168.2.0/24 -> peer 192.168.1.0/24
Note: a broader range doesn't work either. Many people assume "if I write 192.168.0.0/16 on my side it covers the peer's 192.168.2.0/24, that should be fine", but IKE compares whether the traffic selectors are exactly identical, not a containment relationship.
This failure has a very recognizable signature: phase 1 succeeds, phase 2 fails. The real-hardware log usually shows no proposal chosen or invalid ID information.
Hands-on: create and fix it
Load the "Negotiation troubleshooting" scenario, which has two pitfalls planted (mismatched key + unmirrored interesting traffic).
Go to the (3) Negotiation page to see where it's stuck, then go back to the (2) Tunnel Config page and fix it, then come back and verify.
Key takeaway: stuck at the end of phase 1 = key issue, stuck in phase 2 = interesting-traffic issue.
Key takeaways
- Only traffic matching interesting traffic gets encrypted
- Both ends' interesting traffic must be strictly mirrored -- containment doesn't count as a match
- Phase 1 succeeds but phase 2 fails -> check interesting traffic first
Lesson 5 - MTU: ping works but pages won't load
Troubleshooting · about 12 min
Goal: The problem that's easiest to overlook, and easiest to misdiagnose as "the network is slow."
IPsec always makes packets bigger
In tunnel mode, a packet has to carry extra baggage:
- New outer IP header: 20 bytes
- ESP header (SPI + sequence number): 8 bytes
- IV: 16 bytes
- Padding + ESP trailer: ~10 bytes
- ICV (integrity check value): 12-16 bytes
- With NAT-T enabled, add a UDP header: 8 bytes
Total: 60-80 bytes. A packet that was exactly 1500 bytes now exceeds the MTU once encapsulated.
What happens when it exceeds the MTU
Exceeding the outbound interface MTU triggers fragmentation. Fragmentation itself degrades performance, but the real killer is:
many networks filter out ICMP "fragmentation needed" messages, creating a PMTUD black hole -- the sender never receives the "your packet is too big" notification, so it keeps sending large packets, which keep getting dropped.
The symptoms are very distinctive:
- ping works (ICMP packets are small)
- SSH connects, but ls on a large directory hangs
- pages load halfway, large file transfers stall
Many people misdiagnose this as "the network is slow" or "an ISP problem", when it's actually MTU.
The standard fix: lower the TCP MSS
Configure tcp adjust-mss on the tunnel interface (Cisco: ip tcp adjust-mss).
The principle: when the gateway forwards the SYN packet of a TCP handshake, it lowers the MSS value inside it, so both ends' TCP negotiate smaller segments from the very start, avoiding large packets at the source.
This is "a must-do when building a new IPsec tunnel" -- many trouble tickets are missing exactly this one command.
Key takeaways
- IPsec encapsulation overhead is roughly 60-80 bytes, largest with tunnel mode + NAT-T
- Ping works but large packets don't = an MTU/fragmentation problem
- ICMP being filtered causes a PMTUD black hole
- The standard fix is configuring tcp adjust-mss on the tunnel interface
Lesson 6 - NAT traversal and a troubleshooting routine
Troubleshooting · about 12 min
Goal: Branches behind NAT are the norm, plus a troubleshooting sequence you can copy directly.
ESP has no port number, so it can't traverse NAT
NAT relies on port numbers to distinguish multiple sessions on an internal network. But ESP is IP protocol 50, and has no port field at all -- a NAT device has nothing to work with.
How NAT traversal (NAT-T) solves this: wrap the ESP packet in an additional UDP 4500 layer, giving it a port that can be mapped.
So whenever there's NAT on the path, you must:
- Enable NAT traversal on both ends
- Have the firewall allow UDP 500 (IKE negotiation) and UDP 4500 (NAT-T data)
Two knock-on effects of NAT scenarios
(1) AH is completely unusable. It includes the entire IP header in its check, and NAT modifying the address always breaks it.
(2) The peer address must be the post-NAT address. The branch gateway's own interface has a private address, but headquarters sees the post-NAT public address -- headquarters must configure the latter.
(3) When the branch's address isn't fixed, headquarters can only use aggressive mode (IKEv1) or a policy template approach -- it can't hard-code the peer address.
Troubleshooting order (follow this, don't skip steps)
(1) Is the tunnel up? display ike sa / display ipsec sa
If not -> see where it's stuck:
- Stuck in phase 1's early packets -> algorithm proposal mismatch
- Stuck at the end of phase 1 -> mismatched pre-shared key or a misconfigured peer address
- Stuck in phase 2 -> interesting traffic not mirrored / encapsulation mode mismatch / PFS mismatch
(2) Is traffic entering the tunnel? Check whether the interesting-traffic ACL's match counter is increasing, and whether display ipsec statistics's encrypt/decrypt counters are increasing
(3) Small packets work, large ones don't -> MTU / MSS, go configure tcp adjust-mss
(4) One direction fails -> the two ends' interesting traffic isn't mirrored, or a return route is missing
(5) Drops periodically -> parameters mismatch when the SA renegotiates at its lifetime expiry, or DPD isn't enabled
Key takeaways
- ESP has no port number, so traversing NAT requires NAT-T (wrapping in UDP 4500)
- Whenever there's NAT, allow UDP 500 and 4500, and don't use AH
- When the peer is behind NAT, configure its post-NAT address
- Troubleshooting order: tunnel state -> is traffic entering the tunnel -> MTU -> directionality -> stability
Lesson 1 - The fundamental difference from site-to-site
Beginner · about 10 min
Goal: In one line: the client's address isn't fixed, so the entire mechanism has to change.
Just one difference, but it drives the whole mechanism
In site-to-site, both ends are fixed gateways: the peer address is fixed and the subnet being protected is fixed. So "peer address + interesting-traffic ACL" fully describes it.
In client-to-site, the client's address isn't fixed -- at home today, at a hotel tomorrow, on cellular the day after. So:
- Can't authenticate a "site" -> switch to authenticating the person (username/password, certificate, two-factor)
- Can't hard-code interesting traffic -> switch to assigning the client an internal address (address pool), then pushing routes to it, letting the client itself decide which traffic enters the tunnel
Remember this thread -- the four-step access process that follows is just its expansion.
The four access steps
(1) Establish connection -- the client connects to some port on the gateway
(2) Authenticate -- verify who this person is
(3) Assign an address -- give it a virtual NIC address from the pool
(4) Push routes and DNS -- tell the client which traffic goes through the tunnel
Each step has its own typical failures, which lesson 4 walks through one by one.
Key takeaways
- The one fundamental difference: the client's address isn't fixed
- So it switches to authenticating the person + assigning an address + pushing routes
- Four access steps: connect -> authenticate -> assign address -> push routes
Lesson 2 - How to choose among the four access methods
Beginner · about 12 min
Goal: The key to choosing is really "how well it traverses firewalls."
SSL VPN: runs over 443, best at getting through firewalls
Runs over TCP/UDP 443, looking just like ordinary HTTPS.
This is its biggest advantage: guest networks at hotels, cafes, airports, or customer sites almost never block 443. Whereas the UDP 500/4500 that IPsec needs is often blocked.
The cost is TLS encapsulation overhead, though modern implementations using DTLS/QUIC have improved a lot.
If unsure what to pick, pick this one.
L2TP over IPsec: a built-in OS client
Clear division of labor: L2TP builds the tunnel and assigns addresses (it doesn't encrypt on its own), IPsec handles the encryption. Hence the name has an "over" in it.
The advantage is Windows / macOS / iOS / Android all have a built-in client, no software to install.
The disadvantage is it needs UDP 500 / 4500 / 1701 allowed through, which public networks often block.
One detail to note: within L2TP over IPsec, IPsec uses transport mode, because the tunnel is already provided by L2TP.
IKEv2+EAP and WireGuard
- IKEv2 + EAP: a modern approach, natively supports EAP authentication (password/certificate/two-factor), and combined with MOBIKE can switch seamlessly between WiFi and cellular without dropping the connection.
- WireGuard: next-generation. Tiny codebase, uses only one fixed set of modern algorithms (no negotiation), and a one-RTT handshake.
The "no negotiation" part is key -- no algorithm negotiation means no algorithm-mismatch failures, the fundamental reason it's so simple to configure.
The cost is lower flexibility, authentication is public-key only, and enterprise-grade user management relies on auxiliary systems.
Key takeaways
- SSL VPN runs over 443, the best at traversing firewalls, the default first choice
- L2TP only builds the tunnel and assigns addresses without encrypting -- it relies on IPsec (in transport mode) for encryption
- IKEv2+EAP supports seamless network switching
- WireGuard doesn't negotiate algorithms, so there are no algorithm-mismatch failures
Lesson 3 - Split tunnel vs. full tunnel
Advanced · about 12 min
Goal: A trade-off between security and experience, with no standard answer.
Two modes
- Split tunnel: the gateway only pushes internal routes. The client's internal-network access goes through the tunnel, and browsing goes out its own local uplink.
- Full tunnel: the gateway pushes 0.0.0.0/0. All of the client's traffic enters the tunnel, including ordinary browsing.
Where the trade-off lies
Split tunnel
- Good: fast browsing, doesn't consume company egress bandwidth
- Risk: the client is connected to both the internal network and the public internet at once, theoretically becoming a pivot point. If this machine gets infected with malware, the attacker gains a path into the internal network. Many security compliance requirements explicitly forbid it.
Full tunnel
- Good: all traffic passes through the enterprise egress, subject to policy and audit controls
- Cost: heavy load on egress bandwidth, noticeably slower browsing for users, prone to complaints
A common practical compromise: full tunnel + acceleration/caching at the egress; or split tunnel + enforced security baseline checks on the endpoint (EDR, compliance checks).
Hands-on: see which side traffic actually takes
Go to the (3) Access & Test page, dial in, and it will list whether each target goes through the tunnel or the local uplink.
Then switch to full tunnel and see how 8.8.8.8's path changes.
Key takeaways
- Split tunnel only pushes internal routes -- browsing goes out the local uplink
- Full tunnel pushes 0.0.0.0/0 -- all traffic enters the tunnel
- Split tunnel's risk is the client becoming a pivot point between the internal and public networks
Lesson 4 - Connected but can't reach anything
Troubleshooting · about 16 min
Goal: Remote access's number one failure, with a one-line diagnostic rule.
Four access steps, four categories of failure
(1) Can't connect -> the port is blocked by an intermediate network. This is exactly why SSL VPN uses port 443. L2TP/IKEv2's UDP 500/4500 is often blocked.
(2) Authentication fails -> credentials, certificate validity, two-factor, account locked after repeated failures (looks like "the password is definitely right but it still won't connect").
(3) Can't get an address -> the address pool is exhausted, or the address pool conflicts with the internal subnet (or possibly the client's home network).
(4) Connected but can't reach anything -> covered separately below, this is the most common category.
The two root causes of "connected but can't reach anything"
This symptom has two frequent root causes, and the direction of a packet capture distinguishes them in a second:
(1) The client never sends the packet into the tunnel at all
-> split tunnel is missing that subnet's pushed route. The client's routing table has no such route, the packet goes out the local uplink onto the public internet, and gets dropped because it's a private address.
-> check route print (Windows) / netstat -rn (macOS) on the client for that route.
(2) It went out but never came back
-> the internal network is missing a return route to the address pool. The client's source address is 10.10.10.x, the internal server receives the request, but doesn't know how to route back to this subnet, so the reply goes the wrong way.
One-line diagnostic rule: traffic in with nothing back is almost always a return-route problem.
How to add the return route
Two approaches:
(1) Add a static route on the internal core device (recommended, clean)
ip route-static 10.10.10.0 255.255.255.0 <VPN gateway's internal interface>
If the internal network runs OSPF, the VPN gateway can also redistribute the address pool into OSPF.
(2) NAT traffic entering the internal network on the VPN gateway (simpler)
Swap the source address for the gateway's internal interface address, so the internal network doesn't need to know about the address pool.
The cost is the internal side loses visibility into the real client address, affecting auditing and fine-grained access control.
Hands-on: fix two failures
Load the "Connected but can't reach anything" scenario, which has three problems planted: address pool conflicting with the internal subnet, a missing return route, and split tunnel missing a pushed subnet.
Go to the (3) Access & Test page, dial in, see where it's stuck, which targets are unreachable and why, then go back to the (2) Gateway Config page and fix them one by one.
Key takeaways
- Can't connect = port blocked; authentication fails = credentials/certificate/lockout; can't get an address = pool exhausted or conflicting
- Connected but unreachable: either the client never sends into the tunnel (missing pushed route), or traffic never comes back (missing return route)
- Traffic in, nothing back = a return-route problem
- Fix the return route with a static route, or NAT on the gateway
Lesson 5 - Security hardening and zero trust
Advanced · about 10 min
Goal: Remote access is an entry point exposed to the public internet -- worth extra care.
Remote access is an attack surface
The VPN gateway's port is directly exposed to the public internet, making it the number one target for scanning and credential stuffing.
The bare minimum:
- Enable two-factor (SMS/TOTP/hardware token) -- username/password alone isn't enough; credential stuffing and weak passwords are the number one cause of VPN breaches
- Lockout on repeated login failures + alerting
- Promptly clean up departed-employee accounts (the most commonly missed item)
- Patch the gateway software promptly -- mainstream VPN products have had a fair number of critical vulnerabilities in recent years
- Apply least privilege per person/group -- don't let everyone access the entire internal network
The problem with the traditional VPN model
The traditional VPN's implicit assumption is: "once you're in the tunnel, you're an insider."
Once an endpoint is compromised, the attacker gains broad lateral-movement capability across the internal network -- they become the network-layer equivalent of an employee sitting in the office.
This is why the trend is now toward zero trust / SDP:
no more "network-layer admission" -- instead, authorize per person + device + application each time, verifying every access, trusting no location by default.
VPNs won't disappear overnight, but they're being reduced from a "network access solution" to just "an encrypted transport channel."
Key takeaways
- Remote access is a public-internet attack surface: two-factor, failed-login lockout, cleaning up departed accounts, patching
- The traditional VPN's problem is "once you're in the tunnel, you're an insider"
- Zero trust authorizes per person+device+application each time, rather than granting network-layer admission