Skip to content
Thomas Mangin edited this page Jul 13, 2026 · 4 revisions

Pre-Alpha. This page describes behavior that may change.

Ze implements native IKEv2 in Go for route-based IPsec VPN tunnels. No strongSwan, no libreswan, no external IKE daemon. The IKE engine, the cryptographic primitives, the wire codec, and the XFRM dataplane integration are all in-tree. The result is a single binary that negotiates IKE SAs, installs XFRM policies and states, and programs routes through XFRM interfaces, all driven from the same YANG config tree as every other Ze subsystem.

Architecture

The IPsec stack is split across several packages:

Package Role
internal/component/ike/wire IKEv2 wire format codec (RFC 7296). Encodes and decodes all payload types.
internal/component/ike/crypto Cryptographic primitives: DH groups, PRF, integrity, encryption, key derivation.
internal/component/ike/transport UDP transport with NAT-T (RFC 3948) keepalives, port 4500 encapsulation.
internal/component/ike/eap EAP authentication: EAP-MSCHAPv2, EAP-TLS.
internal/component/ike/engine IKE FSM: IKE_SA_INIT, IKE_AUTH, CREATE_CHILD_SA, INFORMATIONAL. Initiator and responder roles, rekeying, DPD.
internal/component/ike/ipsec Config, YANG schema, validation.
internal/component/ike/dataplane XFRM policy and state programming via netlink.
internal/component/pki PKI certificate store for X.509 certificates and private keys.

Configuration

IPsec is configured under vpn { ipsec { } }. Named ike-group and esp-group blocks hold the IKE and ESP proposals and lifetimes; each site-to-site peer references a group pair, sets its authentication, and binds to a VTI (XFRM) interface for route-based forwarding.

pki {
    certificate my-cert {
        certificate-file /etc/ze/certs/router.pem;
        private-key-file /etc/ze/certs/router-key.pem;
    }
    ca-certificate my-ca {
        certificate-file /etc/ze/certs/ca.pem;
    }
}

vpn {
    ipsec {
        interface eth0;

        ike-group site-b-ike {
            key-exchange ikev2;
            lifetime     28800;
            proposal 1 {
                encryption aes256gcm;
                hash       sha256;
                dh-group   14;
            }
            dead-peer-detection { interval 30; timeout 120; }
        }

        esp-group site-b-esp {
            lifetime 3600;
            pfs      enable;
            proposal 1 { encryption aes256gcm; }
        }

        site-to-site {
            peer site-b {
                ike-group       site-b-ike;
                esp-group       site-b-esp;
                connection-type initiate;
                local-address   198.51.100.2;
                remote-address  198.51.100.1;
                authentication {
                    mode           x509;
                    certificate    my-cert;
                    ca-certificate my-ca;
                }
                vti { bind vti0; }
            }
        }
    }
}

Traffic selectors are not listed per tunnel: route-based IPsec sends whatever the routing table forwards through the bound VTI (see Interfaces: XFRM).

IKE features

Feature Detail
IKEv2 (RFC 7296) Full IKE_SA_INIT, IKE_AUTH, CREATE_CHILD_SA, INFORMATIONAL exchange support.
Role Initiator or responder, per peer (connection-type initiate / respond). See IKEv2 responder role below.
Proposals AES-CBC, AES-GCM (128/256), ChaCha20-Poly1305. DH groups: MODP 2048/3072/4096/8192, ECP 256/384/521. PRF: SHA-256/384/512.
Authentication Pre-shared key, X.509 certificates, EAP-MSCHAPv2, EAP-TLS. As responder, Ze is the EAP authenticator (EAP-MSCHAPv2 / EAP-TLS server).
NAT-T (RFC 3948) Automatic NAT detection, UDP encapsulation on port 4500, keepalive.
DPD Dead Peer Detection via INFORMATIONAL exchange. Configurable interval and timeout.
Rekeying Real CREATE_CHILD_SA rekeying of both the IKE SA and the Child SAs, make-before-break. Collision handling. See Rekeying below.
MOBIKE (RFC 4555) Not implemented; an endpoint address change requires the SA to be re-established.
Virtual IP pool Remote-access server assigns addresses from a configured pool.

IKEv2 responder role

Ze can act as the IKEv2 responder as well as the initiator. A peer with connection-type respond waits for an unsolicited inbound IKE_SA_INIT from its configured remote-address, answers IKE_AUTH, and installs the first Child SA. (connection-type initiate, the default, is the original behavior.) The UDP transport always listens, so there is no separate listen switch: responder behavior is selected by connection-type respond plus a matching remote address.

As responder Ze authenticates with pre-shared key, X.509 certificate, or EAP. For EAP it is the EAP authenticator (the EAP-MSCHAPv2 or EAP-TLS server) for a road-warrior client: it presents its own certificate or PSK first, then runs the EAP method and derives the session keys from the EAP MSK.

vpn {
    ipsec {
        interface eth0;
        ike-group IKE-PSK {
            key-exchange ikev2;
            proposal 1 { encryption aes256gcm; hash sha256; dh-group 14; }
        }
        esp-group ESP-PSK {
            pfs enable;
            proposal 1 { encryption aes256gcm; }
        }
        site-to-site {
            peer swan {
                ike-group       IKE-PSK;
                esp-group       ESP-PSK;
                connection-type respond;
                local-address   172.28.0.2;
                remote-address  172.28.0.3;
                authentication {
                    mode              pre-shared-secret;
                    local-id          "172.28.0.2";
                    remote-id         "172.28.0.3";
                    pre-shared-secret "$9$encoded";
                }
            }
        }
    }
}

For a road-warrior EAP server, set authentication { mode eap-mschapv2 } (or eap-tls) and reference a device certificate and ca-certificate from the PKI store. The remote-access container assigns client addresses from a pool and holds per-user EAP credentials in an eap-user list.

Rekeying

Both the Child SAs and the IKE SA are rekeyed with a real on-the-wire CREATE_CHILD_SA exchange (RFC 7296), replacing an earlier local-only key roll that could silently desync a live tunnel. A Child SA rekey carries N(REKEY_SA) with fresh nonces and traffic selectors; an IKE SA rekey performs a fresh Diffie-Hellman exchange (the peer supplies its key-exchange payload) and resets the message-ID counters.

Rekeying is make-before-break: the replacement SA is installed before the old one is deleted, so forwarding never pauses. Simultaneous rekeys are resolved by the RFC 7296 nonce rule (the lower nonce wins) so both ends converge on one SA. Ze rekeys on the ESP or IKE soft-lifetime and retransmits a lost CREATE_CHILD_SA before tearing the tunnel down. Rekeys are counted by ze_ipsec_rekey_total{peer} (both Child SA and IKE SA rekeys) and streamed as child-rekey on monitor vpn ipsec.

Child SA and dataplane

Child SAs define the traffic selectors and the ESP proposal. Ze programs XFRM policies and states via netlink. Route-based IPsec uses XFRM interfaces (see Interfaces: XFRM).

Feature Detail
ESP proposals AES-GCM-16 (128/256), AES-CBC + HMAC-SHA-256/384/512.
Traffic selectors IPv4 and IPv6 CIDR prefixes.
Connection Per peer: connection-type initiate starts the exchange, connection-type respond waits for the peer (see IKEv2 responder role).
Replay protection Anti-replay window (default 32).
Lifetime Time-based and byte-based rekeying thresholds.

PKI certificate store

The pki { } block stores X.509 certificates, private keys, and CA certificates. Certificates are loaded from PEM files and validated at commit time. The PKI store also serves TLS certificates for the web UI and the gRPC API.

Health monitoring reports certificate expiry as warnings (30 days) and errors (expired). Prometheus metrics: ze_pki_certificate_expiry_seconds, ze_pki_certificate_valid.

XFRM interfaces

XFRM interfaces provide route-based IPsec. Traffic routed through the XFRM interface is encrypted; traffic arriving on it is decrypted. See Interfaces: XFRM for the config surface.

CLI

Command Description
show vpn ipsec status Tunnel and peer status summary.
show vpn ipsec sa Active IKE and Child SAs: algorithms, byte counts, rekey timers, SPIs, NAT detection, and is-initiator (initiator vs responder role).
show vpn ipsec peer name <name> Detail for one configured peer.
clear vpn ipsec sa [peer <name>] Tear down and re-establish SAs, optionally for one peer.
monitor vpn ipsec Stream SA and child lifecycle events (sa-up, sa-down, child-up, child-down, child-rekey).
show pki certificates List loaded certificates with expiry.

Health and metrics

The IPsec component registers with the health registry. It reports healthy when all configured tunnels are established, degraded when some are down, and down when critical tunnels fail.

Prometheus metrics include ze_ipsec_sa_count (active IKE SAs), ze_ipsec_tunnel_up{peer}, and ze_ipsec_rekey_total{peer}.

Interop testing

The IKE implementation includes interop tests against strongSwan 5.9.14 (the version shipped in the Alpine 3.21 test image). The test infrastructure lives in test/ipsec-interop/ and drives Docker containers running strongSwan as the remote IKE peer. Coverage includes PSK, X.509, and EAP (EAP-MSCHAPv2 and EAP-TLS) authentication; Ze as the PSK and EAP-MSCHAPv2 responder against a strongSwan initiator; Child SA rekeying with make-before-break; and IKE SA rekeying initiated by strongSwan.

See also

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally