Dall'outsourcing allo sviluppo (Parte 1)

Ciao a tutti, mi chiamo Sergey Emelyanchik. Sono il direttore dell'azienda Audit-Telecom, il principale sviluppatore e l'autore del sistema Veliam. Ho deciso di scrivere un articolo su come io e un amico abbiamo creato un'azienda di outsourcing, abbiamo sviluppato software per noi stessi e successivamente abbiamo iniziato a distribuirlo a chiunque fosse interessato tramite un sistema SaaS. Parlerò di come non credevo assolutamente che fosse possibile. Nell'articolo non ci sarà solo una narrazione, ma anche dettagli tecnici su come è stato creato il prodotto Veliam, comprese alcune parti del codice sorgente. Racconterò quali errori abbiamo commesso e come li abbiamo poi corretti. Ho avuto dei dubbi se pubblicare un articolo del genere. Ma ho pensato che fosse meglio farlo, ricevere feedback e migliorare, piuttosto che non pubblicare l'articolo e pensare a cosa sarebbe successo se…

Antefatti

Ho lavorato in un'azienda come dipendente IT. L'azienda era piuttosto grande con una rete molto articolata. Non mi soffermerò sulle mie mansioni, dirò solo che tra di esse non c'era sicuramente lo sviluppo di alcunché.

Avevamo un monitoraggio, ma per puro interesse accademico volevo provare a scrivere il mio monitoraggio basico. L'idea era di creare un'applicazione web per poter accedere facilmente a ciò che accadeva nella rete da qualsiasi dispositivo, incluso un dispositivo mobile tramite Wi-Fi, e volevo anche capire rapidamente in quale stanza si trovava l'attrezzatura che aveva problemi, poiché c'erano requisiti molto severi per i tempi di risposta a tali problemi. Così, alla fine, ho formulato un piano per scrivere una semplice pagina web, con uno sfondo jpeg del diagramma di rete, ritagliando gli apparecchi con i loro indirizzi IP su questa immagine e sovrapponendo contenuti dinamici sui giusti punti di coordinata come indirizzi IP verdi o rossi lampeggianti. Obiettivo fissato, iniziamo.

In passato mi sono occupato di programmazione in Delphi, PHP, JS e molto superficialmente C++. Conosco piuttosto bene il funzionamento delle reti. VLAN, Routing (OSPF, EIGRP, BGP), NAT. Questo era sufficiente per scrivere un prototipo di monitoraggio primitivo da solo.

Ho scritto quanto avevo in mente in PHP. Il server Apache e PHP erano su Windows, poiché Linux, per me, era qualcosa di completamente sconosciuto e molto complicato. Come si è scoperto più tardi, mi sbagliavo di grosso e in molti aspetti Linux è molto più semplice di Windows, ma questo è un argomento a parte e sappiamo tutti quanti dibattiti ci siano su questo tema. Il Task Scheduler di Windows eseguiva a intervalli brevi (non ricordo esattamente, ma qualcosa come una volta ogni tre secondi) uno script PHP che interrogava tutti gli oggetti con un semplice ping e salvava lo stato in un file.

system("ping -n 3 -w 100 {$ip_address}"); 

Sì, sì, all'epoca anche lavorare con i database era per me un'arte sconosciuta. Non sapevo che fosse possibile parallelizzare i processi, e il passaggio attraverso tutti i nodi della rete richiedeva molto tempo, poiché avveniva in un unico thread. I problemi maggiori si presentavano quando diversi nodi erano irraggiungibili, poiché ciascuno di essi bloccava lo script per 300 ms. Dall'altra parte, sul client, c'era una semplice funzione ciclica che ogni pochi secondi scaricava informazioni aggiornate dal server tramite una richiesta Ajax e aggiornava l'interfaccia. E dopo tre ping non riusciti consecutivi, se sul computer era aperta una pagina web con il monitoraggio, suonava una melodia allegra.

Quando ho visto i risultati, sono stato molto ispirato e ho pensato che potessi aggiungere ancora (in base alle mie conoscenze e capacità). Tuttavia, non mi sono mai piaciuti i sistemi con milioni di grafici, che, come allora e tuttora considero, nella maggior parte dei casi sono inutili. Volevo integrare solo ciò che effettivamente mi avrebbe aiutato nel lavoro. Questo principio rimane tutt'oggi fondamentale nello sviluppo di Veliam. Inoltre, ho capito che sarebbe stato fantastico se non fosse stato necessario tenere aperto il monitoraggio e sapere dei problemi; e quando si verificavano, aprire la pagina e vedere dove si trovava quel nodo problematico e cosa fare dopo. Non leggevo l'email, semplicemente non la usavo. Ho scoperto su internet che esistono gateway SMS, ai quali posso inviare richieste GET o POST, e mi invieranno un SMS sul cellulare con il testo che scrivo. Ho subito capito che lo desideravo tantissimo. E ho iniziato a studiare la documentazione. Dopo un po' di tempo ci sono riuscito e ora ricevevo SMS sui problemi della rete sul cellulare con il nome dell'"oggetto caduto". Anche se il sistema era primitivo, l'ho scritto io stesso e la cosa più importante che mi ha motivato a svilupparlo è stata che si trattava di un'applicazione pratica che mi aiutava realmente nel lavoro.

E così arrivò il giorno in cui uno dei canali internet al lavoro è caduto e il mio monitoraggio non me ne ha dato alcun segnale. Poiché i DNS di Google pingavano ancora ottimamente. È arrivato il momento di pensare a come monitorare se il canale di comunicazione fosse attivo. Ci sono state diverse idee su come farlo. Non avevo accesso a tutta l'attrezzatura. Dovevo inventare un modo per capire quale dei canali fosse vivo, ma senza avere la possibilità di controllarlo direttamente sull'attrezzatura di rete. Allora un collega mi ha suggerito l'idea che la traccia fino ai server pubblici potesse variare a seconda del canale di comunicazione utilizzato per connettersi a internet. Ho controllato ed era proprio così. C'erano diversi percorsi durante la traccia.

system(“tracert -d -w 500 8.8.8.8”);

Così è apparso un altro script, o meglio, la tracciatura è stata aggiunta alla fine dello stesso script, che pingava tutti i dispositivi nella rete. Infatti, si trattava di un altro processo lungo che veniva eseguito nello stesso thread e rallentava il funzionamento dell'intero script. Ma allora non era così ovvio. In ogni caso, faceva il suo lavoro, nel codice era specificato rigidamente quale doveva essere la tracciatura per ciascuno dei canali. Così è iniziato a funzionare un sistema che monitorava (è un modo di dire, poiché non c'era raccolta di metriche, ma solo ping) i dispositivi di rete (router, switch, Wi-Fi, ecc.) e i canali di comunicazione con il mondo esterno. SMS venivano ricevuti regolarmente e nello schema era sempre ben visibile dove si trovava il problema.

In seguito, nel lavoro quotidiano, mi sono trovato a fare cross-checking. E ogni volta dovevo accedere agli switch Cisco per vedere quale interfaccia fosse necessario utilizzare, era stancante. Sarebbe stato fantastico cliccare sulla monitorizzazione su un oggetto e vedere un elenco delle sue interfacce con le descrizioni. Questo mi avrebbe fatto risparmiare tempo. Inoltre, in questo schema non sarebbe stato necessario avviare Putty o SecureCRT, inserire credenziali e comandi. Basta cliccare sulla monitorizzazione, vedere cosa serve e andare a svolgere il proprio lavoro. Ho iniziato a cercare come interagire con gli switch. A colpo d'occhio, ho trovato due opzioni: SNMP o accedere allo switch tramite SSH, inserire i comandi necessari e analizzare il risultato. Ho scartato SNMP per la complessità di implementazione, non vedevo l'ora di ottenere un risultato. Con SNMP avrei dovuto approfondire il MIB a lungo e, sulla base di questi dati, generare informazioni sulle interfacce. Esiste un fantastico comando in CISCO

show interface status

Mostra proprio ciò di cui ho bisogno per il monitoring. Perché soffrire con SNMP, quando voglio solo vedere l'output di questo comando, ho pensato. Dopo un po', ho implementato questa funzionalità. Cliccavo sull'oggetto nella pagina web. Si attivava un evento che utilizzava AJAX per inviare una richiesta al server, che a sua volta si collegava via SSH allo switch di cui avevo bisogno (le credenziali erano hardcoded nel codice, non avevo voglia di rendere tutto più elegante creando menu separati per modificare le credenziali dall'interfaccia, avevo bisogno di un risultato e in fretta) inseriva il comando sopra menzionato e restituiva i dati al browser. Così ho iniziato a vedere con un semplice clic le informazioni sulle interfacce. Era estremamente comodo, specialmente quando dovevo visualizzare queste informazioni su diversi switch contemporaneamente.

Alla fine, il monitoraggio dei canali basato sul tracing si è rivelato non essere la migliore idea, poiché a volte venivano eseguiti lavori sulla rete, e il tracing poteva cambiare, iniziando a farmi sentire che c'erano problemi con il canale. Dopo aver speso molto tempo ad analizzare, capivo che tutti i canali funzionavano, mentre il mio monitoraggio mi ingannava. Così ho chiesto ai colleghi che gestivano gli switch che formavano i canali di inviarmi semplicemente il syslog quando cambiava lo stato di visibilità dei vicini. Questo era molto più semplice, veloce e veritiero rispetto al tracing. Ricevevo eventi del tipo 'neighbor lost', e subito attivavo un avviso per la caduta del canale.

In seguito, ci sono stati ulteriori output su clic sugli oggetti di alcuni altri comandi e ho aggiunto SNMP per raccogliere alcune metriche, e questo è tutto. Il sistema non si è sviluppato oltre. Faceva tutto ciò di cui avevo bisogno, era un buon strumento. Molti lettori possono dirmi che esistono già molti software online per risolvere questi problemi. Ma in realtà, a quel tempo non riuscivo a trovare prodotti gratuiti simili e avevo una grande voglia di migliorare le mie competenze di programmazione, e cosa può spingere meglio in questa direzione se non una vera sfida pratica. Con ciò, la prima versione del monitoraggio si è conclusa e non è stata ulteriormente modificata.

Creazione dell'azienda Audit-Telecom

Col passare del tempo, ho iniziato a lavorare anche per altre aziende, visto che il mio orario di lavoro me lo permetteva. Lavorando in diverse aziende, le competenze in vari settori crescono rapidamente e si amplia la propria visione. Ci sono aziende in cui, come si suol dire, sei sia sarto, che mietitore, e suoni la pipa. Da un lato è complicato, dall'altro, se non sei pigro, diventi un professionista a tutto tondo e questo ti consente di risolvere le problematiche in modo più rapido ed efficace, perché sai come funziona l'area adiacente.

Il mio amico Pavel (anche lui nel settore IT) ha sempre cercato di spingermi verso un'attività autonoma. Ci sono state innumerevoli idee con vari tipi di business. Ne abbiamo parlato per anni. E alla fine non si è concretizzato nulla, perché io sono scettico e Pavel è un sognatore. Ogni volta che proponeva qualche idea, io non ci credevo mai e rifiutavo di partecipare. Ma ci tenevamo davvero ad avviare un'attività nostra.

Alla fine, siamo riusciti a trovare una soluzione che soddisfacesse entrambi e a dedicarci a ciò che sappiamo fare. Nel 2016, abbiamo deciso di creare un'azienda IT che aiutasse le imprese nella risoluzione di problematiche IT. Questo include l'implementazione di sistemi IT (1C, server terminali, server email, ecc.), il loro supporto, un classico HelpDesk per gli utenti e l'amministrazione della rete.

A dire il vero, nel momento in cui abbiamo creato l'azienda, non ci credevo praticamente per il 99,9%. Ma in qualche modo Pavel è riuscito a convincermi a provare, e per fortuna aveva ragione. Io e Pavel abbiamo investito 300.000 rubli ciascuno, abbiamo registrato una nuova LLC "Audit-Telecom", affittato un minuscolo ufficio, fatto delle belle visite, insomma, come fa probabilmente la maggior parte dei giovani imprenditori inesperti, e abbiamo iniziato a cercare clienti. La ricerca di clienti è tutta un'altra storia. Forse scriveremo un articolo a parte per il blog aziendale, se a qualcuno interessa. Chiamate a freddo, volantini e tutto il resto. Non abbiamo ottenuto risultati. Come leggo ora in molte storie aziendali, in un modo o nell'altro molto dipende dalla fortuna. A noi è andata bene, e letteralmente dopo un paio di settimane dalla creazione della ditta, mio fratello Vladimir si è rivolto a noi, portandoci il primo cliente. Non voglio annoiarvi con i dettagli del lavoro con i clienti, l'articolo non parla di questo; dico solo che siamo andati a una consulenza, abbiamo identificato i punti critici e questi punti sono crollati mentre si decisionava se collaborare con noi in modo continuativo come fornitori di servizi esternalizzati. Dopo ciò è stata presa subito una decisione positiva.

In seguito, principalmente attraverso il passaparola tra conoscenti, hanno iniziato a comparire altre aziende da servire. Il servizio di assistenza era in una sola sistema. Le connessioni all'hardware di rete e ai server in un'altra, più precisamente a seconda di chi come. Qualcuno salvava collegamenti, qualcun altro utilizzava rubriche RDP. Il monitoraggio era un altro sistema distinto. Lavorare per il team in sistemi disconnessi è molto scomodo. Si perde di vista informazioni importanti. Ad esempio, se diventa non disponibile il server terminale di un cliente, subito arrivano richieste dagli utenti di quel cliente. Lo specialista del supporto apre una richiesta (che è arrivata per telefono). Se gli incidenti e le richieste fossero registrati in un unico sistema, lo specialista del supporto vedrebbe subito qual è il problema dell'utente e glielo comunicerebbe, mentre si collega già all'oggetto necessario per gestire la situazione. Tutti sono a conoscenza della situazione tattica e lavorano coordinati. Non abbiamo trovato un sistema che unisse tutto questo. È diventato chiaro che era il momento di sviluppare il nostro prodotto.

Proseguimento del lavoro sul nostro sistema di monitoraggio

Era chiaro che il sistema precedentemente scritto non era affatto adatto alle attuali esigenze, né per quanto riguarda le funzionalità né per la qualità. Pertanto, si è deciso di sviluppare un sistema da zero. Graficamente, doveva apparire completamente diverso. Doveva essere un sistema gerarchico, in modo da poter aprire rapidamente e facilmente l'oggetto necessario per il cliente specifico. Lo schema della prima versione non era assolutamente giustificato in questo caso, poiché i clienti erano diversi e non importava in quali stanze fosse posizionato l'equipaggiamento. Questo era già stato affidato alla documentazione.

Quindi, i compiti:

  1. Struttura gerarchica;
  2. Una sorta di parte server che può essere posizionata presso il cliente sotto forma di macchina virtuale per raccogliere le metriche necessarie e inviarle al server centrale, che le riassumerà e ci mostrerà;
  3. Notifiche. Di quelle che non possono essere trascurate, poiché a quel tempo non c'era possibilità per qualcuno di rimanere solo a guardare il monitor;
  4. Sistema di ticket. Iniziarono a comparire clienti per i quali gestivamo non solo attrezzature server e di rete, ma anche stazioni di lavoro;
  5. Possibilità di connettersi rapidamente ai server e all'equipaggiamento dal sistema;

I compiti sono stati fissati, iniziamo a scrivere. Nel frattempo, gestiamo le richieste dei clienti. A quel tempo eravamo già in quattro. Iniziammo a scrivere subito entrambe le parti, sia il server centrale che il server da installare presso i clienti. A questo punto, Linux non ci era già estraneo e si decise che le macchine virtuali che sarebbero state utilizzate dai clienti sarebbero state basate su Debian. Non ci saranno installatori, realizzeremo semplicemente il progetto della parte server su una specifica macchina virtuale e poi la cloneremo per il cliente specifico. Questo si rivelò essere un altro errore. In seguito, divenne chiaro che in tale schema il meccanismo di aggiornamento non era affatto elaborato. Vale a dire, aggiungemmo una nuova funzionalità e poi ci fu un vero problema nel distribuirla a tutti i server dei clienti, ma ne riparleremo più avanti, tutto a suo tempo.

Abbiamo realizzato il primo prototipo. Era in grado di pingare i dispositivi di rete e i server dei clienti e inviare questi dati al nostro server centrale. A sua volta, questo aggiornava i dati nel database centrale. In questo contesto, scriverò non solo la storia di ciò che siamo riusciti a fare, ma anche degli errori da principianti che abbiamo commesso e come abbiamo dovuto pagare per questo in termini di tempo. Così, tutto l'albero degli oggetti era memorizzato in un unico file come oggetto serializzato. Finché abbiamo collegato al sistema alcuni clienti, tutto andava più o meno bene, anche se a volte si verificavano alcuni artefatti che erano del tutto incomprensibili. Ma quando abbiamo collegato al sistema una decina di server, sono cominciati a verificarsi eventi sorprendenti. A volte, senza apparente motivo, tutti gli oggetti nel sistema scomparivano. È importante notare che i server dei clienti inviavano dati al server centrale ogni pochi secondi tramite una richiesta POST. Un lettore attento e un programmatore esperto avrebbero già capito che si verificava un problema di accesso concorrente allo stesso file in cui era memorizzato l'oggetto serializzato, da diversi thread contemporaneamente. E proprio quando accadeva, si manifestavano eventi straordinari con la scomparsa degli oggetti. Il file diventava semplicemente vuoto. Ma tutto ciò non è stato scoperto immediatamente, ma solo durante l’uso con più server. Nel frattempo, è stata aggiunta la funzionalità per la scansione delle porte (i server non inviavano solo informazioni sulla disponibilità dei dispositivi, ma anche sulle porte aperte). Questo è stato fatto inviando il comando:

$connection = @fsockopen($ip, $port, $errno, $errstr, 0.5);

i risultati erano spesso errati e la scansione richiedeva molto tempo. Mi sono completamente dimenticato del ping, che veniva eseguito tramite fping:

system("fping -r 3 -t 100 {$this->ip}");

Anche questo non era stato parallelizzato, quindi il processo era molto lungo. In seguito, in fping veniva passato immediatamente l'intero elenco degli indirizzi IP da verificare e si otteneva un elenco finale di quelli che hanno risposto. A differenza di noi, fping era in grado di parallelizzare i processi.

Un altro lavoro di routine comune era la configurazione di alcuni servizi tramite WEB. Per esempio, ECP di MS Exchange. In realtà, si tratta solo di un link. Abbiamo deciso quindi di permettere l'aggiunta di link direttamente nel sistema, così da non dover cercare nella documentazione o altrove, tra i segnalibri, come accedere all'ECP di un cliente specifico. Così è nato il concetto di link di risorsa per il sistema, la cui funzionalità è ancora disponibile e non ha subito modifiche, o quasi.

Funzionamento dei link di risorsa in Veliam
Dall'outsourcing allo sviluppo (Parte 1)

Connessioni remote

Ecco come appare in azione nell'attuale versione di Veliam
Dall'outsourcing allo sviluppo (Parte 1)

Uno degli obiettivi era consentire una connessione rapida e comoda ai server, che erano già molti (ben oltre cento), e scorrere milioni di collegamenti RDP salvati in precedenza era estremamente scomodo. Era necessario uno strumento. Esistono software online che funzionano come una sorta di rubrica per tali connessioni RDP, ma non sono integrati con il sistema di monitoraggio e non consentono di salvare gli account. Ogni volta inserire gli account per diversi clienti è un vero e proprio incubo, quando al giorno ti connetti decine di volte a server diversi. Per SSH la situazione è leggermente migliore, ci sono molti buoni software che offrono la possibilità di organizzare tali connessioni in cartelle e di memorizzare i relativi account. Ma ci sono 2 problemi. Primo: non abbiamo trovato un'unica programmazione per le connessioni RDP e SSH. Secondo: se in un certo momento non sono al mio computer e devo connettermi rapidamente, oppure se ho semplicemente reinstallato il sistema, dovrò cercare nella documentazione per verificare l'account di quel cliente. È scomodo e una perdita di tempo.

La struttura gerarchica di cui avevamo bisogno per i server dei clienti era già presente nel nostro prodotto interno. Era solo necessario pensare a come collegare le connessioni rapide all'hardware necessario. Per cominciare, almeno all'interno della nostra rete.

Dato che il client nel nostro sistema era un browser che non ha accesso alle risorse locali del computer, e non poteva semplicemente lanciare l'applicazione necessaria con un comando, è stato ideato un sistema tramite "Windows custom url scheme". Così è nato un certo "plugin" per il nostro sistema, che includeva Putty e Remote Desktop Plus e che, durante l'installazione, registrava semplicemente lo schema URI in Windows. Ora, quando volevamo connetterci a un oggetto tramite RDP o SSH, eseguivamo questa azione nel nostro sistema e attivavamo il Custom URI. Si avviava mstsc.exe standard integrato in Windows o putty, che faceva parte del "plugin". Uso le virgolette attorno a plugin perché non si tratta di un plugin per browser nel senso classico.

Questo era già qualcosa. Un'ottima rubrica. In effetti, nel caso di Putty, andava tutto molto bene, poiché poteva ricevere come parametri di input sia l'IP di connessione che il login e la password. Ossia, ci collegavamo ai server Linux nella nostra rete con un solo clic, senza dover inserire password. Ma per RDP non era altrettanto semplice. Nel mstsc standard non era possibile passare le credenziali come parametri. È stato utile Remote Desktop Plus. Permetteva di farlo. Ora ne facciamo a meno, ma per molto tempo è stato un valido alleato nel nostro sistema. Con i siti HTTP(S) era tutto semplice, tali oggetti venivano semplicemente aperti nel browser e basta. Comodo e pratico. Ma questa era una felicità solo nella rete interna.

Poiché la maggior parte dei problemi li risolvevamo a distanza dall'ufficio, il modo più semplice era creare VPN verso i clienti. Così, dal nostro sistema, potevamo connetterci anche a loro. Tuttavia, era comunque piuttosto scomodo. Ogni cliente richiedeva di mantenere una marea di collegamenti memorizzati su ogni computer. VPN Prima di collegarsi a uno di questi, bisognava attivare la relativa VPN. Abbiamo utilizzato questa soluzione per un po' di tempo. Ma il numero di clienti aumentava, così come il numero di VPN, e tutto ciò ha iniziato a diventare frustrante, specialmente quando, dopo la reinstallazione del sistema, dovevamo inserire nuovamente decine di collegamenti VPN nel nuovo profilo di Windows. Non potevo più sopportarlo, ho detto, e ho iniziato a pensare a cosa si potesse fare.

È consuetudine che tutti i clienti utilizzino router della ben nota azienda Mikrotik. Questi dispositivi sono molto funzionali e comodi per svolgere praticamente qualsiasi compito. Tra gli svantaggi, c'è il rischio che vengano "sottratti". Abbiamo risolto questo problema semplicemente bloccando tutti gli accessi esterni. Tuttavia, dovevamo trovare un modo per accedervi senza dover visitare fisicamente il cliente, dato che richiede tempo. Abbiamo quindi creato tunnel per ciascun Mikrotik e li abbiamo raggruppati in un pool separato, senza alcuna routing, per evitare l'integrazione della nostra rete con le reti dei clienti e tra loro.

È nata l'idea di fare in modo che, quando cliccavo sull'oggetto desiderato nel sistema, il server centrale di monitoraggio, conoscendo le credenziali SSH di tutti i Mikrotik dei clienti, si connettesse a quello giusto, creando una regola di port forwarding verso l'host e la porta desiderati. Qui ci sono diversi aspetti da considerare. La soluzione non è universale: funzionerà solo per Mikrotik, poiché la sintassi dei comandi varia tra i diversi router. Inoltre, tali port forwarding dovevano essere anche rimossi in seguito, e la parte server del nostro sistema non poteva in sostanza monitorare se avessi terminato la mia sessione RDP. Inoltre, un tale port forwarding rappresentava una falla per il cliente. Non cercavamo nemmeno una soluzione universale, dato che il prodotto veniva utilizzato solo all'interno della nostra azienda e non avevamo intenzione di renderlo pubblico.

Ogni problema è stato risolto in modo diverso. Quando veniva creata una regola, il port forwarding era accessibile solo da un indirizzo IP esterno specifico (da cui era stata inizializzata la connessione). In questo modo, siamo riusciti a evitare falle nella sicurezza. Tuttavia, ad ogni connessione, veniva aggiunta una regola al Mikrotik nella pagina NAT e non veniva pulita. È risaputo che più regole ci sono, maggiore è il carico sul processore del router. E in generale, non riuscivo ad accettare l'idea che un giorno sarei entrato in un Mikrotik e lo avrei trovato carico di centinaia di regole inutili.

Poiché il nostro server non può monitorare lo stato della connessione, lascia che Mikrotik lo faccia da solo. Ho scritto uno script che monitorava continuamente tutte le regole di forwarding con una descrizione specifica (description) e controllava se ci fosse una connessione TCP corrispondente a questa regola. Se non veniva trovata per un certo periodo, probabilmente la connessione era già terminata e la regola di forwarding poteva essere rimossa. Tutto ha funzionato, lo script lavorava bene.

Ecco qui:

global atmonrulecounter {"dontDelete"="dontDelete"}
:foreach i in=[/ip firewall nat find comment~"atmon_script_main"] do={ 
	local dstport [/ip firewall nat get value-name="dst-port" $i]
	local dstaddress [/ip firewall nat get value-name="dst-address" $i]
	local dstaddrport "$dstaddress:$dstport"
	#log warning message=$dstaddrport
	local thereIsCon [/ip firewall connection find dst-address~"$dstaddrport"]
	if ($thereIsCon = "") do={
		set ($atmonrulecounter->dstport) ($atmonrulecounter->dstport + 1)
		#:log warning message=($atmonrulecounter->dstport)
		if (($atmonrulecounter->dstport) > 5) do={
			#log warning message="Removing nat rules added automaticaly by atmon_script"
			/ip firewall nat remove [/ip firewall nat find comment~"atmon_script_main_$dstport"]
			/ip firewall nat remove [/ip firewall nat find comment~"atmon_script_sub_$dstport"]
			set ($atmonrulecounter->dstport) 0
		}
	} else {
		set ($atmonrulecounter->dstport) 0
	}
}

Sicuramente si poteva fare più bello, più veloce, ecc., ma funzionava, non sovraccaricava i Mikrotik e svolgeva il compito egregiamente. Finalmente potevamo connetterci ai server e alle apparecchiature di rete dei clienti semplicemente con un clic del mouse. Senza attivare una VPN e senza inserire password. Lavorare con il sistema è diventato realmente molto comodo. Il tempo di manutenzione si riduceva, e tutti noi spendevamo tempo nel lavoro, e non per connetterci agli oggetti necessari.

Backup Mikrotik

Avevamo configurato il backup di tutti i Mikrotik su FTP. E in generale andava tutto bene. Ma quando dovevamo recuperare un backup, dovevamo aprire questo FTP e cercarlo lì. Avevamo un sistema dove erano registrati tutti i router, sapevamo comunicare con i dispositivi tramite SSH. Perché non implementare un sistema che prelevasse automaticamente il backup da tutti i Mikrotik ogni giorno, ho pensato. E ho iniziato a realizzarlo. Ci siamo connessi, abbiamo fatto il backup e l'abbiamo trasferito nello storage.

Codice script PHP per prelevare il backup da Mikrotik:

<?php

	$IP = '0.0.0.0';
	$LOGIN = 'admin';
	$PASSWORD = '';
	$BACKUP_NAME = 'test';

    $connection = ssh2_connect($IP, 22);

    if (!ssh2_auth_password($connection, $LOGIN, $PASSWORD)) exit;

    ssh2_exec($connection, '\/system backup save name="atmon" password="atmon"');
    stream_get_contents($connection);
    ssh2_exec($connection, '\/export file="atmon.rsc"');
    stream_get_contents($connection);
    sleep(40); 

    $sftp = ssh2_sftp($connection);

    \/\/ Download backup file
    $size = filesize("ssh2.sftp:\//$sftp\/atmon.backup");
    $stream = fopen("ssh2.sftp:\//$sftp\/atmon.backup", 'r');
    $contents = '';
    $read = 0;
    $len = $size;
    while ($read < $len && ($buf = fread($stream, $len - $read))) {
        $read += strlen($buf);
        $contents .= $buf;
    }
    file_put_contents ($BACKUP_NAME . '.backup',$contents);
    @fclose($stream);

    sleep(3);
    \/\/ Download RSC file
    $size = filesize("ssh2.sftp:\//$sftp\/atmon.rsc");
    $stream = fopen("ssh2.sftp:\//$sftp\/atmon.rsc", 'r');
    $contents = '';
    $read = 0;
    $len = $size;
    while ($read

Il backup viene effettuato in due forme: binario e configurazione testuale. Il binario aiuta a ripristinare rapidamente la configurazione necessaria, mentre il file testuale permette di comprendere le azioni da intraprendere in caso di sostituzione forzata dell'hardware, nel qual caso il binario non può essere caricato. In questo modo, abbiamo ottenuto un ulteriore funzionalità comoda nel sistema. Inoltre, con l'aggiunta di nuovi MikroTik, non è stato necessario fare alcuna configurazione, basta aggiungere l'oggetto nel sistema e impostare l'account SSH. Successivamente, il sistema si occupava automaticamente della creazione dei backup. Nella versione attuale del SaaS Veliam, questa funzionalità non è ancora disponibile, ma la porteremo presto.

Screenshot di come appariva nel sistema interno
Dall'outsourcing allo sviluppo (Parte 1)

Transizione a una corretta archiviazione nel database

In precedenza ho già scritto del fatto che sono apparsi artefatti. A volte spariva semplicemente l'intero elenco degli oggetti nel sistema, altre volte, durante la modifica di un oggetto, le informazioni non venivano salvate e dovevo rinominare l'oggetto tre volte. Questo irritava tutti moltissimo. La scomparsa degli oggetti avveniva raramente e si recuperava facilmente ripristinando quel file, mentre il problema durante la modifica degli oggetti si verificava spesso. Probabilmente non l'ho fatto inizialmente tramite il DB perché non riuscivo a concepire come tenere un albero con tutte le relazioni in una tabella piatta. È piatta, mentre l'albero è gerarchico. Ma una buona soluzione per l'accesso multiplo, e in seguito (con la complessità del sistema) anche per le transazioni, è il DBMS. Sicuramente non sono il primo a cui è successo. Ho cominciato a cercare su Google. Si è scoperto che era già tutto stato pensato prima di me e ci sono diversi algoritmi che costruiscono un albero da una tabella piatta. Dopo aver esaminato ciascuno, ho implementato uno di essi. Ma questa era già una nuova versione del sistema, poiché ho dovuto riscrivere molto a causa di questo. Il risultato era ovvio, i problemi di comportamento casuale del sistema sono scomparsi. Qualcuno potrebbe dire che gli errori sono piuttosto dilettanteschi (script a thread singolo, memorizzazione delle informazioni a cui vi era accesso simultaneo da più thread in un file, ecc.) nel campo dello sviluppo software. Potrebbe anche essere così, ma il mio lavoro principale era l'amministrazione, mentre la programmazione era un'attività secondaria per passione, e semplicemente non avevo esperienza di lavoro in un team di programmatori, dove certe cose elementari sarebbero state suggerite immediatamente da colleghi più esperti. Quindi, ho accumulato tutte queste esperienze autonomamente, ma ho assimilato molto bene il materiale. Inoltre, il mio lavoro comporta incontri con i clienti, azioni volte a promuovere l'azienda, una miriade di questioni amministrative interne e molto, molto altro. Ma in un modo o nell'altro, ciò che esisteva era richiesto. I ragazzi e io abbiamo utilizzato il prodotto nel lavoro quotidiano. Ci sono state idee chiaramente sbagliate e soluzioni in cui è stato speso tempo, e alla fine è diventato chiaro che erano strumenti non funzionanti, di cui nessuno si serviva e che non sono mai finiti in Veliam.

Supporto clienti - HelpDesk

Non sarà superfluo menzionare come è stato sviluppato HelpDesk. Questa è infatti una storia a sé, poiché in Veliam siamo già alla terza versione completamente nuova, che si differenzia da tutte le precedenti. Oggi si tratta di un sistema semplice, intuitivo, privo di fronzoli e con la possibilità di integrarsi con il dominio, così come di accedere allo stesso profilo utente da qualsiasi luogo tramite il link presente nell'email. E la cosa più importante è che è possibile connettersi al richiedente tramite VNC direttamente dalla richiesta, senza VPN o inoltri di porte, da qualsiasi punto (che sia a casa o in ufficio). Racconterò come siamo arrivati a questo, cosa c'era prima e quali terribili soluzioni sono state adottate.

Ci siamo collegati agli utenti tramite il noto TeamViewer. Su tutti i computer degli utenti che assistiamo è installato TV. La prima cosa che abbiamo fatto male e che abbiamo successivamente rimosso è stata l'associazione di ogni cliente all'hardware. Come accedeva un utente al sistema HD per inviare una richiesta? Oltre a TV, su tutti i computer era installata un'utilità speciale, scritta in Lazarus (qui molti allargeranno gli occhi e forse inizieranno a cercare su Google cosa sia, ma dal momento che conoscevo Delphi, Lazarus è praticamente lo stesso, solo gratuito). In sostanza, l'utente avviava un apposito file batch, che avviava questa utilità, la quale leggeva l'HWID del sistema e successivamente apriva il browser per l'autenticazione. Perché è stato fatto questo? In alcune aziende, il conteggio degli utenti assistiti è fatto singolarmente e il costo del servizio mensile è calcolato in base al numero di persone. Questo è chiaro, direte voi, ma perché l'associazione all'hardware? Molto semplice, alcuni individui tornavano a casa e inviavano una richiesta dal proprio portatile domestico con richiesta “fate tutto carino qui”. Oltre a leggere l'HWID del sistema, l'utilità estraeva dal registro l'ID corrente di TeamViewer e lo inviava a noi. TeamViewer dispone di un API per l'integrazione. E noi abbiamo realizzato questa integrazione. Ma c'era un problema. Attraverso queste API non è possibile collegarsi al computer dell'utente se non è lui a iniziare esplicitamente la sessione e dopo aver tentato di collegarsi a lui deve anche premere “conferma”. A quel tempo, sembrava logico che senza il consenso dell'utente nessuno dovesse collegarsi, e dato che la persona era al computer, sarebbero stati loro a iniziare la sessione e a rispondere positivamente alla richiesta di collegamento remoto. Ma le cose non sono andate così. I richiedenti dimenticavano di avviare la sessione, e dovevamo dirlo loro durante la conversazione telefonica. Questo faceva perdere tempo e innervosiva entrambe le parti del processo. Inoltre, non era affatto raro che una persona lasciasse una richiesta ma consentisse il collegamento solo quando andava a pranzo. Poiché il problema non era critico e non voleva che il suo processo lavorativo venisse interrotto. Di conseguenza, non avrebbe premuto nessun pulsante per consentire il collegamento. Così è apparso un funzionalità aggiuntiva durante l'autenticazione in HelpDesk: la lettura dell'ID di TeamViewer. Sapevamo la password permanente, che veniva utilizzata durante l'installazione di TeamViewer. Anzi, solo il sistema lo sapeva, poiché era incorporato nell'installer, e nel nostro sistema. Di conseguenza c'era un pulsante di collegamento nella richiesta su cui, premendo, non era necessario aspettare, ma si apriva immediatamente TeamViewer e si effettuava il collegamento. Alla fine sono emersi due tipi di collegamenti possibili. Tramite l'API ufficiale di TeamViewer e il nostro sistema fai-da-te. Con mia sorpresa, il primo è stato quasi subito abbandonato, anche se era stato indicato di usarlo solo in casi eccezionali e quando l'utente dava il suo consenso. Tuttavia, ora ci si concentra sulla sicurezza. Ma si è scoperto che ai richiedenti non importava. Erano tutti completamente d'accordo sul fatto che ci si collegasse a loro senza la conferma del pulsante. E poiché era così, in seguito, la funzionalità di collegamento tramite API è stata abolita per mancanza di necessità.

Transizione alla multithreading in Linux

Il problema di accelerare la scansione della rete per verificare l'apertura di un elenco predefinito di porte e il semplice ping di oggetti di rete si è fatto sentire da tempo. La prima soluzione che viene in mente è la multithreading. Poiché il principale tempo speso per il ping è l'attesa del ritorno del pacchetto, e il ping successivo non può iniziare finché non torna il pacchetto precedente, in aziende con oltre 20 server e altro hardware di rete, questo avveniva già molto lentamente. Il punto è che un pacchetto può anche andare perso, non si può avvisare immediatamente l'amministratore di sistema. Quest'ultimo smetterebbe di prendere sul serio quei falsi allarmi. Quindi è necessario pingare ogni oggetto più di una volta prima di concludere che non sia raggiungibile. Senza entrare troppo nei dettagli, è necessario parallelizzare, perché se non si fa, molto probabilmente l'amministratore di sistema verrà a sapere del problema dal cliente e non dal sistema di monitoraggio.

PHP di per sé non supporta la multithreading nativamente. Supporta la multiprocessazione, si possono forkare i processi. Ma avevo già fondamentalmente scritto un meccanismo di interrogazione e volevo fare in modo di leggere una sola volta tutti i nodi necessari dal database, pingare tutto in una sola volta, attendere la risposta da ciascuno e solo allora scrivere immediatamente i dati. Questo consente di risparmiare sulle richieste di lettura. Questa idea si adattava perfettamente alla multithreading. Per PHP esiste il modulo PThreads, che consente di implementare una vera multithreading, anche se ho dovuto lavorare abbastanza per configurarlo su PHP 7.2, ma alla fine ce l'ho fatta. La scansione delle porte e il ping sono diventati rapidi. E invece di impiegare ad esempio 15 secondi prima, ora questo processo richiede solo 2 secondi. Questo è stato un buon risultato.

Audit rapido di nuove aziende

Come è nata la funzionalità di raccolta di diverse metriche e caratteristiche hardware? È semplice. A volte ci viene richiesto solo un audit dell'attuale infrastruttura IT. E la stessa cosa è necessaria per accelerare l'audit di un nuovo cliente. Era necessario qualcosa che permettesse di entrare in un'azienda di medie o grandi dimensioni e orientarsi rapidamente su cosa avessero effettivamente. In una rete interna, il ping viene bloccato, secondo me, solo da chi vuole complicarsi la vita, e per nostra esperienza sono pochi. Ma ci sono anche questi casi. Di conseguenza, è possibile scansionare rapidamente le reti per rilevare dispositivi con un semplice ping. Successivamente, si possono aggiungere e scansionare per porte aperte di nostro interesse. In sostanza, questa funzionalità era già presente, era solo necessario aggiungere un comando dal server centrale a quello subordinato, in modo che quest'ultimo scansionasse le reti designate e aggiungesse alla lista tutto ciò che trovava. Ho dimenticato di menzionare, si presumeva che avessimo già un'immagine pronta con il sistema configurato (server subordinato di monitoraggio) che potevamo semplicemente distribuire al cliente durante l'audit e collegarlo al nostro cloud.

Tuttavia, i risultati dell'audit di solito includono una serie di informazioni diverse, e una di esse è: quali dispositivi ci sono in rete. In primo luogo, ci interessavano i server Windows e le workstation Windows all'interno di un dominio. Poiché nelle aziende di medie e grandi dimensioni l'assenza di un dominio è probabilmente l'eccezione alla regola. Per parlare la stessa lingua, per me una media è di 100+ persone. Dovevamo trovare un modo per raccogliere i dati da tutte le macchine e server Windows, conoscendo il loro IP e l'account dell'amministratore di dominio, senza installare alcun software su ognuna di esse. Qui entra in gioco l'interfaccia WMI. Windows Management Instrumentation (WMI), tradotto letteralmente, è lo strumento di gestione di Windows. WMI è una delle tecnologie fondamentali per la gestione centralizzata e il monitoraggio delle diverse parti dell'infrastruttura informatica sotto la piattaforma Windows. Prelevato da Wikipedia. Dopodiché, è stato necessario lavorare nuovamente per raccogliere wmic (il client WMI) per Debian. Una volta che tutto era pronto, rimaneva solo da interrogare tramite wmic i nodi necessari per ottenere le informazioni richieste. Attraverso WMI è possibile estrarre da un computer Windows quasi qualsiasi informazione e, cosa più importante, attraverso di esso è anche possibile gestire il computer, ad esempio, inviarlo al riavvio. Così è nato il sistema di raccolta delle informazioni sulle workstation e server Windows nel nostro sistema. In aggiunta a ciò, otteniamo anche informazioni attuali sui parametri di carico del sistema. Li richiediamo più frequentemente e le informazioni sull'hardware meno frequentemente. Dopo di ciò, effettuare l'audit è diventato un po' più piacevole.

Decisione sulla distribuzione del software

Noi stessi utilizziamo quotidianamente il sistema, e questo è sempre aperto per ciascun membro del personale tecnico. E abbiamo pensato che sarebbe interessante condividere ciò che già esiste anche con altri. Il sistema non era ancora pronto per essere distribuito. Era necessario rielaborare molte cose affinché la versione locale si trasformasse in SaaS. Questo comprende modifiche a vari aspetti tecnici nel funzionamento del sistema (connessioni remote, servizio clienti), l'analisi dei moduli per la questione delle licenze, lo sharding dei database dei clienti, la scalabilità di ciascun servizio e lo sviluppo di sistemi di aggiornamento automatico per tutte le parti. Ma di questo parleremo nella seconda parte dell'articolo.

Aggiornamento

La seconda parte

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster