【问题标题】:Monitoring network usage excluding local traffic监控不包括本地流量的网络使用情况
【发布时间】:2011-05-15 22:56:56
【问题描述】:

我正在开发一个监控网络使用情况的应用程序。但是我注意到很多方法都不允许排除本地流量(比如 Time Machine)。

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

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

How to get network adapter stats in linux/Mac OSX? 问题的答案提供了一种总结总使用量的有趣方式,但它无济于事,因为它总结的使用量是接口统计信息。

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

【问题讨论】:

  • 查看 lo 以外的接口上的流量。或者默认路由指向的那个。不确定如何使用特定于 Mac OS X 的调用来执行此操作(或者我会将其作为答案发布),但 Unix 工具可以做到...
  • 排除每个本地接口的子网应该做一个合理的工作。 getifaddrs(3) 应该没问题;您可能想要的唯一特定于 Mac 的东西是观察界面是否启动/关闭。
  • @derobert 谢谢,但其他接口不应该也有本地流量吗?
  • 我已经回答了你在一个答案中的评论而不是另一个评论,因为我的答案方式太长了,无法发表评论。

标签: objective-c cocoa networking monitoring sysctl


【解决方案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

【讨论】:

    【解决方案2】:

    回答您关于哪些接口承载本地流量的评论实际上很复杂,因为这取决于您所说的本地流量的含义。

    “本地”是什么意思

    “本地流量”最简单的含义是不会离开机器产生的流量(例如,同一台机器上的两个程序相互通信)。这交通都过去了。这是人们说本地时的意思(以及我回答时的想法)。

    下一个最简单的含义是“发往同一子网上的机器的 IP 流量”。那将是在本地子网内具有目标地址的流量。计算这一点的最简单方法是路由表(如果 Mac OS X 计算每个路由的流量统计信息,则各个网关上的路由将为您提供非本地流量)或使用防火墙规则。 这可能不是任何人说“本地交通”时的意思。

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

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

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

    简单网络中的作弊

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

    使用防火墙规则

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

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

    或者:

    • 目的IP地址不在网络接口的子网内默认路由出去

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

    替代方法:SNMP

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

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

    【讨论】:

    • 谢谢!这是一个非常好的答案。但我认为我应该放弃。我从 BSD 系统管理器的联机帮助页中检查了ipsw(IP 防火墙和流量整形器控制程序),但它不能用于提供有用的统计信息。许多现有的 linux 解决方案无法移植,因为它们使用了/proc/net。此外 SNMP 也不是我真正想要的,因为我的应用程序不面向专业人士。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

      • 谢谢!我看着getifaddrs。但这不是我想要的。我需要的是一种方法来分离 getifaddrs 不提供的本地和互联网流量统计信息。更糟糕的是,AF_LINK 系列(->ifa_data->ifi_obytes 和 ifi_ibytes)的统计数据结构是 32 位无符号整数,这意味着它们在统计数据超过大约 4 GB 后会溢出。
      【解决方案5】:

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

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

      10.33.52.123
      netmask 255.255.255.0
      

      这意味着具有源 IP 和目标 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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 自 1993 年以来未使用网络类。secure.wikimedia.org/wikipedia/en/wiki/…
        • 但这并不意味着你不能使用它=)
        • 如果你的网络掩码是 255.255.255.128,那是哪个网络类?
        • 如果您阅读了我的回答,它会说“或者如果它不是标准的,则来自网络掩码中的位”
        • 是的,但是您不能通过查看 IP 地址来假设网络掩码,您必须检查配置的掩码。
        【解决方案7】:

        不可路由的IP地址有3个范围,常用作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

        【讨论】:

        • 这不是真的;内部地址不必是 RFC1918 空间。很多时候,您会为网络上的机器(例如服务器)使用非 1918 空间。同一以太网段上从一台服务器到另一台服务器的流量仍然是本地流量,绝对不是互联网流量。
        【解决方案8】:

        我最终的工作解决方案是使用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 配置等,但我希望看到有关此的建议。

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

        【讨论】:

        • 嗨,亚当,您是如何告诉 iOS 在每次用户使用互联网时调用您的应用程序或您的代码的?
        • 我开发的应用程序不适用于 iOS。目前在 iOS 上是不可能做到这一点的。
        • 嗨@Adam KO 我不知道怎么做,但可以检查数据人和数据使用情况。无论如何谢谢:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-01
        • 2015-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多