Ich bin Entwickler der Netzwerküberwachungssoftware Network MACMonitor .
Bei der Programmentwicklung stellte sich die Aufgabe, festzustellen, welche Computer Benutzer verwenden, und diese Informationen den Ports von Netzwerkgeräten zuzuordnen. In diesem Artikel möchte ich schreiben, wie ich das geschafft habe.

Ich begann mit einfachen Überlegungen: Um einen Benutzer einem Port auf einem Netzwerkgerät zuzuordnen, müssen Sie zuerst den Computer, mit dem der Benutzer arbeitet, an diesen Port anschließen. Da Sie mit dem Programm Network MACMonitor Mac-Adressen an den Ports von Netzwerkgeräten finden können, wurde beschlossen, Computer über Mac-Adressen mit Ports zu verbinden. Als Nächstes müssen Sie Benutzer mit Computern verbinden. Diese Informationen können durch Abfragen von Computern auf irgendeine Weise erhalten werden.
Ich habe zwei Möglichkeiten gesehen, um dieses Problem zu lösen:
- Schreiben Sie einen Windows-Agenten und fragen Sie ihn mit Network MACMonitor ab.
- Verwenden Sie Windows Management Instrumentation (WMI).
Die Version mit dem Windows-Agenten weist eine Reihe von Nachteilen auf, die für mich von Bedeutung waren:
- Entwicklung eines sicheren Protokolls für die Netzwerkinteraktion eines Windows-Agenten mit Network MACMonitor;
- die Notwendigkeit, den Agenten auf Computern vorinstallieren;
- Verwenden einer anderen Programmiersprache (ich schreibe in Java), da Java meines Erachtens nicht zum Schreiben eines Agenten geeignet ist: aufgrund des relativ hohen Verbrauchs an virtuellem Speicher und der Notwendigkeit, JRE auf allen Computern zu installieren.
Aufgrund all der oben genannten Nachteile habe ich mich entschlossen, über die Option mit WMI nachzudenken.
WMI-Client-Entwicklung
Da Network MACMonitor in Java geschrieben ist, habe ich versucht, eine vorgefertigte plattformübergreifende Java-Bibliothek zu finden, die die Funktionalität des WMI-Clients implementiert. Und dann war ich enttäuscht - es gibt keine solche Bibliothek. Alle vorhandenen Bibliotheken sind entweder Wrapper über Windows-Dienstprogramme oder (j-Interop-Bibliothek) erfordern zusätzliche Registrierungsmanipulationen (Eigentümerwechsel und Berechtigungen für Registrierungszweige), um WMI über eine Remote-Registrierung zu aktivieren. Da es für Java keine voll funktionsfähige Bibliothek gab, entschied ich mich, eine Bibliothek oder einen WMI-Client zu finden, der in einer anderen Programmiersprache geschrieben ist. Und fand einen WMI-Client für Linux. Nachdem ich die Arbeit heruntergeladen und überprüft hatte, stellte ich fest, dass das Abrufen von Windows-Computern unter Linux möglich ist.
Wenn dies möglich ist, habe ich beschlossen, meine Bibliothek in reinem Java zu schreiben, damit ich den Computer mit WMI abfragen kann.
Zum Schreiben der Bibliothek war eine klare Dokumentation zum Betrieb des WMI-Protokolls erforderlich. Es stellte sich heraus, dass es eine solche Dokumentation gibt und diese gemeinfrei ist.
Ich begann mich auf das Schreiben der Bibliothek vorzubereiten, indem ich mir den Netzwerkstapel des WMI-Protokolls ansah.
Protokoll | Technische Daten |
---|
Windows Management Instrumentation (WMI) | MS-WMI, MS-WMIO |
Distributed Component Object Model (DCOM) | MS-DCOM |
Remote Procedure Call (RPC) | MS-RPCE |
Transmission Control Protocol (TCP) | - - |
Internet Protocol (IP) | - - |
Damit WMI ordnungsgemäß funktioniert, müssen alle Stapelebenen implementiert sein.
Da WMI nicht in Java implementiert ist, bin ich zum nächsten Protokoll im Stack übergegangen - DCOM. Und hier hatte ich Glück. Obwohl die oben erwähnte j-Interop-Bibliothek keine WMI-Funktionalität implementiert, ist die DCOM-Funktionalität darin implementiert. Es bleibt also eine Implementierung des WMI-Protokolls zu schreiben, dh eine Implementierung der MS-WMI- und MS-WMIO-Spezifikationen zu schreiben.
Ich begann mit der Implementierung der MS-WMIO-Spezifikation, die für das Codierungsformat von Daten in Netzwerkpaketen des WMI-Protokolls verantwortlich ist. Aus der Spezifikation habe ich gelernt, dass beim Codieren von Daten die erweiterte Backus-Naur-Syntaxspezifikation (ABNF, RFC 5234) verwendet wird. Die MS-WMIO-Spezifikation beschreibt das Codierungsformat mit ABNF vollständig. Es ist bekannt, dass bei einer in ABNF beschriebenen Grammatik ein Parser für diese Grammatik erstellt werden kann. Im Internet habe ich einen ABNF-Parser-Generator für Java gefunden und ihn mit einer Grammatik aus der Spezifikation eingegeben. Da der generierte Parser mit Zeichenfolgen arbeitete und MS-WMIO ein binäres Codierungsformat beschreibt, bestand die Idee darin, den generierten Parser einfach durch Zeichenfolgen durch Arrays und Zeichen durch Bytes zu ersetzen. Nachdem ich mir jedoch die Anzahl der Dateien angesehen hatte, bei denen ein Austausch erforderlich war, und aus der MS-WMIO-Spezifikation gelernt hatte, dass manchmal mit Bits gearbeitet werden muss, wurde mir klar, dass es sehr schwierig sein würde, den generierten Parser zu reparieren, und ich entschied mich, diese Idee aufzugeben. Ich dachte, dass das Schreiben eines Parsers von Grund auf schneller sein würde. Und jetzt war der Parser fertig.
Aber wie kann überprüft werden, ob der Parser korrekt geschrieben ist, wenn die MS-WMI-Spezifikation, die für den Betrieb des WMI-Protokolls verantwortlich ist, noch nicht implementiert ist? Dann half mir Wireshark, ein Netzwerk-Verkehrsanalysator. Nachdem ich WMI-Anfragen mit Standard-Windows-Tools (wbemtest) gestellt und zuvor die Verschlüsselung deaktiviert hatte, erhielt ich Netzwerkpakete und speicherte sie in Binärdateien. Diese Dateien konnten bereits als Testdaten für den Parser verwendet werden.
Als der Parser getestet und die gefundenen Fehler behoben wurden, implementierte ich die MS-WMI-Spezifikation, die die Funktionsweise des WMI-Protokolls beschreibt.
Die MS-WMI-Spezifikation ist in Server und Client unterteilt. Ich habe den Client-Teil teilweise implementiert, soweit dies für die Abfrage eines Computers über WMI erforderlich ist. In diesem Teil brauchte ich auch Wireshark, aber bereits, um die Reihenfolge der Netzwerkpakete während der WMI-Abfrage zu analysieren.
Der Versuch, die erforderlichen Daten mit WMI abzurufen
Nach dem Schreiben der WMI-Bibliothek wurde die Aufgabe, sie im Programm Network MACMonitor zu verwenden. Es stellte sich die Frage: Welche Daten sollten von Computern bezogen werden? Ich dachte, ich müsste den Computernamen, die Domäne, das Betriebssystem, die Einschaltzeit, die Mac-Adressen, die IP-Adressen und die aktiven Benutzer abrufen, die am Computer arbeiten.
Es trat jedoch ein sehr wichtiges Problem auf: Wie kann ein Computer während der WMI-Abfrage eindeutig identifiziert werden? Ich habe folgende Optionen in Betracht gezogen:
- Mac-Adresse, mögliche Änderung, möglicherweise nicht eindeutig;
- Computername und Domäne (Arbeitsgruppe), mögliche Änderung, nicht eindeutig (für Arbeitsgruppe);
- Die Seriennummer der Festplatte, auf der das Betriebssystem installiert ist, Administratorrechte sind während der WMI-Abfrage erforderlich. Ich habe nicht auf Eindeutigkeit überprüft, aber ich vermute, dass eine Eindeutigkeit möglich ist.
- Die Seriennummer des Motherboards, nicht eindeutig, ist möglich und ziemlich oft.
- die Kennung des Computersystems ( UUID WMI-Eigenschaft der Win32_ComputerSystemProduct- Klasse), Nicht-Eindeutigkeit ist möglich und ziemlich häufig;
- Die Installationszeit des Betriebssystems ist die beste aller Optionen. Beim Klonen des Systems oder bei der Bereitstellung von einem Image ist jedoch eine Eindeutigkeit möglich.
Da Sie mit keiner Option den Computer eindeutig identifizieren können, habe ich mich entschlossen, den Computer auf drei Arten zu identifizieren:
- Seriennummer des Motherboards,
- Computersystem-ID
- Installationszeit des Betriebssystems.
Natürlich können diese drei Parameter auf verschiedenen Computern zusammenfallen, aber weniger häufig als einer von ihnen.
Es wurde auch versucht, aktive Benutzer mithilfe der Standard-WMI-Klasse Win32_LogonSession zu gewinnen . Dann trat das erste Problem auf: Es stellte sich heraus, dass Win32_LogonSession alle Benutzersitzungen anzeigt , auch diejenigen, die bereits abgeschlossen wurden. Ich begann zu überlegen, wie ich aktive Sitzungen aus denen herausfiltern sollte, die endeten. Es wurde festgestellt, dass dies mit der Win32_SessionProcess- Klasse durchgeführt werden kann, die Instanzen der Win32_LogonSession- Klassen mit Win32_Process verknüpft . Wenn der Link zur Sitzung in der Liste der Instanzen der Win32_SessionProcess- Klasse vorhanden ist (es gibt mindestens einen Prozess mit der Kennung dieser Sitzung), ist er aktiv. Als nächstes stellte sich die Frage, wie eine Sitzung einem Benutzer zugeordnet werden kann. Dies kann mit der Win32_LoggedOnUser- Klasse erfolgen, die Instanzen der Klassen Win32_LogonSession und Win32_UserAccount bindet. Es müssen nur noch Instanzen der Win32_UserAccount- Klasse abgerufen werden , die detaillierte Informationen zum Benutzer bereitstellen.

Aber hier war ich enttäuscht. Bei der Remote-Verwendung von WMI stellte sich heraus, dass beim Versuch, Instanzen der Win32_UserAccount- Klasse abzurufen , nur lokale Computerbenutzer abgerufen werden können. Das heißt, es stellte sich heraus, dass mit Standard-WMI-Tools nicht herausgefunden werden kann, welche Benutzer auf dem Computer aktiv sind.
Entwicklung eines WMI-Anbieters.
Aufgrund der Unmöglichkeit einer eindeutigen Identifizierung von Computern und der Unmöglichkeit, Informationen über aktive Benutzer mithilfe von Standard-WMI-Klassen zu erhalten, wurde beschlossen, die Funktionalität von WMI zu erweitern. Sie können dies tun, indem Sie Ihre WMI-Klassen in einer MOF-Datei beschreiben und einen WMI-Anbieter schreiben, um Instanzen dieser Klassen abzurufen.
Es wurden zwei neue WMI-Klassen beschrieben: NMBY_InstallInfo - zur Identifizierung eines Computers und NMBY_LogonSession - zur Identifizierung aktiver Benutzer eines Computers.

Dann wurde ein WMI-Anbieter geschrieben, mit dem Sie Instanzen dieser Klassen erhalten können.
Für den Anbieter wurden zusätzliche Anforderungen festgelegt:
- auf einem System ohne .NET arbeiten;
- Arbeit unter dem Betriebssystem Windows XP und höher;
- die Fähigkeit, Informationen über ein nicht administratives Konto zu erhalten.
Daher wurde der Anbieter mit WinApi in C ++ geschrieben.
Beim Schreiben des Anbieters traten aufgrund der geringen Menge und Qualität der Dokumentation zu diesem Thema Schwierigkeiten auf, der Anbieter wurde jedoch trotzdem erfolgreich geschrieben.
Ein schriftlicher Anbieter ist auf der Downloadseite verfügbar. Es kann kostenlos installiert und verwendet werden.
Zusammenfassung
Infolgedessen wurde mit dem Programm Network MACMonitor Folgendes möglich:
- Benutzer mit Computern verknüpfen

- Verknüpfen Sie Computer mit Ports auf Netzwerkgeräten

- Verknüpfen Sie Netzwerkgeräteports mit Computern und Benutzern

- Anzeigen des Benutzerregistrierungsverlaufs auf Computern.

Programmwebsite