Skip to content

Parameter Sheet Mapping

The page to keep open while filling in a client's IPsec parameter sheet (Fortigate, pfSense, whatever they send back) as an IPsecGateway CR. Every row below maps a field a client sheet typically asks for to the CR field it becomes; see the CRD Reference for the full field semantics.

Client sheet field CR field Notes
IKE version spec.ike.version Must be 2 — this operator is IKEv2/PSK only (see Known Limitations).
Phase 1 (IKE) proposal / encryption+hash+DH-group spec.ike.proposals Must exact-match the operator's approved allowlist (aes256-sha256-ecp256, aes256-sha512-ecp384, aes256gcm16-prfsha384-ecp384, aes256gcm16-prfsha256-ecp256 — see CRD Reference); a client sheet asking for anything else needs a conversation, not a CR edit. One or more entries; passed through to swanctl.conf's proposals = line verbatim (comma-joined) once validated.
Phase 1 lifetime spec.ike.lifetime e.g. "86400s" for 24h. Omit to take the operator's default (also 86400s).
Phase 2 (IPsec/ESP) proposal spec.tunnels[].esp.proposals Same proposal-string syntax as IKE, per tunnel.
Phase 2 lifetime spec.tunnels[].esp.lifetime e.g. "28800s" for 8h. Omit to take the operator's default — 43200s (12h), not 86400s — the ESP and IKE defaults differ; don't assume they match.
DPD (Dead Peer Detection) interval / retries spec.ike.dpd.delay / spec.ike.dpd.timeout Delay = probe interval (default 30s); Timeout = how long without a response before the SA is considered dead (default 150s, i.e. ~5 missed probes at the default delay). Most client sheets give "retries" rather than a timeout directly — timeout ≈ delay × (retries + 1).
Peer / remote gateway public IP spec.tunnels[].peer.address Also opens the per-tunnel security-group ingress rule (UDP/500 + UDP/4500, restricted to this /32) — a wrong value here doesn't just misconfigure IKE, it also blocks that address at the firewall layer.
Peer / remote IKE identity (ID) spec.tunnels[].peer.id Many client devices default their IKE ID to their public IP — if the sheet doesn't separately specify one, use the same value as peer.address.
Pre-shared key (PSK) A Kubernetes Secret, referenced by spec.auth.pskSecretRef.name/.key Never put the PSK in the CR itself — the CRD has no PSK field. Create the Secret first (kubectl create secret generic <name> --from-literal=<key>=<psk>), then reference it. See Quick Start.
"Network(s) behind their gateway" / remote subnets spec.tunnels[].remoteSubnets One or more CIDRs. Currently rendered as one child SA with a comma-joined remote_ts, not split per subnet — flag this to the reviewing engineer if the client's own firewall needs narrow per-subnet selectors (see Known Limitations).
"Network behind our gateway" / our local subnet (their side of the cryptomap) status.serviceCIDR (read-only, allocated) This is not something you set on the sheet mapping — it's the operator-allocated /24 (or spec.serviceCIDR if you're pinning one) that becomes local_ts in the rendered child SA. Read it back with kubectl get ipsecgateway <name> -o jsonpath='{.status.serviceCIDR}' once the CR is applied, and hand that CIDR to the client as "our network" for their cryptomap/Phase 2 selector.
Cryptomap / Phase 2 selectors (local ↔ remote) local_ts = status.serviceCIDR, remote_ts = spec.tunnels[].remoteSubnets The pair the rendered swanctl.conf child SA actually negotiates — this is the mapping to hand a client whose device wants explicit selectors rather than "any".
"What do we expose to them" / DNAT targets on our side spec.exposures[] Each entry gets its own virtual IP (auto-assigned .10.199 in status.serviceCIDR, or pin one) that DNATs to target.address/target.host (+ target.ports, or all-protocol if empty). This is what the client's firewall admin actually points their rules at — hand them the virtual IP, not our real internal address. Before onboarding, confirm the target's own security group allows ingress from the gateway network's subnet — the operator doesn't provision this side (see Networking).
"What of theirs do we need to reach" / reverse DNAT spec.reverseExposures[] Same shape as exposures[], but the virtual IP range is .200.254 and target must be an address (never host — see the CRD reference). Requires an allowed-address-pair + router route on our side (RoutingReady condition) — the client does not need to add anything extra for this beyond routing that traffic into the tunnel on their end.

Worked example — a representative sheet

Example values from our reference deployment (verified 2026-08-19); peer uses an RFC 5737 documentation address as a stand-in for a real client's peer IP — a useful reference for what a filled-in sheet actually produces:

Sheet field Value → CR
Phase 1 proposal AES-256 / SHA-512 / DH group 20 spec.ike.proposals: [aes256-sha512-ecp384]
Phase 1 lifetime 24h spec.ike.lifetime: "86400s"
DPD 30s / 150s spec.ike.dpd: {delay: "30s", timeout: "150s"}
Peer public IP 203.0.113.10 spec.tunnels[0].peer.address: "203.0.113.10"
Peer IKE ID 203.0.113.10 (same as address) spec.tunnels[0].peer.id: "203.0.113.10"
Their network 10.20.0.0/16 spec.tunnels[0].remoteSubnets: ["10.20.0.0/16"]
Phase 2 proposal AES-256 / SHA-512 / DH group 20 spec.tunnels[0].esp.proposals: [aes256-sha512-ecp384]
Phase 2 lifetime 8h spec.tunnels[0].esp.lifetime: "28800s"
Our network (fed back to client) 100.64.12.0/24 read from status.serviceCIDR after apply
Their LDAPS endpoint we reach 10.20.2.20:636 spec.reverseExposures: [{name: ldaps, target: {address: "10.20.2.20", ports: [636]}}], virtual IP auto-assigned in the .200+ range

See the full worked CR in Quick Start.