MikroTik IPsec runbook — AWS Site-to-Site VPN customer gateways¶
Customer-side (MikroTik CHR) IPsec settings for the IKEv2 tunnels that terminate the
AWS Site-to-Site VPN connections (client-a, client-b, client-c, client-d,
client-e*). This is the customer-router half of the lifetime/rekey fix; the
AWS half lives in terraform/aws/_modules/vpn/main.tf
and the auto-remediation in terraform/aws/_modules/tunnel-trampoline.
Why this exists. On 2026‑07‑17 ~14:00 the Client A/Client C/Client B tunnels went fully down and stayed wedged (a stale IKE SA) until Client A was manually disabled/re‑enabled on 2026‑07‑20 ~08:15. Two things caused/prolonged it: (1) an over‑aggressive AWS rekey margin (now fixed AWS‑side:
rekey_margin_time_seconds1800 → 540), and (2) MikroTik‑side IKE/child‑SA lifetimes that don't align with AWS and DPD not tearing down the dead peer, so a wedged SA never cleared itself. This runbook aligns the lifetimes and enables DPD so a dead peer self‑heals instead of needing a hand‑bounce.Phase B will automate this via the RouterOS API (see the infra plan); until then, apply it by hand per router — Client A first.
Target settings (match the AWS side)¶
| Layer | RouterOS object | Set to | AWS side it matches |
|---|---|---|---|
| Phase 1 (IKE SA) | /ip ipsec profile lifetime |
8h |
phase1_lifetime_seconds = 28800 |
| Phase 1 DPD | /ip ipsec profile dpd-interval / dpd-maximum-failures |
10s / 3 |
dpd_timeout_seconds = 30, dpd_timeout_action = "restart" |
| Phase 2 (child SA) | /ip ipsec proposal lifetime |
1h |
phase2_lifetime_seconds = 3600 |
Rationale:
- Equal lifetimes + AWS's smaller rekey margin ⇒ AWS always initiates the rekey
first, so the two peers don't both try at once (the collisions that leave stale
child SAs).
- DPD (dpd-interval=10s, dpd-maximum-failures=3) ⇒ if the AWS peer stops
responding, the MikroTik tears the SA down (~30s) and renegotiates automatically —
the self‑heal that was missing on 2026‑07‑17.
Router endpoints (MikroTik cloud DDNS)¶
| Customer | Endpoint | AWS BGP ASN |
|---|---|---|
| client-a | hx0000000a1.sn.mynetname.net |
65102 |
| client-b | hx0000000c3.sn.mynetname.net |
65103 |
| client-c | hx0000000b2.sn.mynetname.net (TMC: client-c-tmc.ddns.net) |
65104 |
| client-d (site D) | hx0000000e5.sn.mynetname.net |
65105 |
| client-e | b2c3d4e5f6a7.sn.mynetname.net |
65109 |
| client-e-site2 | hx0000000d4.sn.mynetname.net |
65106 |
| client-e-site3 | a1b2c3d4e5f6.sn.mynetname.net |
65107 |
Access is over the RouterOS API / SSH / WinBox with a write‑capable account (the
monitoring readonly credentials cannot make these changes). Endpoints are also the
canonical inventory in platform-utils router-fleet-resolver/routers-inventory.yml.
Apply (per router)¶
Always print first — object names differ per router; scope set by the printed
.id/name of the objects the AWS peer uses, never blindly across all IPsec.
# 1. Find the AWS peer and the profile/proposal it uses.
/ip ipsec peer print detail
/ip ipsec profile print detail
/ip ipsec proposal print detail
# 2. Phase 1 (IKE) — align lifetime to AWS (8h) and enable DPD self-heal.
# Replace <aws-profile> with the profile name the AWS peer references.
/ip ipsec profile set [find name="<aws-profile>"] \
lifetime=8h dpd-interval=10s dpd-maximum-failures=3
# 3. Phase 2 (child SA) — align lifetime to AWS (1h).
# Replace <aws-proposal> with the proposal name used by the AWS policy.
/ip ipsec proposal set [find name="<aws-proposal>"] lifetime=1h
Verify¶
/ip ipsec profile print detail ;# lifetime=8h, dpd-interval=10s, dpd-maximum-failures=3
/ip ipsec proposal print detail ;# lifetime=1h
/ip ipsec active-peers print ;# the AWS peer is "established", uptime resets after a rekey
/ip ipsec installed-sa print ;# fresh SAs; no duplicate/half-open child SAs
On the AWS side, confirm the connection's tunnels return to UP and traffic flows
again on the VPN Tunnels Grafana dashboard (aws_vpn_tunnel_state_maximum == 1).
Manual bounce (emergency clear of a wedged tunnel)¶
This is the fix that was done by hand on 2026‑07‑17→20. Prefer letting the
tunnel‑trampoline do the AWS‑side equivalent (ReplaceVpnTunnel) once
down_dry_run=false; use this only when acting directly on the router.
# Bounce the AWS peer to force a clean renegotiation (flushes the stale SA).
/ip ipsec identity disable [find peer="<aws-peer>"]
/ip ipsec identity enable [find peer="<aws-peer>"]
# If SAs linger, flush them (they renegotiate immediately):
/ip ipsec installed-sa flush
Notes¶
- Do not widen these
setcommands to all IPsec objects — a router may also run WireGuard/other IPsec; scope to the AWS peer's profile/proposal only. - Keep the MikroTik lifetimes equal to (not shorter than) the AWS values so AWS
stays the rekey initiator. If you ever raise the AWS
phase*_lifetime_seconds, raise these to match. client-eis not yet in the monitoring router‑fleet inventory; add it there when Phase B automation lands so it is covered.