Dynamic VPN IP Allocation by Certificate CN for User-Based Segmentation in OPNse

Started by Enzo42, April 24, 2025, 09:56:22 AM

Previous topic - Next topic
Hello everyone,

I am facing a specific issue on OPNsense and would appreciate your advice on how to resolve it.

Context 
Public IP for IPsec: 51.68.xxx.xxx 
Authentication method: EAP-TLS (each client has a unique certificate, CN = username) 
Current address pool: 10.10.700.0/29 
Internal services: 
Service2: 192.168.1.2 
Service3: 192.168.1.3 
Service4: 192.168.1.4 
Service5: 192.168.1.5 
Service6: 192.168.1.6 

Users 
user1, user2, user3, user4, user5, user6 

Teams and desired access 
Team A (user1, user2) – access only to Service2 & Service3 
Team B (user3, user4) – access only to Service4 & Service5 
Team C (user5)     – access only to Service6 

Current IPsec configuration 
    # This file is automatically generated. Do not edit 
    connections { 
        9e8eb885-b8d2-41f3-b967-1488102d1ebb { 
            proposals = aes256-sha256-modp2048 
            unique = no 
            version = 2 
            mobike = yes 
            local_addrs = 51.68.xxx.xxx 
            pools = ORG-VPN-POOL 
            send_certreq = yes 
            send_cert = always 
            local-36522477-dc3a-43a3-99e8-66b53952755d { 
                auth = pubkey 
                certs = 680256ff7d9b7.crt 
            } 
            remote-63a85f32-c1bd-4db4-8851-7cb1f167918c { 
                auth = eap-tls 
                eap_id = %any 
            } 
            children { 
                0fba29e9-8d1a-452e-a17d-a7b566b7d80f { 
                    mode = tunnel 
                    local_ts = 192.168.1.0/24 
                    remote_ts = 10.10.700.0/29 
                    esp_proposals = aes256-sha256-modp2048 
                    updown = /usr/local/opnsense/scripts/ipsec/updown_event.py --connection_child 0fba29e9-8d1a-452e-a17d-a7b566b7d80f 
                } 
            } 
        } 
        301d809e-7159-471e-b7bd-9997251b9869 { 
            local_addrs = 37.59.xxx.xxx 
            pools = user5-soho 
            remote-71bd5822-155f-4b8f-b268-6774672ff40c { 
                auth = eap-tls 
                eap_id = user5 
            } 
            children { 
                cd06cb63-ed58-48e9-9f58-dccc65694b6c { 
                    local_ts = 192.168.1.8/32 
                    remote_ts = 10.10.700.10 
                    updown = /usr/local/opnsense/scripts/ipsec/updown_event.py --connection_child cd06cb63-ed58-48e9-9f58-dccc65694b6c 
                } 
            } 
        } 
    } 
    pools { 
        ORG-VPN-POOL { 
            addrs = 10.10.700.0/29 
            dns   = 192.168.1.1 
        } 
        User5-soho { 
            addrs = 10.10.700.10/32 
            dns   = 192.168.1.1 
        } 
    } 

Non-scalable attempt 
Tested solution: duplicating the IPsec connection on the same or different public IP for each user, with a /32 pool and a targeted remote_ts. 
Drawbacks: 
1. If the first connection fails on the same IP, the client never fails over to the second. 
2. Requires one IPsec connection per user → not viable at scale. 

Main objective 
On a single IPsec connection (51.68.xxx.xxx): 
1. Dynamically assign the VPN IP address based on the certificate CN (one unique IP per user, or from a shared sub-pool). 
2. Then apply firewall rules (aliases, groups) to grant each user access to the appropriate services. 

Questions 
1. Mapping CN → IP address 
   Is there a native IPsec feature or an OPNsense plugin to map the EAP-TLS certificate CN to a specific VPN IP or to different ranges within the same pool? 
2. Firewall filtering 
   Once the IP is assigned dynamically, how can I expose the CN or a RADIUS attribute to the firewall rules to create aliases/groups and restrict service access? 
3. RADIUS / ACL integration 
   Can a RADIUS server or an OPNsense module push attributes (VSAs) to define the IP and Phase 2 TS per user? 
   What best practices or pitfalls (updown scripts, VTI, rekeying, etc.) should I be aware of for implementing this dynamic segmentation? 

Thank you in advance for your advice and feedback!

Best regards, 
Enzo