监控不包括本地流量的网络使

时间:2010-11-25 23:31:57

标签: objective-c cocoa networking monitoring sysctl

我正在开发一款监控网络使用情况的应用。但是我发现很多方法都不允许排除本地流量(例如,Time Machine)。

我正在寻找一种排除本地流量的方法,并且仅监控直接进出互联网的使用情况。

更新:感谢您的回复,现在我知道如何查找流量是否为本地,但我仍然不知道如何计算总输入/输出字节(对不起,如果我之前没有详细说明)。我无法知道在特定时间段内或自OS启动以来在本地(或互联网)发送/接收的字节数。当OS运行时启动或终止事实过程会使这个问题变得更加复杂。

问题How to get network adapter stats in linux/Mac OSX?的答案提供了一种总结使用量的有趣方法,但它没有帮助,因为它总结的用法是界面统计。

更新2 :我已经发布了我的最终解决方案。请向下滚动一下以查看。

8 个答案:

答案 0 :(得分:2)

回答您对哪些接口带有本地流量的评论实际上很复杂,因为它取决于您对本地流量的含义。

“本地”意味着什么

“本地流量”最简单的含义是不会使机器生成的流量(例如,同一台机器上的两个程序相互通信)。这种流量都超过了。这是人们在说当地话时所说的一件事(当我回答时我想到的是什么)。

下一个最简单的含义是“发往同一子网上的计算机的IP流量”。那是在本地子网内有目的地址的流量。最简单的计算方法是路由表(如果Mac OS X计算每条路由的流量统计数据,各种网关上的路由将为您提供非本地流量)或者使用防火墙规则。 当他们说“本地流量”时,这可能不希望任何人意味着。

另一个含义是“用于此(物理)位置的机器的IP流量”。例如,在我的办公室,我们有几个正在使用的子网,它们之间有路由器,但是从一个子网到另一个子网的流量仍然是本地的。您需要网络知识来区分本地流量和非本地流量。

另一个含义是“发往我组织的机器的IP流量”。这是一个合理的含义,具体取决于您的网络设置方式(例如,您的位置之间可能有快速光纤,但您的Internet连接速度要慢得多,或按GB收费)。需要深入了解网络以确定目的地是否是本地目的 - 而且,对于像VPN这样的事情,可能会随着时间而变化。

最后,“互联网流量”并非与任何相反。有时候,例如,以太网网段上的本地计算机实际上是通过互联网上的VPN(这并不疯狂,它对于远程用户需要使用各种Windows服务时非常有用)。您组织内的流量可以轻松通过Internet VPN传输。

在简单网络中作弊

如果网络非常简单,只有一个内部子网,只有一个路由器,并且所有不属于该内部子网的流量都是互联网流量,您可以作弊并解决此问题。这可能适用于绝大多数家庭网络,以及许多小型企业网络。

使用防火墙规则

在简单的网络设置中,您可以做出一些假设,并通过将流量计为非本地来获得足够接近的答案:

  • 目的MAC地址是默认网关的MAC地址;和
  • 目标IP地址默认网关的IP地址

或者:

  • 目标IP地址不在默认路由熄灭的网络接口的子网中

您可以创建防火墙规则来计算其中任何一个。至少可以使用Linux iptables,我很确定BSD pf,可能还有Mac OS X.

替代方法:SNMP

最后,如果您不能使用防火墙规则(因为它需要root),您可能希望默认网关响应SNMP社区公共,浏览其所有接口,并找到具有子网外的接口IP地址,然后假设是Internet链接。然后,您可以询问路由器在该接口上的流量计数。

当然,您会发现许多SOHO路由器不支持SNMP,而那些可能没有开启的SOHO路由器。

答案 1 :(得分:1)

最好的方法是通过eth0,eth1或任何具有系统调用ifconfig的适配器来查找“外部”ip地址。然后为任何系统(消息,系统日志,等等)拉日志,并为该外部IP地址编写过滤器。为了使它更好,更便携,编写一个正则表达式,只过滤可公共路由的IP,只过滤消息记录该“外部”IP地址。

答案 2 :(得分:1)

您需要阅读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

答案 3 :(得分:0)

我认为,近似解决方案:getifaddrs可用于获取有关网络使用情况的统计信息。

它可以获得Wi-Fi和WWAN接口的单独统计信息。

您可以从以下网址找到更多信息:

http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=getifaddrs

答案 4 :(得分:0)

这取决于你如何定义“本地”,但常见的定义是查看网络掩码。

例如,如果您的IP(即您监控的接口的IP是

10.33.52.123
netmask 255.255.255.0

这意味着每个具有source-IP和destination-IP 10.33.52.xx的IP数据包都是本地的。

我不知道cocoa或objective-c,但您可以使用其中一些功能帮助您从IP地址中提取网络:http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/inet_network.3.html

答案 5 :(得分:0)

不知道如何在objective-c中实现它,但想法是你得到你所在网络的地址(你可以从你的本地网络类(A,B,C)中找到它) ip或来自网络掩码中的位(如果它不是标准的),然后只检查传出连接的地址。如果目的地不在您的本地网络中,则计算流量;如果它在,只是什么也不做。

答案 6 :(得分:0)

有三种不可路由的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

答案 7 :(得分:0)

我的最终工作解决方案是使用libpcap来实现这一目标。当然有一些缺点,包括它需要提升的权限,并且必须捕获所有过滤的数据包以计算统计数据,但至少它运行良好。

关于libpcap的许多文档和教程都相当透彻和明确,我建议每个对这个解决方案感兴趣的人都要看看那些google-fu努力相对较少的人。

此外,我的网络流量过滤器可能只是以下几点 -

- (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;
}

过滤器的设计有一些关于什么算作“本地流量”的答案,我知道它不包含一些边缘情况,如双NAT配置等,但我希望看到有关此的建议。 / p>

我知道net = [net stringByReplacingOccurrencesOfString:@".0" withString:@""];只是一个快速的黑客攻击,在某些特殊情况下很容易失败但是没有人在抱怨,至少现在还没有。