Problem Statement
Modern OpenVPN deployments increasingly use external authentication — OAuth2/OIDC (openvpn-auth-oauth2), LDAP, RADIUS. Users authenticate and authorize via groups/roles, and each group needs its own IP subnet for:
- Firewall rules (MikroTik, iptables) based on source subnet
- Monitoring and session tracing
- Quality of Service policies
- Access segregation to internal resources
Example use-case:
| Group |
Required subnet |
support |
10.8.3.0/24 |
all (regular VPN) |
10.8.0.0/24 |
| Administrators |
10.8.0.0/24 with per-user static IP |
Currently OpenVPN supports only a single pool via --server or --ifconfig-pool. There is no mechanism to define multiple pools and dynamically select which pool to assign an IP from based on the client's group/role.
Current Workarounds and Their Limitations
1. CCD + static IPs (ifconfig-push)
Each profile/group gets a CCD file with ifconfig-push. However:
- This is a static assignment, not a pool — all users in the same group would get the same IP, which doesn't work for concurrent connections.
- Per-user CCD files don't scale (N users = N files to manage).
- No dynamic IP allocation — you must manually manage the address space.
2. client-connect script with external IPAM
A custom script can maintain its own pool DB and issue ifconfig-push via the management interface. Drawbacks:
- OpenVPN is unaware of this external pool — no conflict detection with
--ifconfig-pool.
- No integration with OpenVPN's built-in pool tracking.
- Requires external locking and persistence mechanisms.
- Duplicates functionality that should be in the core.
3. client-auth (MDA) + ifconfig-push
When using the management interface (e.g. openvpn-auth-oauth2), the client-auth command can include a config block with ifconfig-push. This works, but:
- There's no way to say "give me any free IP from pool X" — you must hardcode the IP.
- The selected profile/group info is available at auth time but cannot be used to select a pool dynamically.
4. Profile selector + per-profile static IPs (our current setup)
Our current setup:
/etc/openvpn-auth-oauth2/client-config/Access_VPN_all.conf — no ifconfig-push, IP from the default pool
/etc/openvpn-auth-oauth2/client-config/Access_VPN_support.conf — ifconfig-push 10.8.3.10
- Per-user CCD for admins —
ifconfig-push 10.8.3.12
The CEL expression in openvpn-auth-oauth2 v2 correctly selects the config file based on Keycloak groups, but all users from the support group still get the same static IP. This is fine for our current scale, but it doesn't scale to multiple concurrent users per group without IP conflicts.
Proposed Feature: Named --ifconfig-pool pools with dynamic selection
Server configuration
Allow defining multiple named pools in server.conf:
ifconfig-pool support 10.8.3.0 255.255.255.0 10.8.3.10-10.8.3.250
ifconfig-pool all 10.8.0.0 255.255.255.0 10.8.0.10-10.8.0.250
Where the syntax could be:
ifconfig-pool <name> <network> <netmask> [<start-ip>-<end-ip> | <size>]
If no explicit start/end range is given, the pool auto-calculates from the network.
Per-client pool selection
Add a new option for CCD files and client-auth config blocks:
# In CCD file:
ifconfig-pool "support"
# Or in client-auth config block sent via management interface:
ifconfig-pool "all"
When ifconfig-pool "name" is present instead of ifconfig-push, OpenVPN would:
- Look up the named pool
- Allocate the next free IP from that pool
- Track the allocation (including in the status file)
- Release on disconnect (same as the existing pool mechanism)
Priority/fallback behavior
- If a client has both
ifconfig-pool "name" in CCD and the server has a matching pool — use it.
- If the named pool doesn't exist or is exhausted — fall back to the default
--ifconfig-pool.
- If
ifconfig-push is also present — ifconfig-push takes precedence (backward compatibility).
Integration with client-auth (management interface)
This is especially important for OAuth2 flows. When openvpn-auth-oauth2 calls:
client-auth CID KID\n
ifconfig-pool "support"\n
END\n
OpenVPN would allocate from the support pool instead of the default one.
Benefits
- No code changes needed in auth plugins — the plugin already sends config blocks; it just needs the ability to specify a pool name instead of a hardcoded IP.
- Backward compatible — existing
--ifconfig-pool without a name becomes the default pool.
- Scales — multiple users in the same group each get a unique IP from their group's subnet.
- Integrates with status file, conflict detection, and pool tracking.
- CCD-friendly — group-level CCD files can use
ifconfig-pool "name" instead of per-user ifconfig-push.
Use Cases Beyond OAuth2 Groups
- RADIUS pools — RADIUS server could return a pool attribute (e.g.
Framed-Pool).
- Multi-tenant servers — different customers on the same OpenVPN instance get IPs from different subnets.
- Certificate-based — different certificate OUs could map to different pools via CCD.
Related
- openvpn-auth-oauth2 issue #896 — "Different IP pools per group" (feature request in the auth plugin, but the real limitation is in OpenVPN core)
Problem Statement
Modern OpenVPN deployments increasingly use external authentication — OAuth2/OIDC (openvpn-auth-oauth2), LDAP, RADIUS. Users authenticate and authorize via groups/roles, and each group needs its own IP subnet for:
Example use-case:
support10.8.3.0/24all(regular VPN)10.8.0.0/2410.8.0.0/24with per-user static IPCurrently OpenVPN supports only a single pool via
--serveror--ifconfig-pool. There is no mechanism to define multiple pools and dynamically select which pool to assign an IP from based on the client's group/role.Current Workarounds and Their Limitations
1. CCD + static IPs (
ifconfig-push)Each profile/group gets a CCD file with
ifconfig-push. However:2.
client-connectscript with external IPAMA custom script can maintain its own pool DB and issue
ifconfig-pushvia the management interface. Drawbacks:--ifconfig-pool.3.
client-auth(MDA) +ifconfig-pushWhen using the management interface (e.g. openvpn-auth-oauth2), the
client-authcommand can include a config block withifconfig-push. This works, but:4. Profile selector + per-profile static IPs (our current setup)
Our current setup:
/etc/openvpn-auth-oauth2/client-config/Access_VPN_all.conf— noifconfig-push, IP from the default pool/etc/openvpn-auth-oauth2/client-config/Access_VPN_support.conf—ifconfig-push 10.8.3.10ifconfig-push 10.8.3.12The CEL expression in openvpn-auth-oauth2 v2 correctly selects the config file based on Keycloak groups, but all users from the
supportgroup still get the same static IP. This is fine for our current scale, but it doesn't scale to multiple concurrent users per group without IP conflicts.Proposed Feature: Named
--ifconfig-poolpools with dynamic selectionServer configuration
Allow defining multiple named pools in
server.conf:Where the syntax could be:
If no explicit start/end range is given, the pool auto-calculates from the network.
Per-client pool selection
Add a new option for CCD files and
client-authconfig blocks:When
ifconfig-pool "name"is present instead ofifconfig-push, OpenVPN would:Priority/fallback behavior
ifconfig-pool "name"in CCD and the server has a matching pool — use it.--ifconfig-pool.ifconfig-pushis also present —ifconfig-pushtakes precedence (backward compatibility).Integration with
client-auth(management interface)This is especially important for OAuth2 flows. When openvpn-auth-oauth2 calls:
OpenVPN would allocate from the
supportpool instead of the default one.Benefits
--ifconfig-poolwithout a name becomes the default pool.ifconfig-pool "name"instead of per-userifconfig-push.Use Cases Beyond OAuth2 Groups
Framed-Pool).Related