Linux: 如何使用Python捕获发送到ULOG的包?(带宽监测项目)
我正在为我的网络编写一个自定义的带宽监控系统。我想能够追踪内部网络中每个IP的带宽使用情况。我已经编写了所有基础设施来处理日志显示、发送警告等功能,并进行必要的统计分析。
目前,我使用的方法有点笨拙:我在iptables中设置了一些不做任何事情的规则,然后定期从Python运行iptables -vnxL
并解析出字节计数。这种方法可能相对高效(因为我们不是在解析每一个数据包),但也存在漏掉数据包的可能性,比如如果系统重启,计数器会被重置(尤其是如果重启不干净的话),而且如果我出于某种原因手动修改iptables规则,计数器也会因为这个操作而重置。
我读过关于ULOG目标的内容,我可以用它将所有路由的数据包发送到用户空间,在那里我可以获取数据包的大小并将其添加到存储在数据库中的计数器中。我看到两个可能的选项:
- 在Python中实现一个
ulogd
的等效功能,能够看到所有经过接口的数据包,手动解析每个数据包的大小和地址,并处理所有的计算。我觉得这样可能效率不高,因为我会在Python中逐个解析数据包,所以在高数据包应用(比如VOIP等)情况下,Python可能会跟不上,甚至漏掉数据包。 - 直接运行
ulogd
,但让它只记录每个数据包的IP地址和字节计数到一个文件中;然后定期用Python解析这个文件。每次Python解析文件时,我希望能清空这个文件。
我希望用Python而不是iptables来做这个的原因是我能获得更多的灵活性。因为我会手动解析IP地址和端口等信息,我可以进行一些统计,比如“HTTP流量占比是多少”。目前,使用iptables的方法,我只能确定“每个主机使用了多少带宽”。
我倾向于第二种方法。以下是我想要的流程:
- Python进程启动。它以某种方式捕获当前ulogd日志文件的快照。
- 重启
ulogd
,并清空日志文件。这样可以确保在Python处理数据包快照时不会漏掉任何数据包,并且Python不需要跟踪日志文件的读取位置。 - 现在,Python可以按照自己的节奏解析日志快照中的数据包。
我看到的一些问题:
- Python如何获取这个“快照”?我能想到的唯一方法是:终止ulogd,复制文件,删除或截断原始文件,然后重启ulogd。这可能需要一些时间,而在现代连接中,这几秒钟可能会导致丢失数兆字节的跟踪数据。
- 如果我通过读取ulogd正在写入的同一个文件来工作,我觉得可能会发生一些奇怪的事情,比如写入缓存,这样我们可能仍然会漏掉数据包。
有没有人能给我一些建议,或者指引我去哪里获取一些关于这个项目的建议?
F
1 个回答
我想到两种方法:
- 只解析已经旋转过的文件。比如,先旋转ulogd文件,然后在旋转后解析它们。
- 解析正在使用的文件。
最后,你需要先开发第一种方法,然后可能再扩展到第二种方法。也就是说,你需要考虑日志旋转的情况,记住你最后解析过的旋转文件,然后在下次运行时从那个点开始解析。因此,你肯定需要在每次运行之间保持状态。
对于第二种方法,你可以采用类似logtail的方式。比如,记录正在使用的文件的inode号码和你最后解析到的位置。如果inode号码发生变化(或者文件大小小于你记录的位置),那么你就需要重新解析整个文件。否则,你可以从那个位置继续解析。
如果你不需要实时数据,那么处理旋转过的文件应该效果不错。不过,如果你想要更实时的数据,那么像logtail那样解析当前的日志文件会比较快。
另外,你也可以尝试为ulogd使用数据库作为后端,这样可以在数据库中解决这个问题。