import axios from 'axios'; import https from 'https'; export class OpnsenseService { private baseUrl: string; private apiKey: string; private apiSecret: string; private client: any; constructor(ipAddress: string, apiKey: string, apiSecret: string) { // Assuming HTTPS access to OPNsense, might need to adjust port if custom this.baseUrl = `https://${ipAddress}/api`; this.apiKey = apiKey; this.apiSecret = apiSecret; // OPNsense uses basic auth with API Key and Secret // We ignore SSL errors because OPNsense often has self-signed certs const httpsAgent = new https.Agent({ rejectUnauthorized: false }); this.client = axios.create({ baseURL: this.baseUrl, auth: { username: this.apiKey, password: this.apiSecret, }, httpsAgent, }); } /** * Health check to test API connectivity */ async testConnection(): Promise { try { // Fetching core firmware info as a simple ping const response = await this.client.get('/core/firmware/info'); return response.status === 200; } catch (error) { console.error('OPNsense API Connection Error:', error); return false; } } /** * Captive Portal: Add or update a voucher/user session * This allows the hotspot system to authenticate a user automatically via API */ async authHotspotUser(zoneId: string, username: string, ipAddress: string): Promise { try { // POST /api/captiveportal/session/connect/ const payload = { zoneid: zoneId, user: username, ip: ipAddress, }; // OPNsense expects URL encoded form data or specific JSON structure depending on the endpoint // Using generic captiveportal session connect endpoint const response = await this.client.post(`/captiveportal/session/connect`, payload); return response.data; } catch (error) { console.error('Error authenticating hotspot user:', error); throw new Error('Could not authenticate hotspot user on OPNsense'); } } /** * Captive Portal: Disconnect a user */ async disconnectHotspotUser(zoneId: string, sessionId: string): Promise { try { const payload = { zoneid: zoneId, sessionid: sessionId }; const response = await this.client.post(`/captiveportal/session/disconnect`, payload); return response.data; } catch (error) { console.error('Error disconnecting hotspot user:', error); throw new Error('Could not disconnect hotspot user on OPNsense'); } } /** * Traffic Shaper: Add a rule (e.g. for speed limits) */ async addShaperRule(ruleData: any): Promise { try { const response = await this.client.post('/trafficshaper/rule/addRule', { rule: ruleData }); // Apply the changes (shaper requires an explicit apply call) await this.client.post('/trafficshaper/service/reconfigure'); return response.data; } catch (error) { console.error('Error adding shaper rule:', error); throw new Error('Could not add traffic shaper rule on OPNsense'); } } }