1- import { AddClientResponse , RemoveClientResponse } from '../types/responses' ;
2- import { PeerClient } from "../types/peerClient" ;
3- import { SSHClient } from "./MikrotikSSHClient" ;
1+ import { AddClientResponse , RemoveClientResponse } from '../types/responses' ;
2+ import { PeerClient } from "../types/peerClient" ;
3+ import { SSHClient } from "./MikrotikSSHClient" ;
44import {
5- CLIENT_ADD_FAILED ,
6- CLIENT_ADD_SUCCESS ,
7- CLIENT_REMOVE_FAILED ,
8- CLIENT_REMOVE_SUCCESS ,
9- LIST_CLIENTS_ERROR , NO_CLIENTS_FOUND ,
10- PARSE_LISTEN_PORT_ERROR ,
11- PARSE_PUBLIC_KEY_ERROR ,
12- WIREGUARD_COMMANDS ,
13- WIREGUARD_FIELDS
5+ CLIENT_ADD_FAILED ,
6+ CLIENT_ADD_SUCCESS ,
7+ CLIENT_REMOVE_FAILED ,
8+ CLIENT_REMOVE_SUCCESS ,
9+ LIST_CLIENTS_ERROR , NO_CLIENTS_FOUND ,
10+ PARSE_LISTEN_PORT_ERROR ,
11+ PARSE_PUBLIC_KEY_ERROR ,
12+ WIREGUARD_COMMANDS ,
13+ WIREGUARD_FIELDS
1414} from "../config/constants" ;
1515
1616
1717export class MikroTikWireGuardClientManager {
18- private sshClient : SSHClient ;
19-
20- constructor ( sshClient : SSHClient ) {
21- this . sshClient = sshClient ;
22- }
23-
24- public async addClient ( publicKey : string , comment : string ) : Promise < AddClientResponse > {
25- try {
26- const clientAddress = await this . getNextAvailableIp ( ) ;
27- const command = WIREGUARD_COMMANDS . ADD_PEER ( comment , clientAddress , publicKey ) ;
28- await this . sshClient . executeCommand ( command ) ;
29-
30- const wireGuardInfo = await this . getWireGuardInterfaceInfo ( ) ;
31- return {
32- success : true ,
33- message : CLIENT_ADD_SUCCESS ,
34- config : {
35- clientAddress,
36- routerPublicKey : wireGuardInfo . publicKey ,
37- listenPort : wireGuardInfo . listenPort
38- }
39- } ;
40- } catch ( error ) {
41- return { success : false , message : CLIENT_ADD_FAILED } ;
18+ private sshClient : SSHClient ;
19+
20+ constructor ( sshClient : SSHClient ) {
21+ this . sshClient = sshClient ;
22+ }
23+
24+ public async addClient ( publicKey : string , comment : string ) : Promise < AddClientResponse > {
25+ try {
26+ const clientAddress = await this . getNextAvailableIp ( ) ;
27+ const command = WIREGUARD_COMMANDS . ADD_PEER ( comment , clientAddress , publicKey ) ;
28+ await this . sshClient . executeCommand ( command ) ;
29+
30+ const wireGuardInfo = await this . getWireGuardInterfaceInfo ( ) ;
31+ return {
32+ success : true ,
33+ message : CLIENT_ADD_SUCCESS ,
34+ config : {
35+ clientAddress,
36+ routerPublicKey : wireGuardInfo . publicKey ,
37+ listenPort : wireGuardInfo . listenPort
4238 }
39+ } ;
40+ } catch ( error ) {
41+ return { success : false , message : `${ CLIENT_ADD_FAILED } :${ error } ` } ;
4342 }
44-
45- public async removeClient ( publicKey : string ) : Promise < RemoveClientResponse > {
46- try {
47- const command = WIREGUARD_COMMANDS . REMOVE_PEER ( publicKey ) ;
48- await this . sshClient . executeCommand ( command ) ;
49- return { success : true , message : CLIENT_REMOVE_SUCCESS } ;
50- } catch ( error ) {
51- return { success : false , message : CLIENT_REMOVE_FAILED } ;
52- }
43+ }
44+
45+ public async removeClient ( publicKey : string ) : Promise < RemoveClientResponse > {
46+ try {
47+ const command = WIREGUARD_COMMANDS . REMOVE_PEER ( publicKey ) ;
48+ await this . sshClient . executeCommand ( command ) ;
49+ return { success : true , message : CLIENT_REMOVE_SUCCESS } ;
50+ } catch ( error ) {
51+ return { success : false , message : ` ${ CLIENT_REMOVE_FAILED } : ${ error } ` } ;
5352 }
53+ }
5454
55- public async listClients ( ) : Promise < PeerClient [ ] > {
56- try {
57- const command = WIREGUARD_COMMANDS . LIST_PEERS ;
58- const output = await this . sshClient . executeCommand ( command ) ;
55+ public async listClients ( ) : Promise < PeerClient [ ] > {
56+ try {
57+ const command = WIREGUARD_COMMANDS . LIST_PEERS ;
58+ const output = await this . sshClient . executeCommand ( command ) ;
5959
60- return this . parseWireGuardPeers ( output ) ;
61- } catch ( error ) {
62- throw new Error ( LIST_CLIENTS_ERROR ) ;
60+ return this . parseWireGuardPeers ( output ) ;
61+ } catch {
62+ throw new Error ( LIST_CLIENTS_ERROR ) ;
63+ }
64+ }
65+
66+ private parseWireGuardPeers ( output : string ) : PeerClient [ ] {
67+ const clients : PeerClient [ ] = [ ] ;
68+ const lines = output . split ( '\n' ) ;
69+ let currentComment = '' ;
70+ lines . forEach ( ( line ) => {
71+ const trimmedLine = line . trim ( ) ;
72+ if ( trimmedLine . startsWith ( ';;;' ) ) {
73+ currentComment = trimmedLine . slice ( 4 ) . trim ( ) ;
74+ } else if ( trimmedLine . length > 0 ) {
75+ const parts = trimmedLine . split ( / \s + / ) ;
76+ if ( parts . length >= 4 ) {
77+ clients . push ( {
78+ index : parts [ 0 ] ,
79+ interface : parts [ 1 ] ,
80+ publicKey : parts [ 2 ] ,
81+ allowedIp : parts [ 4 ] ,
82+ comment : currentComment ,
83+ } ) ;
6384 }
85+ }
86+ } ) ;
87+ return clients ;
88+ }
89+
90+ private async getWireGuardInterfaceInfo ( ) : Promise < { publicKey : string ; listenPort : number } > {
91+ const command = WIREGUARD_COMMANDS . GET_INTERFACE_INFO ;
92+ const output = await this . sshClient . executeCommand ( command ) ;
93+ const lines = output . split ( '\n' ) ;
94+ let publicKey = '' ;
95+ let listenPort = 0 ;
96+
97+ lines . forEach ( line => {
98+ const trimmedLine = line . trim ( ) ;
99+ if ( trimmedLine . includes ( WIREGUARD_FIELDS . PUBLIC_KEY ) ) {
100+ publicKey = trimmedLine . split ( WIREGUARD_FIELDS . PUBLIC_KEY ) [ 1 ] . replace ( / " / g, '' ) ;
101+ }
102+ if ( trimmedLine . includes ( WIREGUARD_FIELDS . LISTEN_PORT ) ) {
103+ listenPort = parseInt ( trimmedLine . split ( WIREGUARD_FIELDS . LISTEN_PORT ) [ 1 ] , 10 ) ;
104+ }
105+ } ) ;
106+
107+ if ( ! publicKey ) {
108+ throw new Error ( PARSE_PUBLIC_KEY_ERROR ) ;
64109 }
65-
66- private parseWireGuardPeers ( output : string ) : PeerClient [ ] {
67- const clients : PeerClient [ ] = [ ] ;
68- const lines = output . split ( '\n' ) ;
69- let currentComment = '' ;
70- lines . forEach ( ( line ) => {
71- const trimmedLine = line . trim ( ) ;
72- if ( trimmedLine . startsWith ( ';;;' ) ) {
73- currentComment = trimmedLine . slice ( 4 ) . trim ( ) ;
74- } else if ( trimmedLine . length > 0 ) {
75- const parts = trimmedLine . split ( / \s + / ) ;
76- if ( parts . length >= 4 ) {
77- clients . push ( {
78- index : parts [ 0 ] ,
79- interface : parts [ 1 ] ,
80- publicKey : parts [ 2 ] ,
81- allowedIp : parts [ 4 ] ,
82- comment : currentComment ,
83- } ) ;
84- }
85- }
86- } ) ;
87- return clients ;
110+ if ( ! listenPort ) {
111+ throw new Error ( PARSE_LISTEN_PORT_ERROR ) ;
88112 }
89113
90- private async getWireGuardInterfaceInfo ( ) : Promise < { publicKey : string ; listenPort : number } > {
91- const command = WIREGUARD_COMMANDS . GET_INTERFACE_INFO ;
92- const output = await this . sshClient . executeCommand ( command ) ;
93- const lines = output . split ( '\n' ) ;
94- let publicKey = '' ;
95- let listenPort = 0 ;
96-
97- lines . forEach ( line => {
98- const trimmedLine = line . trim ( ) ;
99- if ( trimmedLine . includes ( WIREGUARD_FIELDS . PUBLIC_KEY ) ) {
100- publicKey = trimmedLine . split ( WIREGUARD_FIELDS . PUBLIC_KEY ) [ 1 ] . replace ( / " / g, '' ) ;
101- }
102- if ( trimmedLine . includes ( WIREGUARD_FIELDS . LISTEN_PORT ) ) {
103- listenPort = parseInt ( trimmedLine . split ( WIREGUARD_FIELDS . LISTEN_PORT ) [ 1 ] , 10 ) ;
104- }
105- } ) ;
106-
107- if ( ! publicKey ) {
108- throw new Error ( PARSE_PUBLIC_KEY_ERROR ) ;
109- }
110- if ( ! listenPort ) {
111- throw new Error ( PARSE_LISTEN_PORT_ERROR ) ;
112- }
114+ return { publicKey, listenPort} ;
115+ }
113116
114- return { publicKey, listenPort} ;
117+ private async getNextAvailableIp ( ) : Promise < string > {
118+ const clients = await this . listClients ( ) ;
119+ const validClients = clients . filter ( client => client . allowedIp . includes ( '/' ) ) ;
120+ if ( validClients . length === 0 ) {
121+ throw new Error ( NO_CLIENTS_FOUND ) ;
115122 }
116123
117- private async getNextAvailableIp ( ) : Promise < string > {
118- const clients = await this . listClients ( ) ;
119- const validClients = clients . filter ( client => client . allowedIp . includes ( '/' ) ) ;
120- if ( validClients . length === 0 ) {
121- throw new Error ( NO_CLIENTS_FOUND ) ;
122- }
123-
124- const firstClientIp = validClients [ 0 ] . allowedIp . split ( '/' ) [ 0 ] ;
125- const subnet = validClients [ 0 ] . allowedIp . split ( '/' ) [ 1 ] ;
126- const baseIp = firstClientIp . split ( '.' ) . slice ( 0 , 3 ) . join ( '.' ) ;
127- const lastOctets = validClients . map ( client => parseInt ( client . allowedIp . split ( '.' ) [ 3 ] ) ) . sort ( ( a , b ) => a - b ) ;
128- const nextOctet = ( lastOctets [ lastOctets . length - 1 ] || 1 ) + 1 ;
124+ const firstClientIp = validClients [ 0 ] . allowedIp . split ( '/' ) [ 0 ] ;
125+ const subnet = validClients [ 0 ] . allowedIp . split ( '/' ) [ 1 ] ;
126+ const baseIp = firstClientIp . split ( '.' ) . slice ( 0 , 3 ) . join ( '.' ) ;
127+ const lastOctets = validClients . map ( client => parseInt ( client . allowedIp . split ( '.' ) [ 3 ] ) ) . sort ( ( a , b ) => a - b ) ;
128+ const nextOctet = ( lastOctets [ lastOctets . length - 1 ] || 1 ) + 1 ;
129129
130- return `${ baseIp } .${ nextOctet } /${ subnet } ` ;
131- }
132- }
130+ return `${ baseIp } .${ nextOctet } /${ subnet } ` ;
131+ }
132+ }
0 commit comments