# L2TP/IPsec VPN Connection Debugging Real-world troubleshooting log from setting up a L2TP/IPsec VPN tunnel between a Hetzner VPS (Ubuntu 24.04, strongSwan 6.0.4) and a MikroTik CCR gateway. ## Problem: Tunnel won't establish ### Symptom 1: "no shared key found" / INVAL_KE ``` parsed ID_PROT response 0 [ SA V V V V ] no shared key found for '5.161.114.8' - '76.195.7.60' received NO_PROPOSAL_CHOSEN error notify ``` **Causes:** 1. PSK in ipsec.secrets doesn't match what's on the MikroTik 2. strongSwan 6 stroke plugin doesn't match the generic `: PSK "..."` format **Fix:** Use explicit IPs in ipsec.secrets and strip YAML inline comments from the parsed value: ```bash printf '5.161.114.8 %s : PSK "%s"\n' "$SERVER_IP" "$PSK" > "$IPSEC_SECRETS" ``` Also ensure the comment was stripped from the YAML value: `sed 's/ *#.*//'` after extraction. ### Symptom 2: "NO_PROPOSAL_CHOSEN" on ESP (Phase 2) after IKE SA established ``` IKE_SA wisp-vpn[5] established between 5.161.114.8[...]...76.195.7.60[...] parsed INFORMATIONAL_V1 request [ HASH N(NO_PROP) ] received NO_PROPOSAL_CHOSEN error notify ``` **Cause:** ESP proposal `esp=aes128-sha1` doesn't include MODP group. strongSwan 6 requires exact match with the MikroTik's proposal. **Fix:** Add `-modp1024` suffix to both `ike=` and `esp=`: ``` ike=aes128-sha1-modp1024 esp=aes128-sha1-modp1024 ``` ## Problem: VPN connects but kills VPS internet ### Symptom: "ppp0 recursion detected" on MikroTik, VPS unreachable, Telegram/SSH dead **User sees on MikroTik:** `ppp0 recursion detected` in logs. **VPS behavior:** internet completely dead — `ping 8.8.8.8` fails, SSH session drops, Telegram stops responding. **Reproduction:** Happens when the VPN script `up` handler doesn't pin the L2TP server public IP route before `ipsec up`. The IPsec transport mode encrypts traffic destined for `76.195.7.60` (the peer), the kernel looks up the route, finds ppp0, and sends the encrypted packet back through the tunnel → MikroTik sees it and logs `recursion detected`. **Recovery:** The user must disable the PPP secret on their MikroTik to force the L2TP session down (`/ppp secret disable shonuff`). The IPsec SA may also need to be cleared on both sides. **Fix (in wisp-vpn.sh `up` handler, BEFORE `ipsec up`):** ```bash # Pin the L2TP server's route through eth0, not through the tunnel CURRENT_GW=$(ip route get 8.8.8.8 | awk '{print $3}' | head -1) if [ -n "$CURRENT_GW" ]; then ip route add "$SERVER_IP" via "$CURRENT_GW" dev eth0 metric 100 2>/dev/null || \ ip route change "$SERVER_IP" via "$CURRENT_GW" dev eth0 metric 100 2>/dev/null fi ``` Also remove `defaultroute` from the PPP options so pppd doesn't install itself as the default route at all. Add only specific subnet routes through ppp0 after connection. ## When to keep the VPN always-on Once the tunnel is stable, switch from connect-on-demand to always-on: - **systemd service** — `wisp-vpn.service` with `ExecStart=/bin/bash /script.sh status` + `ExecStart=/bin/bash /script.sh up` (idempotent — if status exits 0, the second ExecStart is skipped) - **Keepalive timer** — `wisp-vpn-keepalive.timer` running every 2 minutes, reconnecting if the tunnel drops - **Auto-start** — both the service and timer are `systemctl enable`'d so they survive reboots See the umbrella skill's "Always-on VPN with systemd" section for full implementation. ### Symptom: L2TP connects but SSH to router fails (timeout) **Setup:** ppp0 has IP `192.168.88.105`, peer is `192.168.88.1`. Ping fails, SSH times out. **Causes:** 1. Firewall on MikroTik blocks traffic from ppp interface to router management IP 2. `/ip service set ssh address=` restricts SSH to specific source IPs/subnets 3. Routing table on VPS doesn't have the `192.168.88.0/24` route through ppp0 **Fix (on MikroTik):** ```routeros /ip service set ssh address=0.0.0.0/0 ``` ## How to verify IPsec status ```bash # Check IPsec SA state ipsec status # Check all SAs ipsec statusall # Check routing ip route show | grep ppp # Check VPN interface ip addr show ppp0 # Check charon logs journalctl -u strongswan-starter -n 30 --no-pager # Check xl2tpd logs journalctl -u xl2tpd -n 30 --no-pager # Check if internet is reachable (must do after VPN connect) ping -c 1 -W 3 8.8.8.8 ``` ## Current working config (MikroTik L2TP/IPsec) ```conf config setup charondebug="all" uniqueids=yes conn wisp-vpn auto=add keyexchange=ikev1 authby=secret type=transport left=%defaultroute leftprotoport=17/1701 right=76.195.7.60 rightprotoport=17/1701 ike=aes128-sha1-modp1024 esp=aes128-sha1-modp1024 dpddelay=30 dpdtimeout=120 dpdaction=clear ``` ## Terminal output reference When the IPsec connection succeeds: ``` connection 'wisp-vpn' established successfully ``` When the L2TP connection succeeds: ``` pppd[NNN]: local IP address 192.168.88.105 pppd[NNN]: remote IP address 192.168.88.1 ``` When authentication fails: ``` pppd[NNN]: MS-CHAP authentication failed: bad username or password pppd[NNN]: CHAP authentication failed ``` When `lock` option is used (pppd 2.5.x): ``` pppd[NNN]: unrecognized option 'lock' ```