const { Client } = require( 'ssh2' );
const fs = require( 'fs' );
+const net = require( 'net' );
+const util = require( 'util' );
+const exec = require( 'child_process' ).execSync;
+const execPromise = util.promisify(exec);
/**
*
next( error );
} ).connect( sshConfig );
},
- getAvailableClients:async ( req, res, next ) => {
+ getAvailableClients: async ( req, res, next ) => {
const conn = new Client();
conn.on( 'ready', () => {
const commands = [
next( error );
} ).connect( sshConfig );
},
- getClients:async ( req, res, next ) => {
+ getClients: async ( req, res, next ) => {
const conn = new Client();
conn.on( 'ready', () => {
const command = `cat /var/log/openvpn/openvpn-status.log`;
const error = new createError( 500, `SSH connection failed: ${ err.message }` );
next( error );
} ).connect( sshConfig );
+ },
+ disconnect: async ( req, res, next ) => {
+ const { clientName, duration } = req.body; // duration in minutes
+ if (!clientName) {
+ return next(new createError(400, 'Client name required'));
+ }
+
+ try {
+ // Read from the OpenVPN status log to get the client's real IP
+ const statusContent = fs.readFileSync('/var/log/openvpn/openvpn-status.log', 'utf8');
+ let clientIp = null;
+ const clientLine = statusContent.split('\n').find(line =>
+ line.startsWith(`${clientName},`) && !line.startsWith('Virtual Address')
+ );
+ if (clientLine) {
+ const [, realAddress] = clientLine.split(',');
+ clientIp = realAddress.split(':')[0];
+ } else {
+ return next(new createError(404, `Client ${clientName} not connected`));
+ }
+
+ // Disconnect client via management interface
+ const client = new net.Socket();
+ client.connect(7505, 'localhost', () => {
+ logger.info('Connected to OpenVPN management interface');
+ client.write(`client-kill ${clientName}\n`);
+ });
+
+ client.on('data', async (data) => {
+ const response = data.toString();
+ if (response.includes('SUCCESS: client-kill command succeeded')) {
+ if (duration && clientIp) {
+ // Add iptables rule to block client IP for duration
+ const conn = new Client();
+ conn.on('ready', () => {
+ const commands = [
+ `sudo iptables -A INPUT -s ${clientIp} -p tcp --dport 1194 -j DROP`,
+ `sleep ${duration * 60} && sudo iptables -D INPUT -s ${clientIp} -p tcp --dport 1194 -j DROP &`,
+ ];
+ conn.exec(commands.join(' && '), (err, stream) => {
+ if (err) {
+ conn.end();
+ client.destroy();
+ return next(new createError(500, `IPTables command failed: ${err.message}`));
+ }
+ stream.on('close', (code) => {
+ conn.end();
+ client.destroy();
+ if (code === 0) {
+ res.json({ message: `Client ${clientName} disconnected for ${duration} minutes` });
+ } else {
+ next(new createError(500, `IPTables command failed`));
+ }
+ });
+ });
+ }).on('error', (err) => {
+ client.destroy();
+ next(new createError(500, `SSH connection failed: ${err.message}`));
+ }).connect(sshConfig);
+ } else {
+ client.destroy();
+ res.json({ message: `Client ${clientName} disconnected` });
+ }
+ } else {
+ client.destroy();
+ next(new createError(500, `Failed to disconnect client: ${response}`));
+ }
+ });
+
+ client.on('error', (err) => {
+ client.destroy();
+ next(new createError(500, `Management interface connection failed: ${err.message}`));
+ });
+ } catch (error) {
+ next(new createError(500, `Failed to process disconnection: ${error.message}`));
+ }
+ },
+ getStatus: async ( req, res, next ) => {
+ try {
+ const { stdout } = await execPromise('systemctl is-active openvpn@server');
+ res.json({ status: stdout.trim() });
+ } catch (error) {
+ return next(new createError(500, `Failed to check VPN status: ${error.message}`));
+ }
+ },
+ restart: async ( req, res, next ) => {
+ try {
+ await execPromise('systemctl restart openvpn@server');
+ res.json({ message: 'VPN restarted successfully' });
+ } catch (error) {
+ return next(new createError(500, `Failed to restart VPN: ${error.message}`));
+ }
}
};
\ No newline at end of file