监控网络使用情况(不包括本地流量)
-
28-09-2019 - |
题
我正在开发一个监控网络使用情况的应用程序。然而,我注意到许多方法都不允许排除本地流量(例如,时间机器)。
我正在寻找一种排除本地流量的方法,并且仅监视直接进出互联网的使用情况。
更新:谢谢您的回复,现在我知道如何查找流量是否是本地的,但我仍然不知道如何计算总输入/输出字节(抱歉,如果我之前没有详细说明)。我无法知道在特定时间段内或自操作系统启动以来本地(或互联网)发送/接收了多少字节。由于操作系统运行时进程会启动或终止,这个问题变得更加复杂。
问题的答案 如何在 Linux/Mac OSX 中获取网络适配器统计信息? 提供了一种总结总使用情况的有趣方法,但它没有帮助,因为它总结的使用情况是接口统计信息。
更新2:我已经发布了我的最终解决方案。请向下滚动一点查看。
解决方案 8
我拥有的最终工作解决方案是使用 libpcap
为达到这个。当然,有一些缺点,其中包括它需要提高特权,并且必须捕获所有过滤的数据包以计算统计数据,但至少效果很好。
许多文档和教程 libpcap
我建议每个对此解决方案感兴趣的人都相当透彻和清晰,以相对较少的Google-Fu努力来查看那些。
另外,我的Internet流量过滤器仅仅是以下内容 - 可能会感兴趣 -
- (NSString *)_internetFilterStringForInterface:(AKNetworkInterface *)interface
inOrOut:(BOOL)inYesOutNo
{
if (![interface net] || ![interface mask] || IsEmpty([interface addresses]))
{
return nil;
}
NSString *hostType = inYesOutNo ? @"dst" : @"src";
NSString *host = nil;
for (NSString *hostComponent in [interface addresses])
{
if (IsEmpty(hostComponent)) continue;
if (!host)
host = [NSString stringWithFormat:@"(%@ host %@", hostType, hostComponent];
else
host = [host stringByAppendingFormat:@" or %@ host %@", hostType, hostComponent];
}
host = [host stringByAppendingString:@")"];
NSString *net = [interface netString];
net = [net stringByReplacingOccurrencesOfString:@".0" withString:@""];
NSString *filter = [NSString stringWithFormat:
@"ip and (not %@ net %@) and %@",
inYesOutNo ? @"src" : @"dst",
net, host];
return filter;
}
该过滤器的设计具有有关“本地流量”的一些答案,我知道它不包括一些边缘案例,例如Double NAT配置等,但我想了解有关此的建议。
我知道 net = [net stringByReplacingOccurrencesOfString:@".0" withString:@""];
只是一个快速的黑客,在某些特殊情况下很容易失败,但是嘿,没有人抱怨,至少还没有。
其他提示
回答您对哪种接口带来本地流量的评论实际上很复杂,因为这取决于您的本地流量的含义。
“本地”意味着什么
“本地流量”的最简单含义是流量不会使机器生成的计算机(例如,同一台计算机上的两个程序相互交谈)。这个流量全部结束了。当人们说本地时(以及我回答时我在想什么),这是一件事。
下一个最简单的含义将是“ IP流量,注定是同一子网上的机器”。那将是在本地子网内部具有目标地址的流量。最简单的计算方法将是路由表(如果MAC OS X计算每个路线的流量统计信息,则各种网关上的路由将为您提供非本地流量),也可以使用防火墙规则。 当他们说“本地流量”时,这可能不希望任何人意味着。
另一个含义将是“ IP流量注定要在此(物理)位置中的计算机”。例如,在我的办公室使用了几个子网,它们之间有路由器,但是从一个子网到另一个子网的流量显然仍然是本地的。您需要网络知识,以将本地与非本地流量区分开,并使用此定义。
另一个含义将是“ IP流量注定为我的组织中的机器”。这是一个合理的含义,具体取决于您的网络的设置方式(例如,您的位置之间的光纤也很快,但是您的互联网连接速度较慢,或者收费的每GB)。需要深入了解网络的知识,以确定目的地是否将是本地的,并且与VPN这样的事物 可能会随着时间的流逝而有所不同。
最后,“互联网流量”不是 任何 那些。有时,例如,以太网段上似乎是本地计算机上的本地计算机实际上是通过Internet上的VPN(这不是疯狂的,这对于远程用户需要使用各种Windows服务非常有用)。组织内部的流量可以轻松地通过Internet VPN旅行。
在简单网络中作弊
如果网络非常简单,只有一个内部子网,只有一个路由器,并且所有流量都不是内部子网作为互联网流量,则可以作弊并解决此问题。这可能适用于绝大多数家庭网络以及许多小型企业。
使用防火墙规则
在简单的网络设置中,您可能可以做出一些假设,并通过将流量视为非本地的流量来获得足够的答案:
- 目标MAC地址是默认网关的MAC地址;和
- 目标IP地址是 不是 默认网关的IP地址
或者:
- 目标IP地址不在网络接口的子网中,默认路由输出
您可能可以创建一个防火墙规则来计算其中的任何一个。至少有了Linux Iptables,您可以肯定BSD PF,以及可能的Mac OSX。
替代方法:SNMP
最后,如果您不能使用防火墙规则(如需要根本),您可以希望默认网关对SNMP社区公开响应,探索其所有接口,并找到带有额外提议IP地址的一个界面,然后假设这是互联网链接。然后,您可以向路由器询问该接口的流量计数。
当然,您会发现许多SOHO路由器不支持SNMP,而那些可能没有打开的SOHO路由器。
最好的方法是通过ETH0,ETH1或使用系统调用IFConfig的任何适配器找到“外部” IP地址。然后为任何系统(消息,syslog等)提取日志,并为该外部IP地址编写过滤器。为了使其变得更好,更便携,请编写一条正则是将仅用于公开可路由IP的过滤,并且只需过滤消息登录该“外部” IP地址。
您需要阅读 ifconfig(8) 的源代码,它描述了如何获取每个连接的网络接口的状态。
特别注意 in_status(),它获取接口的 inet 地址和网络掩码。
当流量中的源地址或目标地址与本地接口具有相同的主机时
int is_local =
(src && netmask) == (ifaddr && netmask)
|| (dst && netmask) == (ifaddr && netmask)
那么你可以确定它是本地的
http://www.opensource.apple.com/source/network_cmds/network_cmds-307/ifconfig.tproj/ifconfig.c
我认为,一个大致的解决方案:GetifAddrs可用于获取有关网络使用的统计信息。
它可以获取Wi-Fi和WWAN接口的单独统计信息。
您可能会从:
http://www.gsp.com/cgi-bin/man.cgi?section=3&topic = getifaddrs
这取决于您如何定义“本地”,但是一个常见的定义是查看网络掩码。
例如,如果您的IP(即,您监视的接口的IP是
10.33.52.123
netmask 255.255.255.0
这意味着每个具有源-IP和destination-ip 10.33.52.xx的IP包都是本地的。
我不知道可可或Objective-C,但是您可能可以使用其中一些功能来帮助您从IP地址提取网络: http://developer.apple.com/library/mac/#documentation/darwin/reference/manpages/man3/inet_network.3.html
不知道如何在Objective-C中实现它,但是您的想法是您获得了您所处网络的地址(您可以从本地IP或从网络类(a,b,c)中弄清楚这一点netmask中的位,如果不是标准),请检查传出连接的地址。如果目的地不在您的本地网络中,请计算流量;如果它进去,那就什么也不做。
有三个不可用的IP地址范围,它们通常用作NAT服务的地址范围。不可用的地址范围之一中不存在的任何地址都是外部地址。
当然,如果您不在NAT路由器后面,那么任务就更难了(从技术上讲,所有地址都短于127.0.0.1,此时也是外部的)。
不可用的IP范围是:
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255