Selectors, routes, firewall, NAT, overlaps, and MTU — the six things to check, in order, when phase 1 and 2 are up but no data flows.
Both peers report the tunnel as ESTABLISHED, phase 1 and phase 2 are green, and yet a ping across the link times out and applications cannot reach the far subnet. This is one of the most common IPsec support cases, and it is almost never a negotiation problem — the encrypted channel is fine, but something between the host and the tunnel is dropping, misrouting, or rewriting the packets.
Work through the six causes below in order. Each one has a symptom, a command that confirms it, and the fix. Throughout, the VPNGeek side is 10.20.0.0/16 and the remote LAN is 192.168.1.0/24.
First, confirm the SA is actually installed
Before blaming routing, make sure a child SA with the right selectors exists and is passing counters. On the VPNGeek gateway:
ipsec statusall
# Look for a CHILD_SA line like:
# net-net{3}: INSTALLED, TUNNEL, ...
# net-net{3}: 10.20.0.0/16 === 192.168.1.0/24
# and byte counters that INCREASE when you send traffic:
# net-net{3}: in 1234 bytes, out 5678 bytes
If out bytes climb but in stays at zero, your packets are entering the tunnel and the reply is being lost on the far side (routing/firewall there). If out never moves, your own host's traffic is not reaching the tunnel at all — start at cause 1.
1. Traffic selectors / proxy IDs mismatch
The selectors define which source/destination subnets are allowed into the tunnel. If the two peers disagree — even by one bit of a netmask — the SA may still install with a narrowed range, and any packet outside that narrowed range is silently discarded.
ipsec statusall | grep -A1 CHILD_SA
# IKEv1 equivalent — compare the proxy IDs on both firewalls.
# VPNGeek expects: local 10.20.0.0/16 remote 192.168.1.0/24
# The peer MUST mirror it: local 192.168.1.0/24 remote 10.20.0.0/16
Fix: make both peers define identical subnets (mirrored). On a policy-based peer, the proxy ID pair must match VPNGeek's local/remote exactly. Re-establish the child SA after changing selectors so the new range installs.
2. Missing or wrong route
Even with a perfect SA, the kernel has to decide to send the packet toward the tunnel. On a route-based (VTI/XFRM) setup a missing route sends the traffic out the default gateway in clear text instead.
ip route get 192.168.1.10
# GOOD: dev vti0 (or your XFRM/tunnel iface)
# BAD: dev eth0 via <default gw> -> leaks in the clear
# List installed IPsec policies (policy-based / XFRM)
ip xfrm policy
# Add the missing route for a route-based tunnel
ip route add 192.168.1.0/24 dev vti0
Fix: add a static route for the remote subnet pointing at the tunnel interface (route-based), or confirm the XFRM policy exists (policy-based). Also check the return route on the far side and on the destination host itself.
3. Firewall policy not permitting the subnets
The packet may reach the tunnel and be encrypted, but a firewall rule — on either gateway, or on the host — can drop it before or after decryption. On decrypt, traffic often arrives on the tunnel/VTI interface, which many rule sets do not trust by default.
tcpdump -ni vti0 host 192.168.1.10
# See what the ESP packets look like on the WAN (encrypted)
tcpdump -ni eth0 esp or udp port 4500
# Check counters on any DROP rules
iptables -vnL FORWARD --line-numbers
Fix: add explicit allow rules in both directions between 10.20.0.0/16 and 192.168.1.0/24, and make sure the tunnel/VTI interface is in a trusted zone. On the destination host, allow the remote subnet through its local firewall.
4. NAT eating the traffic before the tunnel
If the gateway also does source NAT for internet-bound traffic, a broad masquerade rule can rewrite the source address of tunnel-bound packets before the IPsec policy matches them. The rewritten source no longer matches the selector, so the packet skips the tunnel entirely.
iptables -t nat -vnL POSTROUTING --line-numbers
# Exempt tunnel-bound traffic from NAT (insert BEFORE the masquerade).
# This says: do not NAT traffic from our LAN to the remote LAN.
iptables -t nat -I POSTROUTING 1 \
-s 10.20.0.0/16 -d 192.168.1.0/24 -j ACCEPT
Fix: add a no-NAT exemption for the site-to-site subnet pair, inserted above the general masquerade rule. On many appliances this is a dedicated "no-NAT" or "policy NAT exempt" checkbox on the VPN policy.
5. Overlapping subnets
If both sides use the same or overlapping address space (classic when both use 192.168.1.0/24), the host can never tell "local" from "remote" — it delivers the packet on its own LAN instead of the tunnel. The tunnel is healthy but the packet is never handed to it.
ip route | grep -E '192\.168\.1\.|10\.20\.'
# If the far LAN overlaps yours, present it via 1:1 NAT
# so it appears as a distinct range across the tunnel, e.g.
# remote 192.168.1.0/24 mapped to 10.99.1.0/24 locally.
6. MTU / fragmentation
This is the last check because it produces a distinctive symptom: small pings work, large transfers hang. IPsec adds encapsulation overhead, so a full-size 1500-byte packet no longer fits. If the path filters ICMP, Path MTU Discovery breaks and large packets vanish into a blackhole while tiny ones sail through.
ping -M do -s 1400 -c 3 192.168.1.10 # likely fails over IPsec
ping -M do -s 1200 -c 3 192.168.1.10 # likely succeeds
# Binary-search the largest payload that gets through, then set
# tunnel MTU = working payload + 28 (IP+ICMP headers).
# Pragmatic fix: clamp TCP MSS to the tunnel path MTU
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Fix: lower the tunnel interface MTU (typically 1400 or lower) and clamp TCP MSS so TCP sessions negotiate a size that survives encapsulation. For a full walk-through of encapsulation overhead and PMTUD blackholes, see the dedicated MTU and fragmentation guide.
Summary
Ninety percent of "up but no traffic" cases are one of the first three: a narrowed selector, a missing route, or a firewall rule. Confirm the SA counters first, then walk selectors → routes → firewall → NAT → overlaps → MTU. Fix one thing at a time and re-test with a sourced ping so you always know which change moved the needle.
