Vom Outsourcing zur Entwicklung (Teil 1)

Hallo zusammen, ich heiße Sergey Emelyanchik. Ich bin der Geschäftsführer der Firma Audit-Telecom, Hauptentwickler und Autor des Systems Veliam. Ich habe beschlossen, einen Artikel darüber zu schreiben, wie wir mit einem Freund ein Outsourcing-Unternehmen gegründet haben, Software für uns selbst entwickelt und sie anschließend im Rahmen eines SaaS-Systems allen Interessierten zur Verfügung gestellt haben. Es geht darum, wie ich kategorisch nicht an die Möglichkeit geglaubt habe, dass dies möglich ist. Der Artikel wird nicht nur eine Erzählung enthalten, sondern auch technische Details zur Entwicklung des Produkts Veliam, einschließlich einiger Abschnitte des Quellcodes. Ich werde darüber berichten, welche Fehler wir gemacht haben und wie wir sie später korrigiert haben. Ich hatte Bedenken, einen solchen Artikel zu veröffentlichen. Aber ich dachte, es ist besser, es zu tun, Feedback zu erhalten und mich zu verbessern, als den Artikel nicht zu veröffentlichen und darüber nachzudenken, was wäre, wenn…

Vorgeschichte

Ich habe als IT-Mitarbeiter in einer großen Firma gearbeitet, die eine ausgeklügelte Netzwerkstruktur hatte. Ich werde nicht auf meine spezifischen Aufgaben eingehen, nur so viel sei gesagt: Dazu gehörte sicherlich nicht die Entwicklung von irgendetwas.

Wir hatten Monitoring, aber aus rein akademischem Interesse wollte ich versuchen, ein einfaches eigenes zu schreiben. Die Idee war, dass es webbasiert sein sollte, so dass man einfach ohne Installation von Clients darauf zugreifen und sehen konnte, was im Netzwerk von jedem Gerät aus geschieht, einschließlich Mobilgeräten über Wi-Fi. Außerdem wollte ich schnell verstehen, in welchem Raum die Geräte, die „probleme gemacht haben“, stehen, da es sehr strenge Anforderungen an die Reaktionszeit auf solche Probleme gab. Letztendlich entstand im Kopf der Plan, eine einfache Webseite zu erstellen, auf der als Hintergrund ein JPEG mit dem Netzwerkdiagramm war, die Geräte mit ihren IP-Adressen aus diesem Bild auszuschneiden und an den entsprechenden Koordinaten dynamische Inhalte in Form einer grünen oder blinkenden roten IP-Adresse einzublenden. Die Aufgabe ist gesetzt, loslegen.

Früher habe ich mit Delphi, PHP, JS und sehr oberflächlich mit C++ programmiert. Ich kenne mich ziemlich gut mit Netzwerken aus: VLAN, Routing (OSPF, EIGRP, BGP), NAT. Das reichte aus, um einen Prototyp eines primitiven Monitorings selbst zu schreiben.

Ich habe das, was ich mir vorgenommen hatte, in PHP geschrieben. Der Server Apache und PHP liefen unter Windows, da Linux für mich zu diesem Zeitpunkt etwas Unverständliches und sehr Kompliziertes war. Wie sich später herausstellte, hatte ich mich stark geirrt – in vielen Bereichen ist Linux viel einfacher als Windows. Aber das ist ein separates Thema, und wir wissen alle, wie viele Diskussionen es dazu gibt. Der Windows-Taskplaner rief in kurzen Abständen (ich erinnere mich nicht genau, aber es war etwas wie einmal alle drei Sekunden) ein PHP-Skript auf, das alle Objekte mit einem einfachen Ping abfragte und den Status in einer Datei speicherte.

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

Ja, zu diesem Zeitpunkt war mir auch die Arbeit mit Datenbanken nicht vertraut. Ich wusste nicht, dass man Prozesse parallelisieren kann, und das Durchlaufen aller Knoten im Netzwerk dauerte lange, da dies in einem Thread geschah. Besonders Probleme traten auf, wenn mehrere Knoten nicht erreichbar waren, da jeder von ihnen das Skript um 300 ms verzögerte. Auf der Client-Seite gab es eine einfache Schleifenfunktion, die in regelmäßigen Abständen aktualisierte Informationen vom Server über eine Ajax-Anfrage herunterlud und die Benutzeroberfläche aktualisierte. Nach drei aufeinanderfolgenden fehlgeschlagenen Pings, wenn auf dem Computer eine Web-Seite mit der Überwachung geöffnet war, spielte eine fröhliche Melodie.

Als alles geklappt hat, war ich sehr inspiriert von dem Ergebnis und dachte, dass ich noch etwas hinzufügen könnte (in Anbetracht meiner Kenntnisse und Möglichkeiten). Aber ich mochte schon immer keine Systeme mit Millionen von Diagrammen, die ich damals für überflüssig hielt und auch heute noch so sehe. Ich wollte nur das hinzufügen, was mir wirklich in meiner Arbeit helfen würde. Dieses Prinzip bleibt bis heute grundlegend für die Entwicklung von Veliam. Dann wurde mir klar, dass es großartig wäre, wenn ich das Monitoring nicht ständig offen halten müsste, um von Problemen zu erfahren. Stattdessen könnte ich die Seite nur öffnen, wenn ein Problem auftrat, um zu sehen, wo sich der problematische Netzwerk-Knoten befindet und was ich damit tun sollte. Ich hatte damals kaum E-Mails gelesen, ich nutzte sie einfach nicht. Ich stieß im Internet auf SMS-Gateways, an die man GET- oder POST-Anfragen senden kann, und die mir dann eine SMS mit dem Text, den ich schreibe, auf mein Handy schicken. Sofort wurde mir klar, dass ich das wirklich wollte. Und ich begann, die Dokumentation zu studieren. Nach einiger Zeit war es mir gelungen, und nun bekam ich SMS über Netzwerkprobleme auf mein Mobiltelefon mit dem Namen des "ausgefallenen Objekts". Auch wenn das System einfach war, so war es doch von mir selbst geschrieben, und das Wichtigste, was mich damals zur Weiterentwicklung motivierte, war, dass es ein praktisches Programm war, das mir tatsächlich in meiner Arbeit half.

Und so kam der Tag, an dem einer der Internetkanäle bei der Arbeit ausfiel, und mein Monitoring mir keinerlei Hinweise darauf gab. Da die Google-DNS nach wie vor hervorragend anpingbar waren. Es war an der Zeit, darüber nachzudenken, wie ich überwachen kann, ob der Kommunikationskanal funktioniert. Es gab verschiedene Ideen, wie man das umsetzen könnte. Ich hatte nicht zu allen Geräten Zugang. Ich musste mir überlegen, wie ich erkennen kann, welcher der Kanäle aktiv ist, ohne dass ich die Möglichkeit habe, dies direkt am Netzwerkgerät zu sehen. Damals hatte ein Kollege die Idee, dass die Traceroute zu öffentlichen Servern unterschiedlich sein könnte, je nachdem, über welchen Kommunikationskanal der Internetzugang erfolgt. Ich habe das überprüft, und tatsächlich war es so. Es gab verschiedene Routen bei der Traceroute.

system("tracert -d -w 500 8.8.8.8");

So entstand ein weiteres Skript, genauer gesagt wurde die Nachverfolgung aus einem bestimmten Grund ans Ende desselben Skripts hinzugefügt, das alle Geräte im Netzwerk anpingte. Schließlich war das ein weiterer langwieriger Prozess, der im selben Thread ausgeführt wurde und die Ausführung des gesamten Skripts bremste. Aber damals war das nicht so offensichtlich. So oder so, es tat seinen Dienst, im Code war festgelegt, welche Nachverfolgung jeder der Kanäle haben sollte. So begann ein System zu arbeiten, das bereits die (überspitzt gesagt, da keine Metriken gesammelt wurden, sondern einfach nur ping) Netzwerkgeräte (Router, Switches, Wi-Fi usw.) und Kommunikationskanäle mit der Außenwelt überwachte. SMS kamen zuverlässig an und auf dem Diagramm war immer gut sichtbar, wo das Problem lag.

Weiterhin musste ich in der täglichen Arbeit mit Cross-Connection arbeiten. Es wurde lästig, bei Cisco-Switches einloggen zu müssen, um zu sehen, welchen Schnittstellen ich verwenden sollte. Wie toll wäre es, auf dem Monitoring auf ein Objekt zu klicken und eine Liste seiner Schnittstellen mit Beschreibungen zu sehen. Das würde mir viel Zeit sparen. Zudem müsste man in diesem Schema kein Putty oder SecureCRT starten, keine Anmeldedaten und Befehle eintippen. Einfach im Monitoring klicken, sehen, was notwendig ist, und dann seine Arbeit machen. Ich begann zu suchen, wie ich mit den Switches interagieren könnte. Auf Anhieb fielen mir sofort 2 Varianten ein: SNMP oder über SSH auf den Switch zugreifen, die erforderlichen Befehle eingeben und das Ergebnis parsen. SNMP schloss ich wegen der Komplexität der Implementierung aus, ich wollte unbedingt schnell Ergebnisse erhalten. Mit SNMP müsste man lange in den MIBs wühlen, um basierend auf diesen Daten die Informationen über die Schnittstellen zu generieren. Es gibt einen großartigen Befehl in CISCO

show interface status

Sie zeigt genau das, was ich für die Cross-Checks brauche. Wozu sich mit SNMP quälen, wenn ich einfach die Ausgabe dieses Befehls sehen möchte, dachte ich. Nach einiger Zeit setzte ich diese Möglichkeit um. Ich klickte auf das Objekt auf der Webseite. Ein Ereignis wurde ausgelöst, wodurch der AJAX-Client den Server kontaktierte, der sich wiederum über SSH mit dem für mich benötigten Switch verband (die Zugangsdaten waren im Code hinterlegt, ich hatte keine Lust, es zu verfeinern oder separate Menüs zu erstellen, in denen ich die Zugangsdaten aus der Benutzeroberfläche ändern konnte, ich brauchte ein Ergebnis und zwar schnell), gab dort den oben genannten Befehl ein und zeigte ihn im Browser an. So begann ich, mit einem Mausklick Informationen zu den Schnittstellen zu sehen. Das war extrem praktisch, besonders wenn ich diese Informationen gleichzeitig auf verschiedenen Switches anschauen musste.

Die Überwachung von Kanälen basierend auf der Traceroute stellte sich letztendlich nicht als die beste Idee heraus, da manchmal Arbeiten im Netzwerk durchgeführt wurden, und die Traceroute sich ändern konnte, wobei die Überwachung mir signalisiert hat, dass es Probleme mit dem Kanal gibt. Nach eingehender Analyse stellte ich fest, dass alle Kanäle funktionieren und meine Überwachung mich täuscht. Schließlich bat ich Kollegen, die die kanalbildenden Switches verwalteten, mir einfach die Syslogs zu senden, wenn sich der Sichtbarkeitsstatus der Nachbarn (neighbor) änderte. Das war also viel einfacher, schneller und genauer als die Traceroute. Ein Ereignis wie „neighbor lost“ kam, und ich machte sofort eine Benachrichtigung über den Ausfall des Kanals.

Weiterhin gab es durch einen Klick auf das Objekt noch einige weitere Befehle und SNMP wurde für das Sammeln einiger Metriken hinzugefügt, und damit war es im Großen und Ganzen auch schon alles. Das System entwickelte sich nicht weiter. Es machte alles, was ich benötigte; es war ein gutes Werkzeug. Viele Leser werden mir sicherlich sagen, dass es für diese Aufgaben bereits eine Menge Software im Internet gibt. Aber tatsächlich fand ich damals keine kostenlosen Produkte, und ich wollte sehr gerne meine Programmierfähigkeiten weiterentwickeln, und was könnte besser geeignet sein, als eine reale praktische Aufgabe. Damit war die erste Version der Überwachung abgeschlossen und wurde nicht mehr modifiziert.

Gründung der Firma Audit-Telekom

Mit der Zeit begann ich, nebenbei in anderen Unternehmen zu arbeiten, da mir der Arbeitszeitplan dies erlaubte. Wenn man in verschiedenen Unternehmen arbeitet, wachsen die Fähigkeiten in verschiedenen Bereichen sehr schnell, der Horizont erweitert sich gut. Es gibt Unternehmen, in denen man, wie man so schön sagt, sowohl Schneider, als auch Erntearbeiter und Musiker ist. Einerseits ist das kompliziert, andererseits, wenn man nicht faul ist, wird man zu einem Fachmann mit breitem Profil, was es ermöglicht, Aufgaben schneller und effektiver zu lösen, da man weiß, wie ein angrenzendes Gebiet funktioniert.

Mein Freund Pawel (auch ein ITler) hat ständig versucht, mich zu motivieren, mein eigenes Geschäft zu gründen. Es gab unzählige Ideen mit verschiedenen Varianten eigener Unternehmungen. Das wurde über ein ganzes Jahr diskutiert. Und letztendlich sollte es zu nichts führen, weil ich ein Skeptiker bin und Pawel ein Träumer. Jedes Mal, wenn er eine Idee vorschlug, glaubte ich nicht daran und weigerte mich teilzunehmen. Aber wir wollten alle unbedingt unser eigenes Geschäft eröffnen.

Schließlich gelang es uns, eine Option zu finden, die uns beiden zusagte, und uns mit dem zu beschäftigen, was wir können. Im Jahr 2016 beschlossen wir, ein IT-Unternehmen zu gründen, das Unternehmen bei der Lösung von IT-Aufgaben unterstützen würde. Dazu gehören die Implementierung von IT-Systemen (1C, Terminalserver, Mailserver usw.), deren Wartung, klassischer Helpdesk für Benutzer und Netzadministration.

Um ehrlich zu sein, als ich das Unternehmen gegründet habe, glaubte ich zu 99,9 % nicht daran. Aber irgendwie konnte Pavel mich überzeugen, es auszuprobieren, und ich kann vorwegnehmen, dass er recht hatte. Pavel und ich haben jeweils 300.000 Rubel zusammengelegt, ein neues Unternehmen „Audit-Telekom“ registriert, ein winziges Büro gemietet, coole Visitenkarten gemacht und im Allgemeinen, wie wahrscheinlich die meisten unerfahrenen, aufstrebenden Unternehmer, angefangen, nach Kunden zu suchen. Die Kundensuche ist eine ganz eigene Geschichte. Vielleicht schreiben wir einen separaten Artikel in unserem Unternehmensblog, wenn das jemanden interessiert. Kaltakquise, Flyer und so weiter. Das brachte keine Ergebnisse. Wie ich jetzt aus vielen Geschichten über das Geschäft lese, hängt vieles irgendwie vom Glück ab. Wir hatten Glück. Und kaum zwei Wochen nach der Gründung der Firma wandte sich mein Bruder Vladimir an uns, der uns den ersten Kunden brachte. Ich möchte nicht mit den Details der Kundenarbeit langweilen, der Artikel handelt nicht davon; ich sage nur, dass wir zur Prüfung fuhren, kritische Punkte identifizierten und diese Punkte zusammenbrachen, während die Entscheidung über die Frage, ob wir als Outsourcer dauerhaft mit uns zusammenarbeiten sollten, getroffen wurde. Danach wurde sofort eine positive Entscheidung getroffen.

Darüber hinaus begannen hauptsächlich über Mundpropaganda durch Bekannte weitere Unternehmen, betreut zu werden. Helpdesk war in einem System. Die Verbindungen zu Netzwerkausrüstungen und Servern in einem anderen, genauer gesagt, je nachdem, wie es jeder handhabte. Einige speicherten Verknüpfungen, andere benutzten RDP-Adressbücher. Das Monitoring war ein weiteres separates System. Es ist sehr unangenehm für das Team, in unterschiedlichen Systemen zu arbeiten. Wichtige Informationen gehen aus dem Blickfeld verloren. Wenn beispielsweise der Terminalserver beim Kunden nicht mehr erreichbar ist, kommen sofort Anfragen von den Nutzern dieses Kunden. Ein Support-Spezialist erstellt eine Anfrage (sie kam per Telefon). Wenn die Vorfälle und Anfragen in einem System registriert wären, würde der Support-Spezialist sofort sehen, was das Problem des Nutzers ist, und es ihm mitteilen, während er sich parallel mit dem betroffenen Objekt verbindet, um die Situation zu bearbeiten. Alle sind über die taktische Lage informiert und arbeiten harmonisch zusammen. Wir haben kein solches System gefunden, in dem all dies vereint ist. Es wurde klar, dass es an der Zeit war, unser eigenes Produkt zu entwickeln.

Fortsetzung der Arbeit an unserem eigenen Überwachungssystem

Es war klar, dass das System, das zuvor geschrieben wurde, absolut nicht für die aktuellen Aufgaben geeignet war, weder in Bezug auf die Funktionalität noch in Bezug auf die Qualität. Daher wurde beschlossen, ein System von Grund auf neu zu schreiben. Grafisch sollte es ganz anders aussehen. Es sollte ein hierarchisches System sein, damit man schnell und bequem das benötigte Objekt bei dem passenden Kunden öffnen konnte. Das Schema, das in der ersten Version verwendet wurde, war in diesem Fall absolut nicht gerechtfertigt, da die Kunden unterschiedlich waren und es keine Rolle spielte, in welchen Räumen die Ausrüstung stand. Dies war bereits in der Dokumentation festgehalten.

Also, die Aufgaben:

  1. Hierarchische Struktur;
  2. Eine Serverkomponente, die beim Kunden in Form einer virtuellen Maschine platziert werden kann, um die benötigten Metriken zu sammeln und an den zentralen Server zu senden, der alles zusammenfasst und uns anzeigt;
  3. Benachrichtigungen. Solche, die man nicht übersehen kann, da es zu diesem Zeitpunkt nicht möglich war, dass jemand nur auf den Monitor starrte;
  4. Antragssystem. Es begannen Kunden zu erscheinen, bei denen wir nicht nur Server- und Netzwerkgeräte, sondern auch Arbeitsstationen betreuten;
  5. Die Möglichkeit, schnell auf Server und Geräte aus dem System zuzugreifen;

Die Aufgaben sind gestellt, wir beginnen mit dem Schreiben. Gleichzeitig bearbeiten wir die Anfragen der Kunden. Zu diesem Zeitpunkt waren wir bereits 4 Personen. Wir begannen sofort, beide Teile zu schreiben, sowohl den zentralen Server als auch den Server für die Installation bei den Kunden. Bis zu diesem Zeitpunkt war Linux uns nicht fremd, und es wurde beschlossen, dass die virtuellen Maschinen, die bei den Kunden stehen würden, auf Debian basieren würden. Es wird keine Installer geben, wir machen einfach ein Projekt für die Serverkomponente auf einer bestimmten virtuellen Maschine und klonen sie dann einfach zum entsprechenden Kunden. Das war ein weiterer Fehler. Später wurde klar, dass in diesem Schema der Mechanismus für Updates überhaupt nicht ausgearbeitet war. Das heißt, wir fügten eine neue Funktion hinzu, und dann gab es ein großes Problem, sie auf alle Server der Kunden zu verteilen, aber darauf kommen wir später zurück, alles der Reihe nach.

Wir haben den ersten Prototyp erstellt. Er konnte die für uns notwendigen Netzwerkgeräte der Clients und Server pingen und diese Daten an unseren zentralen Server senden. Dieser aktualisierte wiederum diese Daten in der Gesamtheit auf dem zentralen Server. Ich werde hier nicht nur die Geschichte darüber schreiben, wie und was gelungen ist, sondern auch welche dilettantischen Fehler gemacht wurden und wie man dafür Zeit bezahlen musste. Nun, der gesamte Objektbaum wurde in einer einzigen Datei als serialisiertes Objekt gespeichert. Solange wir einige Clients an das System anschlossen, war alles mehr oder weniger in Ordnung, obwohl manchmal einige Artefakte auftauchten, die völlig unverständlich waren. Doch als wir ein Dutzend Server an das System anschlossen, begannen Wunder zu geschehen. Manchmal verschwanden alle Objekte im System einfach aus unerklärlichen Gründen. Hier ist wichtig zu erwähnen, dass die Server der Clients alle paar Sekunden Daten an den zentralen Server mittels eines POST-Requests sendeten. Der aufmerksame Leser und erfahrene Programmierer hat bereits erkannt, dass ein Problem mit dem gleichzeitigen Zugriff auf genau die Datei, in der das serialisierte Objekt aus verschiedenen Threads gespeichert war, auftrat. Und genau zu dem Zeitpunkt, als dies geschah, traten Wunder mit dem Verschwinden von Objekten auf. Die Datei wurde einfach leer. Doch das stellte sich nicht sofort heraus, sondern erst im Verlauf des Betriebs mit mehreren Servern. In dieser Zeit wurde auch eine Funktion zum Scannen von Ports hinzugefügt (die Server sendeten an das Zentrale nicht nur Informationen über die Verfügbarkeit von Geräten, sondern auch über die darauf geöffneten Ports). Dies wurde durch den Befehl erreicht:

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

Die Ergebnisse waren oft falsch, und das Scannen dauerte sehr lange. Ich habe ganz den Ping vergessen, der über fping ausgeführt wurde:

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

Auch dies war nicht parallelisiert, daher war der Prozess sehr langwierig. Später wurde fping so angepasst, dass gleich die gesamte Liste der zu überprüfenden IP-Adressen übergeben wurde, und zurück erhielten wir eine fertige Liste derjenigen, die geantwortet haben. Im Gegensatz zu uns konnte fping Prozesse parallelisieren.

Eine weitere häufige Routinearbeit bestand darin, verschiedene Dienste über das WEB einzurichten. Zum Beispiel den ECP von MS Exchange. Im Grunde genommen ist das nur ein Link. Wir entschieden, dass wir die Möglichkeit benötigen, solche Links direkt im System hinzuzufügen, um nicht in der Dokumentation oder an anderen Stellen nachzuschauen, wie man auf das ECP eines bestimmten Kunden zugreift. So entstand das Konzept der Ressourcennlinks für das System, deren Funktionalität bis heute verfügbar ist und sich nahezu nicht verändert hat.

Die Funktionsweise der Ressourcennlinks in Veliam
Vom Outsourcing zur Entwicklung (Teil 1)

Fernverbindungen

So sieht es in der aktuellen Version von Veliam in der Praxis aus
Vom Outsourcing zur Entwicklung (Teil 1)

Eine der Aufgaben war eine schnelle und bequeme Verbindung zu den Servern, von denen es inzwischen viele gibt (nicht nur eine Handvoll), und es war äußerst unpraktisch, Millionen von im Voraus gespeicherten RDP-Verknüpfungen durchzugehen. Ein Tool war notwendig. Es gibt im Internet Software, die etwas wie ein Adressbuch für solche RDP-Verbindungen darstellt, jedoch sind sie nicht in das Überwachungssystem integriert und die Anmeldedaten können nicht gespeichert werden. Jedes Mal Anmeldedaten für verschiedene Kunden einzugeben ist der reinste Horror, wenn man am Tag nicht Dutzende Male mit verschiedenen Servern verbindet. Bei SSH ist die Situation etwas besser, es gibt viele gute Software, die die Möglichkeit bietet, solche Verbindungen in Ordnern zu organisieren und die Anmeldedaten zu speichern. Aber es gibt zwei Probleme. Erstens — für RDP- und SSH-Verbindungen haben wir kein einheitliches Programm gefunden. Zweitens — wenn ich zu irgendeinem Zeitpunkt nicht an meinem Computer bin und mich schnell verbinden muss oder ich einfach das System neu installiert habe, muss ich in die Dokumentation schauen, um die Anmeldedaten für diesen Kunden zu finden. Das ist unpraktisch und eine Zeitverschwendung.

Die uns benötigte hierarchische Struktur für die Server der Kunden war bereits in unserem internen Produkt vorhanden. Es musste nur überlegt werden, wie wir schnelle Verbindungen zu der notwendigen Hardware integrieren können. Zum Anfang, zumindest innerhalb unseres eigenen Netzwerks.

Da der Browser, der in unserem System als Kunde fungierte, keinen Zugriff auf lokale Computerressourcen hatte, um einfach eine bestimmte Anwendung mit einem Befehl zu starten, wurde die Idee entwickelt, alles über das „Windows Custom URL-Schema“ zu realisieren. So entstand eine Art „Plugin“ für unser System, das Putty und Remote Desktop Plus beinhaltete und bei der Installation einfach das URI-Schema in Windows registrierte. Jetzt, wenn wir eine Verbindung zu einem Objekt über RDP oder SSH herstellen wollten, klickten wir auf diese Aktion in unserem System, und das Custom URI funktionierte. Es wurde die standardmäßige mstsc.exe, die in Windows eingebaut ist, oder putty gestartet, das Teil des „Plugins“ war. Ich setze das Wort Plugin in Anführungszeichen, weil es sich nicht um ein klassisches Browser-Plugin handelt.

Das war zumindest schon mal etwas: ein praktisches Adressbuch. Besonders im Fall von Putty war alles sehr gut, da man als Eingabeparameter sowohl die IP-Adresse als auch den Benutzernamen und das Passwort übergeben konnte. Das heißt, zu den Linux-Servern in unserem Netzwerk konnten wir uns mit einem Klick ohne Eingabe von Passwörtern verbinden. Aber mit RDP war es nicht so einfach. In das standardmäßige mstsc konnten keine Zugangsdaten als Parameter übergeben werden. Da kam Remote Desktop Plus zur Hilfe. Er erlaubte es, dies zu tun. Heute verzichten wir darauf, aber lange Zeit war es ein zuverlässiger Helfer in unserem System. Mit HTTP(S)-Websites ist alles einfach; solche Objekte wurden einfach im Browser geöffnet, und das war's. Praktisch und bequem. Aber das war nur in unserem internen Netzwerk ein Segen.

Da wir die meisten Probleme aus dem Büro remote lösten, war es am einfachsten, VPNs zu unseren Kunden einzurichten. So konnten wir auch von unserem System aus auf sie zugreifen. Es war aber trotzdem etwas umständlich. Für jeden Kunden musste man auf jedem Computer eine Menge gespeicherter Verbindungen verwalten, und bevor man sich mit einem von ihnen verbinden konnte, musste man das entsprechende VPN aktivieren. Mit dieser Lösung kamen wir eine ganze Zeit lang aus. Aber die Anzahl der Kunden stieg, die Anzahl der VPNs ebenfalls, und das alles begann, unbequem zu werden – besonders kamen die Tränen in die Augen nach der Neuinstallation des Systems, wenn man Dutzende von VPN-Verbindungen in einem neuen Windows-Profil erneut eingeben musste. „Es reicht jetzt“, sagte ich und begann zu überlegen, was man dagegen tun könnte. VPN Verbindungen und bevor man sich mit einem verbindet, musste man das entsprechende VPN aktivieren. Mit dieser Lösung haben wir eine lange Zeit gearbeitet. Aber die Anzahl der Kunden wächst, die Anzahl der VPNs ebenfalls, und das begann zu belasten, sodass wir etwas dagegen unternehmen mussten. Besonders liefen einem die Tränen in die Augen nach der Neuinstallation des Systems, als man wieder dutzende VPN-Verbindungen im neuen Windows-Profil eingeben musste. Das konnte ich nicht mehr ertragen, habe ich gesagt, und begann zu überlegen, was man dagegen tun könnte.

Es hat sich so ergeben, dass alle unsere Kunden als Router Geräte der bekannten Marke Mikrotik verwendeten. Diese sind sehr funktionell und praktisch für die Durchführung fast aller Aufgaben. Ein Nachteil ist, dass sie oft „gestohlen“ werden. Wir haben dieses Problem einfach gelöst, indem wir alle externen Zugänge gesperrt haben. Aber wir mussten irgendwie Zugriff auf sie haben, ohne zum Kunden vor Ort zu fahren, da das zeitaufwändig ist. Wir haben einfach zu jedem solchen Mikrotik Tunnel eingerichtet und diese in einen separaten Pool aufgeteilt, ohne jegliche Routing, um eine Verbindung unseres eigenen Netzwerks mit den Netzwerken der Kunden und deren Netzwerken untereinander zu vermeiden.

Die Idee entstand, so zu verfahren, dass beim Klicken auf das benötigte Objekt im System der zentrale Überwachungsserver, der die Anmeldedaten für SSH aller Kundenmikrotiks kennt, sich mit dem richtigen verbindet, eine Regel für das Portforwarding zu dem gewünschten Host mit dem benötigten Port erstellt. Hier gibt es gleich mehrere Aspekte. Diese Lösung ist nicht universell – sie funktioniert nur für Mikrotik, da die Syntax der Befehle bei allen Routern unterschiedlich ist. Außerdem mussten solche Weiterleitungen später irgendwie gelöscht werden, und der Serverteil unseres Systems konnte im Grunde nicht verfolgen, ob ich meine RDP-Sitzung beendet hatte. Und solch eine Weiterleitung ist ein Sicherheitsrisiko für den Kunden. Wir haben nach Universallösungen nicht gesucht, da das Produkt nur innerhalb unseres Unternehmens verwendet wurde und wir nie daran gedacht haben, es öffentlich zu machen.

Jedes dieser Probleme wurde auf seine Weise gelöst. Als die Regel erstellt wurde, war das Forwarding nur für eine spezifische externe IP-Adresse verfügbar (von der die Verbindung initiiert wurde). So konnten Sicherheitslücken vermieden werden. Aber bei jeder solchen Verbindung wurde eine Regel auf dem Mikrotik zur NAT-Seite hinzugefügt und nicht gelöscht. Und es ist allgemein bekannt, dass je mehr Regeln es dort gibt, desto stärker die CPU des Routers belastet wird. Außerdem konnte ich es nicht akzeptieren, dass ich einmal auf einen Mikrotik zugreife und dort Hunderte von toten, unnötigen Regeln finde.

Da unser Server den Verbindungsstatus nicht überwachen kann, soll MikroTik dies selbst tun. Ich habe ein Skript geschrieben, das kontinuierlich alle Portweiterleitungsregeln mit einer bestimmten Beschreibung (description) überwacht und überprüft, ob es eine passende TCP-Verbindung gibt. Wenn es eine Weile keine solche Verbindung gab, war die Verbindung wahrscheinlich bereits beendet und die Weiterleitung konnte gelöscht werden. Es hat alles funktioniert, das Skript lief gut.

Übrigens, hier ist es:

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="Entfernen der automatisch hinzugefügten NAT-Regeln durch 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
	}
}

Sicherlich hätte man es schöner, schneller usw. machen können, aber es funktionierte, belastete die MikroTiks nicht und erledigte seine Aufgabe hervorragend. Wir konnten endlich einfach mit einem Mausklick auf die Server und Netzwerkausrüstung unserer Kunden zugreifen, ohne ein VPN hochzufahren oder Passwörter einzugeben. Die Arbeit mit dem System wurde wirklich sehr bequem. Die Wartungszeit wurde verkürzt, und wir konnten unsere Zeit für die Arbeit nutzen, nicht für den Zugriff auf die gewünschten Objekte.

Mikrotik Backup

Wir hatten das Backup aller MikroTiks auf FTP eingerichtet. Insgesamt war alles gut. Aber wenn wir ein Backup brauchen würden, mussten wir diesen FTP öffnen und dort nach ihm suchen. Wir haben ein System, in dem alle Router registriert sind, und wir können über SSH mit den Geräten kommunizieren. Warum sollten wir nicht so etwas machen, dass das System täglich alle Backups von den MikroTiks holt, dachte ich. Und so machte ich mich an die Umsetzung. Wir haben uns verbunden, ein Backup erstellt und es ins Archiv geholt.

PHP-Skriptcode zum Erstellen eines Backups von 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); // Warten auf die Erstellung des Backups

    $sftp = ssh2_sftp($connection);

    // Sicherungsdatei herunterladen
    $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);
    // RSC-Datei herunterladen
    $size = filesize("ssh2.sftp://$sftp/atmon.rsc");
    $stream = fopen("ssh2.sftp://$sftp/atmon.rsc", 'r');
    $contents = '';
    $read = 0;
    $len = $size;
    while ($read

Das Backup wird in zwei Formen erstellt — als Binärdatei und als Textkonfiguration. Die Binärdatei ermöglicht es, die benötigte Konfiguration schnell wiederherzustellen, während das Textformat hilft, zu verstehen, was zu tun ist, wenn eine zwanghafte Hardwareänderung erfolgt und die Binärdatei nicht auf das neue Gerät übertragen werden kann. Am Ende haben wir ein weiteres nützliches Funktionalität in das System integriert. Zudem musste bei der Hinzufügung neuer Mikrotiks nichts konfiguriert werden, man fügte einfach das Objekt in das System ein und stellte einen SSH-Zugang ein. Das System erledigte dann automatisch die Sicherung. In der aktuellen Version von SaaS Veliam ist diese Funktionalität noch nicht vorhanden, aber wir werden sie bald portieren.

Screenshots, wie das in unserem internen System aussah.
Vom Outsourcing zur Entwicklung (Teil 1)

Übergang zur ordnungsgemäßen Speicherung in der Datenbank

Ich habe bereits oben geschrieben, dass Artefakte auftraten. Manchmal verschwand die gesamte Objektliste im System, manchmal wurde beim Bearbeiten eines Objekts die Information nicht gespeichert, und ich musste das Objekt dreimal umbenennen. Das hat alle furchtbar genervt. Das Verschwinden von Objekten passierte selten und ließ sich leicht durch Wiederherstellung der entsprechenden Datei beheben, aber das Problem beim Bearbeiten von Objekten trat häufig auf. Vermutlich habe ich das ursprünglich nicht über die Datenbank gemacht, weil ich nicht begreifen konnte, wie man einen Baum mit all seinen Verbindungen in einer flachen Tabelle speichern kann. Eine Tabelle ist flach, während ein Baum hierarchisch ist. Aber eine gute Lösung für den gleichzeitigen Zugriff und später (bei Komplikationen im System) auch für Transaktionen ist ein DBMS. Ich kann mir sicher sein, dass ich nicht der Erste bin, der mit diesem Problem konfrontiert wird. Ich begann zu googeln. Es stellte sich heraus, dass schon alles vor mir erfunden wurde und es mehrere Algorithmen gibt, die einen Baum aus einer flachen Tabelle erstellen. Nach dem Betrachten jedes einzelnen implementierte ich einen von ihnen. Aber das war bereits eine neue Version des Systems, da ich letztendlich aufgrund dessen viel umschreiben musste. Das Ergebnis war nachvollziehbar, die Probleme mit dem zufälligen Verhalten des Systems verschwanden. Manche könnten sagen, dass die Fehler recht amateurhaft waren (einzelne Skripte, Speicherung von Informationen, die gleichzeitig von mehreren Threads in einer Datei abgerufen wurden usw.) im Bereich der Softwareentwicklung. Vielleicht stimmt das, aber mein Hauptjob war die Verwaltung, während das Programmieren eher ein Hobby war, und ich hatte einfach keine Erfahrung in der Arbeit mit einem Team von Programmierern, wo mir solche grundlegenden Dinge sofort von älteren Kollegen erklärt worden wären. Daher habe ich all diese Schwierigkeiten selbst überwunden, aber ich habe das Material sehr gut gelernt. Außerdem umfasst mein Tätigkeitsfeld Kundenmeetings, Aktivitäten zur Promotion der Firma und eine Menge administrativer Fragen innerhalb des Unternehmens und vieles, vieles mehr. Dennoch war das, was bereits war, gefragt. Die Jungs und ich selbst nutzten das Produkt in unserer täglichen Arbeit. Es gab auch offen gesagt missratene Ideen und Lösungen, für die Zeit aufgewendet wurde, und letztendlich wurde klar, dass es sich um ein nicht funktionierendes Werkzeug handelt, und niemand hat es verwendet, und es gelangte nicht in Veliam.

Kundendienst — HelpDesk

Es ist erwähnenswert, wie der HelpDesk entstanden ist. Das ist eine ganz eigene Geschichte, denn in Veliam ist dies bereits die dritte ganz neue Version, die sich von allen vorherigen unterscheidet. Jetzt ist es ein einfaches, intuitiv verständliches System ohne überflüssige Schnörkel und Spielereien, mit der Möglichkeit, sich mit der Domain zu integrieren, sowie mit der Möglichkeit, auf dasselbe Benutzerprofil von überall über den Link in der E-Mail zuzugreifen. Und das Wichtigste ist, dass es von jedem Punkt aus (ob ich zu Hause oder im Büro bin) möglich ist, sich über VNC direkt aus der Anfrage mit dem Antragssteller zu verbinden, ohne VPN oder Portweiterleitungen. Ich werde erklären, wie wir dazu gekommen sind, was zuvor war und welche schrecklichen Lösungen es gab.

Wir haben uns über den weithin bekannten TeamViewer mit den Nutzern verbunden. Auf allen Computern, deren Nutzer wir betreuen, ist TV installiert. Das Erste, was wir falsch gemacht haben und später entfernt haben — die Bindung jedes Kunden-Hardware-ID (HWID). Wie trat der Nutzer in das HD-System ein, um eine Anfrage zu stellen? Auf allen Computern, abgesehen von TV, war ein spezielles Tool installiert, das in Lazarus geschrieben wurde (viele werden hier die Augen verdrehen und möglicherweise sogar googeln, was das ist, aber von den kompilierbaren Sprachen kannte ich am besten Delphi, und Lazarus ist fast das Gleiche, nur kostenlos). Im Allgemeinen startete der Benutzer ein spezielles Batch-Skript, das dieses Tool öffnete; dieses las die HWID des Systems aus und danach wurde der Browser gestartet und die Autorisierung erfolgte. Warum wurde das gemacht? In einigen Unternehmen wird die Anzahl der betreuten Nutzer einzeln gezählt, und der Preis für die Dienstleistung wird basierend auf der Anzahl der Personen pro Monat festgelegt. Das ist klar, werden Sie sagen, aber warum die Bindung an die Hardware? Ganz einfach, einige Individuen kamen nach Hause und reichten von ihrem Heim-Notebook aus Anfragen ein mit dem Stil: „Machen Sie mir alles schön hier.“ Neben dem Auslesen der HWID des Systems holte das Tool auch die aktuelle TeamViewer-ID aus der Registrierungsdatenbank und übermittelte sie uns. TeamViewer hat eine API für die Integration. Und wir haben diese Integration erstellt. Aber es gab ein Problem. Über diese API kann man sich nicht mit dem Computer des Nutzers verbinden, wenn er diese Sitzung nicht eindeutig initiiert, und nach dem Versuch, sich mit ihm zu verbinden, muss er auch auf „bestätigen“ drücken. Zu diesem Zeitpunkt schien es uns logisch, dass sich ohne die Zustimmung des Nutzers niemand verbinden sollte, und da die Person vor dem Computer sitzt, initiiert sie auch die Sitzung und bestätigt die Anfrage für die remote Verbindung. Doch es stellte sich heraus, dass es nicht so war. Antragsteller vergaßen, die Sitzung zu initiieren, und mussten dies im Telefongespräch mit uns besprochen werden. Das kostete Zeit und nervte beide Seiten des Prozesses. Darüber hinaus sind solche Momente nicht selten, wenn eine Person eine Anfrage hinterlässt, aber die Verbindung erst dann zulässt, wenn sie zum Mittagessen geht. Denn das Problem ist nicht kritisch und sie möchte nicht, dass ihr Arbeitsprozess unterbrochen wird. Folglich wird sie keinen Knopf drücken, um die Verbindung zu erlauben. So entstand die zusätzliche Funktionalität bei der Autorisierung im HelpDesk — das Auslesen der TeamViewer-ID. Wir kannten das permanente Passwort, das bei der Installation von TeamViewer verwendet wurde. Genauer gesagt kannte es nur das System, da es im Installationsprogramm und in unserem System eingebaut war. Folglich gab es einen Verbindungsknopf in der Anfrage, bei dessen Betätigung man nichts mehr abwarten musste, sondern TeamViewer sofort geöffnet wurde und die Verbindung stattfand. Insgesamt gab es zwei Arten von möglichen Verbindungen. Über die offizielle TeamViewer-API und unsere eigene. Zu meinem Erstaunen wurde die erste fast sofort nicht mehr genutzt, obwohl es eine Anweisung gab, sie nur in besonderen Fällen zu verwenden, wenn der Nutzer selbst dies genehmigte. Sicherheitsaspekte sind jetzt gefragt. Aber es stellte sich heraus, dass den Antragstellern dies nicht wichtig war. Sie waren alle absolut einverstanden, dass man sich ohne Bestätigungsknopf mit ihnen verbindet. Und da dies so war, wurde in Zukunft die Funktionalität der Verbindung über die API als nicht mehr notwendig abgeschafft.

Der Übergang zur Mehrfachverarbeitung in Linux

Schon seit einiger Zeit stellt sich die Frage, wie man die Geschwindigkeit des Netzwerkscanners zur Überprüfung der Offenheit einer vorher definierten Liste von Ports und das einfache Pingen von Netzwerkobjekten beschleunigen kann. In diesem Zusammenhang ist die erste Lösung, die einem in den Sinn kommt, die Mehrfachverarbeitung. Da die meiste Zeit, die für das Pingen benötigt wird, auf die Wartezeit der Rückkehr des Pakets entfällt und der nächste Ping nicht beginnen kann, bevor das vorherige Paket zurückgekehrt ist, geschieht dies bei Unternehmen mit mehr als 20 Servern und Netzwerkausrüstung bereits ziemlich langsam. Das Problem ist, dass ein Paket möglicherweise verlorengeht, und der Systemadministrator darüber nicht sofort informiert werden kann. Er würde solches Spam sehr schnell nicht mehr wahrnehmen. Das bedeutet, dass jeder Objekt mindestens mehrmals gepingt werden sollte, bevor man zu dem Schluss kommt, dass es nicht erreichbar ist. Wenn wir nicht zu sehr ins Detail gehen wollen, dann ist es notwendig, parallel zu arbeiten, denn wenn man das nicht tut, wird der Systemadministrator wahrscheinlich vom Kunden und nicht vom Überwachungssystem von dem Problem erfahren.

PHP selbst kann aus der Box heraus keine Mehrfachverarbeitung. Es kann Mehrprozessarbeit, man kann es forken. Aber ich hatte bereits einen Mechanismus zur Abfrage geschrieben und wollte es so gestalten, dass ich alle benötigten Knoten einmal aus der Datenbank abfrage, alle sofort ping und auf die Antworten von jedem warte, und erst danach die Daten sofort schreibe. Das spart Leseanfragen. In diese Idee passte die Mehrfachverarbeitung perfekt. Für PHP gibt es das Modul PThreads, das echte Mehrfachverarbeitung ermöglicht, allerdings musste ich eine Weile damit verbringen, es für PHP 7.2 einzurichten, aber es wurde gemacht. Das Scannen der Ports und das Pingen wurden schnell. Und statt früher 15 Sekunden für einen Durchlauf benötigte der Prozess jetzt nur noch 2 Sekunden. Das war ein gutes Ergebnis.

Schnelles Audit neuer Unternehmen

Wie ist die Funktionalität zur Sammlung verschiedener Metriken und Eigenschaften von Hardware entstanden? Es ist ganz einfach. Manchmal bestellen wir einfach eine Prüfung der aktuellen IT-Infrastruktur. Das Gleiche ist notwendig, um die Prüfung eines neuen Kunden zu beschleunigen. Es musste etwas geben, das es ermöglicht, in ein mittelständisches oder großes Unternehmen zu kommen und schnell zu erkennen, was sie überhaupt haben. Ping wird im internen Netzwerk meiner Meinung nach nur von denen blockiert, die sich selbst das Leben schwer machen wollen, und solche sind nach unserer Erfahrung selten. Aber sie kommen vor. Dementsprechend kann man das Netzwerk schnell nach Geräten scannen, indem man einfach pingt. Danach kann man sie hinzufügen und nach offenen Ports scannen, die uns interessieren. Im Grunde genommen gab es diese Funktionalität bereits, es musste nur ein Befehl vom zentralen Server an den untergeordneten Server hinzugefügt werden, damit dieser die festgelegten Netzwerke scannt und alles, was er findet, zur Liste hinzufügt. Ich habe vergessen zu erwähnen, es wurde angenommen, dass wir bereits ein fertiges Image mit einem eingerichteten System (ein untergeordneter Überwachungsserver) haben, das wir einfach beim Kunden während der Prüfung bereitstellen und an unsere Cloud anschließen konnten.

Das Ergebnis des Audits umfasst in der Regel eine Menge unterschiedlicher Informationen, und eine davon ist, welche Geräte sich überhaupt im Netzwerk befinden. Zunächst interessierten uns die Windows-Server und Windows-Workstations innerhalb der Domäne. In mittelgroßen und großen Unternehmen ist das Fehlen einer Domäne wahrscheinlich die Ausnahme von der Regel. Um eine gemeinsame Grundlage zu schaffen, stelle ich mir eine durchschnittliche Größe von über 100 Mitarbeitern vor. Wir mussten einen Weg finden, um Daten von allen Windows-Maschinen und Servern zu sammeln, indem wir ihre IP-Adressen und das Konto eines Domänenadministrators verwendeten, ohne jedoch auf jedem von ihnen eine Art Software zu installieren. Hier kommt die WMI-Schnittstelle ins Spiel. Windows Management Instrumentation (WMI) ist übersetzt ein Werkzeug zur Verwaltung von Windows. WMI ist eine der grundlegenden Technologien für das zentrale Management und die Überwachung der Funktionsweise verschiedener Teile der Computerinfrastruktur, die unter der Windows-Plattform betrieben wird. Dies habe ich aus Wikipedia. Danach musste ich wieder etwas Zeit investieren, um wmic (den WMI-Client) für Debian zu erstellen. Nachdem alles bereit war, musste ich nur noch die benötigten Knoten über wmic nach den erforderlichen Informationen abfragen. Über WMI kann man von einem Windows-Computer nahezu jede Information abrufen, und darüber hinaus kann man mit ihm auch den Computer steuern, zum Beispiel einen Neustart auslösen. So entstand die Informationssammlung über Windows-Stationen und -Server in unserem System. Zusätzlich holten wir aktuelle Informationen über die derzeitige Systemauslastung. Diese abfragen wir häufiger, während die Hardware-Informationen seltener angefordert werden. Danach wurde das Audit ein wenig angenehmer.

Entscheidung über die Verteilung von Software

Wir selbst nutzen das System täglich, und es ist immer für jeden technischen Mitarbeiter geöffnet. Wir dachten, dass wir auch mit anderen teilen könnten, was bereits vorhanden ist. Das System war jedoch noch nicht bereit für die Verbreitung. Es war notwendig, sehr vieles zu überarbeiten, damit die lokale Version in ein SaaS-Modell verwandelt werden konnte. Dazu gehören Änderungen an verschiedenen technischen Aspekten der Systemfunktion (Remote-Verbindungen, Supportdienste), die Analyse von Modulen hinsichtlich der Lizenzierung, das Sharding von Kundendatenbanken, die Skalierung jedes der Dienste und die Entwicklung von automatischen Aktualisierungssystemen für alle Teile. Aber darüber wird es im zweiten Teil des Artikels gehen.

Update

Der zweite Teil

Quelle: habr.com

60GB SSD 8Gb DDR4