Rev 16 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
# Program Overview: totp_opnsense Suite
This suite consists of four main programs/modules for managing TOTP and OpenVPN user access with OPNSense routers. Each has a distinct role in the workflow, from configuration management to user authentication and credential delivery.
---
## 1. configure
**Purpose:**
- Interactive tool for managing router configurations stored in `routers.json`.
- Allows adding, editing, and removing router definitions.
- Manages API credentials, VPN provider settings, and OpenVPN configuration formats.
**Key Features:**
- 3-space indentation and camelCase variable naming.
- Menu-driven interface for easy configuration management.
- Supports multiple OpenVPN configuration formats per router.
- Direct integration with OPNsense API to select VPN providers.
**Main Subroutines:**
- `usage`: Prints usage instructions.
- `readConfig`: Reads router configuration from JSON file.
- `writeConfig`: Writes router configuration to JSON file with proper permissions (0600, root-only).
- `trim`: Removes leading/trailing whitespace from strings.
- `menuSelect`: Displays interactive menu and captures user selection.
- `selectOvpnIndex`: Retrieves VPN provider list from router and allows selection.
- `editFormats`: Manages the formats hash for creating multiple OpenVPN configurations.
- `editRouter`: Main editor for router configuration fields.
**Formats Configuration:**
- Each format defines a unique OpenVPN configuration variant.
- Format structure: `{ "filename": "ROUTER_USER_format.ovpn", "additionalStrings": "proto tcp\\nport 443" }`
- ROUTER and USER placeholders in filename are replaced with actual values.
- `additionalStrings` supports `\n` for line breaks in configuration directives.
**Usage:**
```bash
./configure [configfile]
```
(defaults to `routers.json` in script directory if not specified)
---
## 2. index.php
**Purpose:**
- Web interface for users to authenticate and retrieve their TOTP QR code and OpenVPN configurations.
- Validates user credentials against password hashes stored in `users.json`.
- Displays QR codes, TOTP seeds, and provides download links for VPN configurations.
**Key Features:**
- 3-space indentation and camelCase variable naming for PHP code.
- Password verification using bcrypt hashes.
- Support for multiple OpenVPN configuration files per user.
- Router selection dropdown populated from available routers.
- Request refresh functionality for router data.
- Automatic logging of successful logins to `logs/` directory.
**Main Functionality:**
- Reads configuration from `users.json` generated by `opnsense-totp-ovpn-export`.
- Displays QR code image for TOTP setup.
- Shows TOTP seed for manual entry into authenticator apps.
- Provides download links for OpenVPN configuration files:
- Single file: displays one download link
- Multiple files: displays separate links for each configuration
- Logs successful authentication with timestamp, IP address, and username.
- Displays last update timestamp for selected router.
- Allows users to request router data refresh via web interface.
**Log Files:**
- Location: `./logs/log_YYYY-MM-DD.log`
- Format: `YYYY-MM-DD HH:MM:SS<tab>IP_ADDRESS<tab>Success<tab>USERNAME<tab>`
- Log directory created automatically if it doesn't exist.
**Refresh Mechanism:**
- See `updaterouters.cron` for an example of allowing users to request a rescan of a router.
- Refresh request creates a marker file in `/tmp` that cron job processes.
---
## 3. opnsense-totp-ovpn-export
**Purpose:**
- Connects to OPNsense router via API to retrieve user credentials and VPN configurations.
- Generates QR codes for TOTP authentication.
- Creates OpenVPN configuration files based on defined formats.
- Updates `users.json` with current user data.
**Key Features:**
- 3-space indentation and camelCase variable naming.
- Lock file mechanism prevents concurrent execution and data corruption.
- Clearly marked subroutine headers for maintainability.
- Uses `GD::Barcode::QRcode` for QR code generation.
- Uses `MIME::Base64` for decoding OpenVPN files from API.
- Supports multiple OpenVPN configuration formats per user.
**Main Subroutines:**
- `slurpFile`: Reads entire file contents into a string.
- `dumpFile`: Writes string contents to a file.
- `loadConfig`: Loads router configuration from JSON file (`routers.json`).
- `loadUsers`: Loads user data from JSON file (`users.json`).
- `saveUsers`: Saves user data to JSON file with proper structure.
- `makeQR`: Generates QR code image from TOTP seed and account information.
- `makeVPNConfigFile`: Creates OpenVPN configuration file with custom settings:
- Accepts filename template with ROUTER and USER placeholders
- Expands `\n` in additionalStrings to actual newlines
- Appends configuration directives to base VPN config
- Returns relative path to created file
- `cleanOldDataFiles`: Removes obsolete data files from previous runs.
**Format Processing:**
- Reads formats from `routers.json` for each router.
- Iterates through all defined formats to create multiple .ovpn files.
- Each format specifies:
- Filename template (e.g., `ROUTER_USER_tcp.ovpn`)
- Additional configuration strings (e.g., `proto tcp\nport 443`)
- Falls back to default single file if no formats defined.
- Stores result as array if multiple files, or string if single file.
**Lock File:**
- Location: `/tmp/opnsense.lock`
- Prevents concurrent execution.
- Retries: 6 attempts with 10-second intervals.
- Automatically removed on successful completion.
**Usage:**
```bash
./opnsense-totp-ovpn-export <routername>
```
Must be run as root.
---
## 4. opnsense.pm (Perl Module)
**Purpose:**
- Provides an object-oriented interface for interacting with the OPNSense API.
- Handles API requests using either curl or LWP::UserAgent, with SSL verification disabled for compatibility.
**Key Features:**
- 3-space indentation and camelCase variable naming.
- Clearly marked subroutine headers for maintainability.
- Flexible API request handling (curl or LWP).
**Main Subroutines:**
- `new`: Constructor for the Opnsense object.
- `apiRequest`: Dispatches API requests to curl or LWP handler.
- `apiRequestCurl`: Handles API requests using curl.
- `apiRequestLwp`: Handles API requests using LWP::UserAgent.
- `getVpnProviders`: Retrieves list of VPN providers from router.
- `getVpnUsers`: Gets VPN user certificates from router.
- `getAllUsers`: Retrieves all users with authentication data (including TOTP secrets).
- `getVpnConfig`: Exports VPN configuration file for a specific certificate.
---
## Datafile Structures
**user configuration file (users.json)**
- Contains sensitive information (TOTP codes and password hashes).
- Used by both `index.php` and `opnsense-totp-ovpn-export`.
- Should be owned by root with read access for web server.
- JSON structure:
```json
{
"router1": {
"qrLocationFileystem": "/file/system/path/to/qrcode/directory",
"qrLocation": "./qrcodes",
"ovpnLocationFileSystem": "/file/system/path/to/ovpn/directory",
"ovpnLocation": "./openvpn_configs",
"lastUpdate": 1759817343,
"users": {
"user1": {
"password": "<bcrypt hashed password>",
"otp_seed": "<TOTP seed in base32>",
"certs": ["cert-id-1"],
"qrFile": "./qrcodes/router1_user1.png",
"ovpnFile": "./openvpn_configs/router1_user1.ovpn"
},
"user2": {
"password": "<bcrypt hashed password>",
"otp_seed": "<TOTP seed in base32>",
"certs": ["cert-id-2"],
"qrFile": "./qrcodes/router1_user2.png",
"ovpnFile": [
"./openvpn_configs/router1_user2_tcp.ovpn",
"./openvpn_configs/router1_user2_udp.ovpn"
]
}
}
},
"router2": {
...
}
}
```
**Note on ovpnFile:**
- Can be a string (single configuration file) or array (multiple configuration files).
- Multiple files are automatically displayed as separate download links in web interface.
**router configuration file (routers.json)**
- Contains apiSecret and apiKey that provide access to router management.
- Owned by root with permissions 0600 (root-only access).
- JSON structure:
```json
{
"routername": {
"url": "https://192.168.1.1",
"apiKey": "public API key from OPNsense Router",
"apiSecret": "secret API key from OPNsense Router",
"ovpnIndex": "1",
"template": "PlainOpenVPN",
"hostname": "router.example.org",
"localPort": "1194",
"downloadToken": "random-token-string",
"formats": {
"tcp": {
"filename": "ROUTER_USER_tcp.ovpn",
"additionalStrings": "proto tcp\\nport 443\\nauth-nocache"
},
"udp": {
"filename": "ROUTER_USER_udp.ovpn",
"additionalStrings": "proto udp\\nport 1194\\nauth-nocache"
},
"tcp-alt": {
"filename": "ROUTER_USER_tcp_alt.ovpn",
"additionalStrings": "proto tcp\\nport 8443\\nauth-nocache"
}
}
}
}
```
**Configuration Fields:**
- `url`: Router management URL (how scripts connect).
- `apiKey` / `apiSecret`: API credentials from OPNsense.
- `ovpnIndex`: VPN provider index (single digit in older systems, long hash in newer versions).
- `template`: OpenVPN template type (typically "PlainOpenVPN").
- `hostname`: Hostname written to .ovpn files (external VPN endpoint).
- `localPort`: Port number written to .ovpn files (can be overridden by format strings).
- `downloadToken`: Authentication token for download requests.
- `formats`: Hash of configuration format definitions:
- Key: Format identifier (e.g., "tcp", "udp", "tcp-alt")
- Value: Hash with `filename` template and `additionalStrings` for configuration directives
---
# Workflow Summary
1. **Initial Setup:**
- Obtain API key and secret from OPNsense router (System → Access → Users).
- Run `./configure` to set up router configuration.
- Define OpenVPN formats if multiple configurations needed.
2. **Data Export:**
- Run `./opnsense-totp-ovpn-export routername` to:
- Connect to router via API
- Retrieve user credentials and TOTP secrets
- Generate QR code images
- Create OpenVPN configuration files for all formats
- Update `users.json`
3. **User Access:**
- Users navigate to `index.php` web interface.
- Log in with username, password, and router selection.
- View QR code for TOTP setup (first time).
- Download OpenVPN configuration file(s).
- Import .ovpn file into OpenVPN client.
4. **Automated Updates:**
- Set up cron job to run `opnsense-totp-ovpn-export` periodically.
- Users can request on-demand refresh via web interface.
- See `updaterouters.cron` for implementation example.
---
# Security Note
All scripts treat OTP secrets and user data as sensitive information:
- **Router configuration:** Root-only access (0600 permissions).
- **User configuration:** Root-owned, world-readable for web server.
- **QR codes:** Pre-generated and stored on filesystem (consider access restrictions).
- **Passwords:** Hashed using bcrypt with cost factor 10-11.
- **API credentials:** Stored in protected configuration file.
- **Logs:** Record successful authentication attempts with timestamps and IP addresses.
**Recommendations:**
- Host system on secure internal network or behind firewall.
- Use HTTPS for web interface.
- Implement web server access controls (.htaccess, IP restrictions).
- Regularly review access logs.
- Use dedicated API keys with minimal required permissions.
- Consider implementing rate limiting for login attempts.
---
# Version Information
- **configure:** v1.1.0
- **opnsense-totp-ovpn-export:** v1.1.0
- **index.php:** v1.3.0
- **opnsense.pm:** (see module for version)
See individual script headers for detailed version history and changes.