94 lines
2.3 KiB
Markdown
94 lines
2.3 KiB
Markdown
|
|
Connection Flow with MAC Validation
|
|||
|
|
|
|||
|
|
Client starts OpenVPN
|
|||
|
|
|
|||
|
|
The user runs their .ovpn config, which includes:
|
|||
|
|
|
|||
|
|
auth-user-pass (username & password prompt or file).
|
|||
|
|
|
|||
|
|
TLS client certificate.
|
|||
|
|
|
|||
|
|
OpenVPN receives login request
|
|||
|
|
|
|||
|
|
The OpenVPN server (server.conf) is configured with:
|
|||
|
|
|
|||
|
|
auth-user-pass-verify /etc/openvpn/access/auth.py via-env
|
|||
|
|
|
|||
|
|
|
|||
|
|
This tells OpenVPN: “When a client logs in, call my Python script and pass credentials via environment variables.”
|
|||
|
|
|
|||
|
|
Access Server (auth.py) is executed
|
|||
|
|
|
|||
|
|
OpenVPN sets environment variables like:
|
|||
|
|
|
|||
|
|
username (VPN login username)
|
|||
|
|
|
|||
|
|
password (VPN login password)
|
|||
|
|
|
|||
|
|
untrusted_ip (client’s source IP)
|
|||
|
|
|
|||
|
|
common_name (from client certificate)
|
|||
|
|
|
|||
|
|
But MAC address is not included by default.
|
|||
|
|
|
|||
|
|
To enforce MAC binding, your .ovpn client config must also send the local MAC address (e.g., using --push-peer-info and setenv).
|
|||
|
|
|
|||
|
|
Example in client config:
|
|||
|
|
|
|||
|
|
setenv CLIENT_MAC 00:11:22:33:44:55
|
|||
|
|
|
|||
|
|
|
|||
|
|
→ This will be available to the server script as an environment variable CLIENT_MAC.
|
|||
|
|
|
|||
|
|
Validation logic in auth.py
|
|||
|
|
|
|||
|
|
auth.py looks up the username in MySQL.
|
|||
|
|
|
|||
|
|
It checks:
|
|||
|
|
|
|||
|
|
Password hash ✅
|
|||
|
|
|
|||
|
|
Registered MAC address = CLIENT_MAC ✅
|
|||
|
|
|
|||
|
|
If both match → return exit code 0 (success).
|
|||
|
|
|
|||
|
|
If mismatch → return exit code 1 (deny).
|
|||
|
|
|
|||
|
|
Session Management (session.py)
|
|||
|
|
|
|||
|
|
When client successfully connects, OpenVPN can run another script using client-connect directive:
|
|||
|
|
|
|||
|
|
client-connect /etc/openvpn/access/session.py
|
|||
|
|
client-disconnect /etc/openvpn/access/session.py
|
|||
|
|
|
|||
|
|
|
|||
|
|
This allows you to:
|
|||
|
|
|
|||
|
|
Record session start in DB.
|
|||
|
|
|
|||
|
|
Start a background timer to enforce max session time.
|
|||
|
|
|
|||
|
|
On disconnect, update DB session table.
|
|||
|
|
|
|||
|
|
Decision
|
|||
|
|
|
|||
|
|
If validation fails → OpenVPN rejects the connection.
|
|||
|
|
|
|||
|
|
If validation passes → OpenVPN allows the tunnel, assigns IP, and routes traffic.
|
|||
|
|
|
|||
|
|
🔧 Example Interaction Setup in server.conf
|
|||
|
|
auth-user-pass-verify /etc/openvpn/access/auth.py via-env
|
|||
|
|
client-connect /etc/openvpn/access/session.py
|
|||
|
|
client-disconnect /etc/openvpn/access/session.py
|
|||
|
|
script-security 3
|
|||
|
|
|
|||
|
|
📝 Summary
|
|||
|
|
|
|||
|
|
OpenVPN triggers your Python scripts at authentication and session events.
|
|||
|
|
|
|||
|
|
Your scripts validate MAC + user credentials against MySQL.
|
|||
|
|
|
|||
|
|
Session time control is also handled by your scripts (client-connect + client-disconnect).
|
|||
|
|
|
|||
|
|
OpenVPN itself doesn’t know about MAC/time limits → it just calls your scripts, and your logic decides allow or deny.
|