我如何将计算机和用户连接到网络MACMonitor监视程序中的网络设备端口

我是Network MACMonitor网络监控软件的开发人员。


在程序开发过程中,出现了一个任务:确定用户正在使用哪些计算机,并将此信息与网络设备的端口相关联。 在本文中,我想写我如何做到的。


图片


我从简单的考虑开始:为了使用户与网络设备上的端口相关联,必须首先将用户使用的计算机连接到该端口。 由于程序Network MACMonitor允许您在网络设备的端口上查找mac地址,因此决定使用mac地址将计算机连接到端口。 接下来,您需要将用户连接到计算机。 可以通过任何方式询问计算机来获取此信息。


我看到了两种解决此问题的方法:


  1. 编写一个Windows代理,并使用网络MACMonitor对其进行询问;
  2. 使用Windows管理规范(WMI)。

Windows代理的版本具有许多对我来说很重要的缺点:


  • 开发用于Windows代理与网络MACMonitor进行网络交互的安全协议;
  • 需要在计算机上预安装代理;
  • 使用另一种编程语言(我用Java写),因为我认为Java不适合编写代理程序:由于虚拟内存的消耗量很大,并且需要在所有计算机上安装JRE。

由于上述所有不利因素,我决定使用WMI来介绍该选项。


WMI客户端开发


因为Network MACMonitor是用Java编写的,所以我试图找到一个现成的,跨平台的Java库,该库实现WMI客户端的功能。 然后我很失望-没有这样的图书馆。 所有现有库都是Windows实用程序的包装程序,或者(j-Interop库)需要其他注册表操作(更改注册表分支的所有权和权限)才能通过远程注册表激活WMI。 由于没有适用于Java的完全正常运行的库,因此我决定找到一个用任何其他编程语言编写的库或WMI客户端。 并找到了一个用于Linux的WMI客户端。 下载并检查其工作后,我意识到可以在Linux下轮询Windows计算机。


如果可能,我决定用纯Java编写我的库,这将使我能够使用WMI轮询计算机。


要编写该库,需要有关WMI协议操作的清晰文档。 原来有这样的文档,它是在公共领域。


我开始通过查看WMI协议网络堆栈来准备编写库。


协议书技术指标
Windows管理规范(WMI)MS-WMI,MS-WMIO
分布式组件对象模型(DCOM)MS-DCOM
远程过程调用(RPC)MS-RPCE
传输控制协议(TCP)--
互联网协议(IP)--

为了使WMI正常工作,必须实现所有堆栈级别。


由于WMI不是用Java实现的,因此我继续研究堆栈中的下一个协议-DCOM。 在这里,我很幸运。 尽管上述j-Interop库没有实现WMI功能,但在其中实现了DCOM功能。 因此,剩下的工作就是编写WMI协议的实现,即编写MS-WMI和MS-WMIO规范的实现。


我首先实现了MS-WMIO规范,该规范负责WMI协议的网络数据包中数据的编码格式。 从规范中,我了解到在对数据进行编码时,使用了扩展的Backus-Naur语法规范(ABNF,RFC 5234)。 MS-WMIO规范完全描述了使用ABNF的编码格式。 众所周知,如果在ABNF中描述了一种语法,则可以为该语法创建解析器。 在Internet上,我找到了一个用于Java的ABNF解析器生成器,并输入了来自规范的语法。 由于生成的解析器使用字符串,并且MS-WMIO描述了一种二进制编码格式,因此其想法是简单地将生成的解析器替换为字符串,将其替换为数组,将字符替换为字节。 但是在查看了需要替换的文件数量之后,并且从MS-WMIO规范中了解到有时有时需要使用位,我意识到修复生成的解析器非常困难,因此决定放弃这个想法。 我认为从头开始编写解析器会更快。 现在解析器已准备就绪。


但是,如果尚未执行负责WMI协议操作的MS-WMI规范,如何验证解析器是否正确编写呢? 然后,网络流量分析器Wireshark帮助了我。 使用标准Windows工具(wbemtest)发出了WMI请求,并且之前禁用了加密,我收到了网络数据包并将其保存到二进制文件中。 可以将这些文件用作解析器的测试数据。


测试了解析器并纠正了发现的错误后,我着手实施MS-WMI规范,该规范描述了WMI协议的操作。


MS-WMI规范分为服务器和客户端。 在通过WMI轮询计算机所必需的程度上,我部分实现了客户端部分。 在这一部分中,我还需要Wireshark,但已经可以在WMI轮询期间分析网络数据包的顺序。


尝试使用WMI获得必要的数据


编写WMI库之后,就可以在网络MACMonitor程序中使用它了。 问题出现了:应该从计算机获取哪些数据? 我以为我需要获取计算机名称,域,操作系统,开机时间,mac地址,ip地址,在计算机上工作的活跃用户。


但是出现了一个非常重要的问题:如何在WMI轮询期间唯一地标识计算机? 我考虑了以下选项:


  • mac地址,可能的更改,可能的唯一性;
  • 计算机名称和域(工作组),可能的更改,不唯一(对于工作组);
  • 安装操作系统的硬盘驱动器的序列号,在WMI轮询期间需要管理员权限,我没有检查唯一性,但是我怀疑可能是唯一性;
  • 主板的序列号可能是唯一的,而且经常出现;
  • 计算机系统的标识符( Win32_ComputerSystemProduct类的UUID WMI属性)可能是唯一的,而且经常出现;
  • 操作系统的安装时间是所有选项中最好的,但是在克隆系统或从映像进行部署时可能会出现非唯一性。

没有选项允许您唯一地标识计算机,因此我决定通过三种方式标识计算机:


  • 主板序列号,
  • 计算机系统标识符
  • 操作系统安装时间。

当然,这三个参数可能在不同的计算机上重合,但频率不及其中之一。


还尝试使用标准WMI类Win32_LogonSession来获得活动用户。 然后出现了第一个问题:事实证明Win32_LogonSession显示所有用户会话,即使是已经完成的用户会话。 我开始思考如何从结束的活动中过滤掉活动的活动。 发现可以使用Win32_SessionProcess类完成此任务,该类将Win32_LogonSession类的实例与Win32_Process关联。 如果在Win32_SessionProcess类的实例列表中存在到会话的链接(至少有一个具有该会话标识符的进程),则该会话处于活动状态。 接下来,出现了有关如何将会话与用户关联的问题。 这可以使用Win32_LoggedOnUser类完成,该类绑定Win32_LogonSessionWin32_UserAccount类的实例。 剩下的只是获取Win32_UserAccount类的实例,该实例提供有关用户的详细信息。


图片


但是在这里我很失望。 事实证明,当远程使用WMI时,尝试获取Win32_UserAccount类的实例时,可能只能获取本地计算机用户。 也就是说,事实证明,使用标准的WMI工具,不可能找出哪些用户在计算机上处​​于活动状态。


WMI提供程序的开发。


由于不可能明确标识计算机并且无法使用标准WMI类获取有关活动用户的信息,因此决定扩展WMI的功能。 您可以通过在MOF文件中描述WMI类并编写WMI提供程序来获取这些类的实例来做到这一点。


已经描述了两个新的WMI类: NMBY_InstallInfo (用于标识计算机)和NMBY_LogonSession (用于标识计算机的活动用户)。


图片


然后编写了一个WMI提供程序,您可以使用它来获取这些类的实例。


为提供者设置了其他要求:


  • 在没有.NET的系统上工作;
  • 在Windows XP及更高版本的操作系统上工作;
  • 使用非管理帐户获取信息的能力。

因此,该提供程序是使用WinApi用C ++编写的。


在编写提供程序的过程中,由于有关此主题的文档数量少且质量低,因此出现了困难,但是尽管如此,提供程序还是被成功编写了。


下载页面上有书面提供者。 可以免费安装和使用。


总结


结果,使用网络MACMonitor程序可以:


  • 将用户与计算机关联

图片


  • 将计算机与网络设备上的端口关联

图片


  • 将网络设备端口与计算机和用户关联

图片


  • 在计算机上查看用户注册历史记录。

图片


计划网站

Source: https://habr.com/ru/post/zh-CN416217/


All Articles