Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/strongswan/strongswan/llms.txt

Use this file to discover all available pages before exploring further.

The Extensible Authentication Protocol (EAP) is an IKEv2 authentication framework that supports a wide variety of credential types — passwords, certificates, SIM cards, and more. In strongSwan, EAP is used exclusively for IKEv2; for IKEv1 use XAuth instead. In a typical road-warrior deployment, the gateway authenticates itself with a certificate and the client authenticates via EAP, providing a username/password experience familiar to end users.

Supported EAP Methods

MethodPluginDescription
EAP-MD5eap-md5Challenge-response using MD5 hash; server-only auth
EAP-MSCHAPv2eap-mschapv2Microsoft CHAP v2; mutual auth, generates MSK
EAP-TLSeap-tlsCertificate-based EAP; mutual authentication
EAP-TTLSeap-ttlsTLS tunnel carrying an inner EAP or PAP/CHAP method
EAP-PEAPeap-peapProtected EAP; TLS tunnel with inner EAP-MSCHAPv2
EAP-RADIUSeap-radiusProxy EAP to an external RADIUS server
EAP-SIMeap-simSIM card-based authentication (GSM)
EAP-AKAeap-aka3G/4G USIM card-based authentication
EAP-GTCeap-gtcGeneric Token Card (one-time passwords)
EAP-MD5 does not produce a Master Session Key (MSK) and is not mutual — it only authenticates the client to the server. Use EAP-MSCHAPv2, EAP-TTLS, or EAP-PEAP for stronger password-based authentication.

Gateway Configuration

The gateway authenticates itself with a certificate and requires the client to use EAP:
# /etc/swanctl/swanctl.conf
connections {
  eap-server {
    local_addrs  = 203.0.113.1
    remote_addrs = %any

    local {
      auth  = pubkey
      certs = serverCert.pem
      id    = vpn.example.org
    }

    remote {
      auth   = eap-mschapv2
      # Optionally request EAP-Identity from the client
      eap_id = %any
    }

    vips = 0.0.0.0

    children {
      rw {
        local_ts  = 0.0.0.0/0
        remote_ts = dynamic
      }
    }
  }
}

secrets {
  eap-alice {
    id     = alice
    secret = "AlicePassword!"
  }
  eap-bob {
    id     = bob
    secret = "BobPassword!"
  }
}

Client Configuration

The client authenticates itself with EAP and verifies the gateway’s certificate:
connections {
  eap-client {
    local_addrs  = %any
    remote_addrs = 203.0.113.1

    local {
      auth   = eap-mschapv2
      eap_id = alice
    }

    remote {
      auth    = pubkey
      cacerts = trustedCA.pem
      id      = vpn.example.org
    }

    vips = 0.0.0.0

    children {
      rw {
        remote_ts = 0.0.0.0/0
      }
    }
  }
}

secrets {
  eap-alice {
    id     = alice
    secret = "AlicePassword!"
  }
}

EAP Identity vs IKEv2 Identity

EAP uses two distinct identities:
IdentityConfig KeyPurpose
IKEv2 identitylocal { id }Used in IKE_AUTH; can differ from EAP identity
EAP identitylocal { eap_id }Sent in the EAP-Identity response; used for credential lookup
AAA server identitylocal { aaa_id }Expected server identity in EAP-TLS/TTLS/PEAP inner exchange
When the gateway requests an EAP identity (remote { eap_id = %any }), the client sends its eap_id value. This EAP identity is then used to look up EAP credentials and enforce the uniqueness policy.
# Client sending a different EAP identity than IKE identity
local {
  auth   = eap
  id     = client.example.org  # IKEv2 identity (in certificate or as IDi)
  eap_id = alice@company.com   # EAP identity used for credential lookup
}

EAP-MD5 Example

EAP-MD5 is a simple challenge-response method. The server sends a 16-byte random challenge; the client replies with MD5(identifier | secret | challenge).
# Gateway
remote {
  auth   = eap-md5
  eap_id = %any
}

# Client
local {
  auth   = eap-md5
  eap_id = testuser
}

secrets {
  eap-testuser {
    id     = testuser
    secret = "md5-password"
  }
}

EAP-MSCHAPv2 Example

EAP-MSCHAPv2 provides mutual authentication and generates an MSK for IKEv2 key derivation. It supports NTLM-hashed secrets stored separately from plain-text secrets:
secrets {
  # Plain-text password (hashed internally)
  eap-alice {
    id     = alice
    secret = "AlicePassword"
  }

  # Pre-computed NT Hash: MD4(UTF-16LE(password))
  ntlm-bob {
    id     = bob
    secret = 0x8846f7eaee8fb117ad06bdd830b7586c
  }
}

Combining Certificate + EAP (Two-Round Auth)

RFC 4739 Multiple Authentication allows the client to authenticate with both a certificate and EAP in a single IKE session:
connections {
  dual-auth {
    local {
      auth  = pubkey
      certs = serverCert.pem
    }
    local2 {
      auth   = eap-mschapv2
      eap_id = %any
    }

    remote {
      # First round: client certificate
      auth    = pubkey
      cacerts = clientCA.pem
    }
    remote2 {
      # Second round: EAP password
      auth = eap-mschapv2
    }
  }
}

EAP-RADIUS

The eap-radius plugin proxies EAP conversations to an external RADIUS server, enabling integration with existing AAA infrastructure (Active Directory, FreeRADIUS, etc.) without storing credentials locally.

How It Works

strongSwan acts as a RADIUS NAS (Network Access Server). EAP packets received from the IKE client are wrapped in RADIUS Access-Request messages and forwarded to the RADIUS server. The server’s Access-Accept or Access-Reject is translated back into IKE EAP success/failure.

swanctl.conf

The connection config remains the same — just use the desired EAP method in remote { auth } as the RADIUS server handles the actual credential check:
remote {
  auth   = eap-radius
  eap_id = %any
}

strongswan.conf

Configure the RADIUS server in strongswan.conf:
# /etc/strongswan.conf
charon {
  plugins {
    eap-radius {
      server         = radius.example.org
      secret         = sharedRADIUSsecret
      port           = 1812  # default auth port
      nas_identifier = strongSwan-VPN
      sockets        = 1
    }
  }
}
The eap-radius plugin also registers an XAuth backend named radius, allowing RADIUS-based authentication for IKEv1 XAuth connections.

RADIUS Accounting

The plugin supports RADIUS accounting (RFC 2866). Accounting Start/Stop packets are sent to the RADIUS server’s accounting port (default: 1813) as IKE_SAs are established and torn down.

Dynamic Authorization (DAE)

The plugin supports RADIUS Dynamic Authorization Extensions (RFC 5176), allowing the RADIUS server to send Disconnect-Requests or CoA-Requests to terminate or modify active sessions:
charon {
  plugins {
    eap-radius {
      dae {
        enable = yes
        listen = 0.0.0.0
        port   = 3799
        secret = daeSecret
      }
    }
  }
}