监控网络使用情况(不包括本地流量)
我正在开发一个监控网络使用情况的应用程序。然而,我注意到许多方法都不允许排除本地流量(例如,时间机器)。
我正在寻找一种排除本地流量的方法,并且仅监视直接进出互联网的使用情况。
更新:谢谢您的回复,现在我知道如何查找流量是否是本地的,但我仍然不知道如何计算总输入/输出字节(抱歉,如果我没有之前详细阐述过)。我无法知道在特定时间段内或自操作系统启动以来本地(或互联网)发送/接收了多少字节。由于操作系统运行时进程会启动或终止,这个问题变得更加复杂。
问题的答案 如何获取网络适配器统计信息linux/Mac OSX? 提供了一种有趣的方式来总结总使用情况,但它没有帮助,因为它总结的使用情况是接口统计信息。
更新 2:我已经发布了我的最终解决方案。请向下滚动一点查看。
I am working on an app that monitors network usage. However I noticed many ways to do this does not allow exclusion of local traffic (say, Time Machine).
I am looking for a way to exclude local traffic, and only monitors usage that goes directly to/from the internet.
Update: Thank you for your replies, now I know how to find if the traffic is local, but I still don't know how I can calculate total in/out bytes (sorry if I didn't elaborate earlier). I have no way of knowing how many bytes are sent/received locally (or to the internet) in a certain period of time, or since the OS starts. This problem is further complicated by the fact processes are launched or killed when the OS is running.
The answer to the question How to get network adapter stats in linux/Mac OSX? gives an interesting way of summing up total usage but it doesn't help because the usage it sums up are interface statistics.
Update 2: I've posted my final solution to this. Please scroll down a bit to see.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您需要阅读 ifconfig(8) 的源代码,它描述了如何获取每个连接的网络接口的状态。
特别注意 in_status(),它获取接口的 inet 地址和网络掩码。
当流量中的源地址或目标地址与本地接口具有相同的主机时
int is_local =
(src && 网络掩码) == (ifaddr && 网络掩码)
<代码>|| (dst && netmask) == (ifaddr && netmask)
那么你可以确定它是本地的
http://www.opensource.apple.com/source/network_cmds/network_cmds-307/ifconfig.tproj/ifconfig.c
you need to read the source for ifconfig(8), which describes how to get the status of every attached network interface.
pay particular attention to in_status(), which gets the inet address and netmask of an interface.
when the source or destination address in the traffic has the same host as a local interface
int is_local =
(src && netmask) == (ifaddr && netmask)
|| (dst && netmask) == (ifaddr && netmask)
then you can be sure that it is local
http://www.opensource.apple.com/source/network_cmds/network_cmds-307/ifconfig.tproj/ifconfig.c
回答您有关哪些接口承载本地流量的评论实际上很复杂,因为这取决于您所说的本地流量的含义。
“本地”的含义
“本地流量”最简单的含义是不离开其生成的计算机的流量(例如,同一台计算机上的两个程序相互通信)。这些流量都过去了 lo。这是人们说本地时所指的一件事(也是我回答时所想到的)。
下一个最简单的含义是“发往同一子网上的计算机的 IP 流量”。那将是具有本地子网内的目标地址的流量。最简单的统计方法是使用路由表(如果 Mac OS X 计算每个路由的流量统计数据,则各个网关上的路由将为您提供非本地流量)或使用防火墙规则。 这可能不是任何人所说的“本地流量”时的意思。
另一个含义是“发往此(物理)位置的计算机的 IP 流量”。例如,在我的办公室,我们有几个正在使用的子网,它们之间有路由器,但从一个子网到另一个子网的流量显然仍然是本地的。您需要网络知识来根据此定义区分本地流量和非本地流量。
另一个含义是“发往我组织中的计算机的 IP 流量”。这是一个合理的含义,具体取决于您的网络设置方式(例如,您的位置之间可能有快速光纤,但您的互联网连接速度要慢得多,或者按 GB 收费)。需要对网络有深入的了解才能确定目的地是否是本地的,并且对于 VPN 之类的东西,可能会随着时间的推移而变化。
最后,“互联网流量”不是与其中任何一个相反。例如,有时,以太网段上看似本地的计算机实际上是通过 VPN、通过 Internet 进行的(这并不疯狂,当远程用户需要使用各种 Windows 服务时,它非常有用)。您组织内部的流量可以轻松地通过 Internet VPN 传输。
简单网络中的作弊
如果网络非常简单,只有一个内部子网,只有一台路由器,并且所有未到达该内部子网的流量都是 Internet 流量,则可以作弊并解决此问题。这可能适用于绝大多数家庭网络,以及许多小型企业网络。
使用防火墙规则
在简单的网络设置中,您可能可以做出一些假设,并通过将流量计数为非本地来获得足够接近的答案,如果:
或者:
您可以创建一条防火墙规则来计算以下任一情况那些。至少使用 Linux iptables 可以,而且我很确定 BSD pf,可能还有 Mac OS X。
替代方法:SNMP
最后,如果您不能使用防火墙规则(因为这需要 root),您可以希望默认网关响应 SNMP 社区公共,探索其所有接口,找到具有子网外 IP 地址的接口,然后假设该接口是 Internet 链路。然后您可以向路由器询问该接口上的流量计数。
当然,您会发现许多 SOHO 路由器不支持 SNMP,而支持 SNMP 的路由器可能也没有打开它。
Answering you comment about which interfaces carry local traffic is actually complicated, because it depends on what you mean by local traffic.
What “Local” Means
The easiest meaning of "local traffic" is traffic that does not leave the machine its generated on (two programs on the same machine talking to each other, for example). This traffic all goes over lo. This is one thing that people mean when they say local (and what I was thinking of when I answered).
The next easiest meaning would be "IP traffic destined to machines on the same subnet". That'd be traffic that has a destination address inside the local subnet. The easiest way to count this is going to be either the routing table (if Mac OS X counts traffic stats per route, the routes on the various gateways will give you non-local traffic) or with a firewall rule. This probably isn't want anyone means when they say "local traffic".
Another meaning would be "IP traffic destined to machines in this (physical) location". E.g., at my office we have several subnets in use, with routers between them, but traffic from one subnet to the other is still clearly local. You need network knowledge to distinguish local from non-local traffic with this definition.
Another meaning would be "IP traffic destined to machines in my organization". This is a reasonable meaning depending on how your network is set up (e.g., maybe you have fast fiber between your locations, but your Internet connections are much slower, or charged per-GB). Requires in-depth knowledge of the network to figure if a destination is going to be local or not—and, with things like VPNs, that may vary over time.
Finally, "Internet traffic" isn't the opposite of any of those. Sometimes, for example, what appears to be a local machine on your Ethernet segment is actually over a VPN, over the Internet (this isn't crazy, it's very useful for when remote users need to use various Windows services). Traffic inside your organization can easily travel over an Internet VPN.
Cheating in Simple Networks
If the network is very simple, with there being only one internal subnet, only one router, and all traffic not to that internal subnet being Internet traffic, you can cheat and solve this. This probably applies to the vast majority of home networks, and many small business ones as well.
Using firewall rules
In a simple network setup, you can probably make some assumptions, and get a close enough answer by counting traffic as non-local if:
alternatively:
You can probably create a firewall rule to count either of those. At least with Linux iptables you can, and I'm pretty sure BSD pf, and probably Mac OS X.
Alternate Approach: SNMP
Finally, if you can't use a firewall rule (as that'd require root), you could hope that the default gateway responds to SNMP community public, explore all its interfaces, and find the one with a off-subnet IP address, and then assume that is the Internet link. Then you can ask the router for traffic counts on that interface.
Of course, you'll find that many SOHO routers don't support SNMP, and those that do probably don't have it turned on.
最好的方法是通过 eth0、eth1 或任何具有 ifconfig 系统调用的适配器来查找“外部”IP 地址。然后提取任何系统的日志(消息、系统日志等)并为该外部 IP 地址编写过滤器。为了使其更好、更便携,请编写一个正则表达式,仅过滤可公开路由的 IP,并仅过滤该“外部”IP 地址的消息日志。
The best way is to find the 'external' ip address through the eth0, eth1, or whatever adapter with a system call to ifconfig. Then pull logs for whatever system (messages, syslog, whatever) and write a filter for that external ip address. To make it nicer and more portable, write a regex that will filter for publicly routable IPs only and just filter messages log for that 'external' ip address.
我认为,一个近似的解决方案: getifaddrs 可用于获取网络使用情况的统计信息。
它可以获取 Wi-Fi 和 WWAN 接口的单独统计信息。
您可以从以下位置找到更多信息:
http://www. gsp.com/cgi-bin/man.cgi?section=3&topic=getifaddrs
I think, an approximate solution: getifaddrs can be used to get statistics on network usage.
It can get separate statistics for Wi-Fi and WWAN interfaces.
You might find more information from :
http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=getifaddrs
这取决于您如何定义“本地”,但常见的定义是查看网络掩码。
例如,如果您的IP(即您监控的接口的IP)
意味着每个源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
It depends on how you define "local", but a common definition would be to look at the network mask.
For example, if your IP (ie the IP of the interface you monitor is
that would mean every IP-packet with both source-IP and destination-IP 10.33.52.xx is local.
I don't know cocoa or objective-c, but you can probably use some of these functions helping you extract the network from an IP-address: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/inet_network.3.html
不知道如何在 Objective-C 中实现它,但想法是你得到你所在网络的地址(你可以从基于你本地 ip 的网络类(A,B,C)中找出这个地址或从网络掩码中的位(如果不是标准的),然后只需检查传出连接的地址。如果目的地不在您的本地网络中,则计算流量;如果它在,则什么都不做。
Don't know how to implement it in objective-c but the idea is that you get the address of the network you are in (you can figure this out from network class(A,B,C) based from your local ip or from bits in netmask if it's not standard), then just check the outgoing connection's address. If the destination is not in your local network, calculate traffic; if it's in, just do nothing.
不可路由的 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
There are three ranges of non-routable IP addresses, and they are commonly used as the address ranges for NAT services. Any address that is not in one of the non-routable address ranges is an external address.
Of course if you are not behind a NAT router, the task is harder (and technically all the addresses short of 127.0.0.1 are external at this point).
The non-routable IP ranges are:
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255
我最终的工作解决方案是使用 libpcap 来实现这一点。当然,它也有一些缺点,包括它需要提升权限,并且必须捕获所有过滤的数据包来计算统计数据,但至少它工作得很好。
关于 libpcap 的许多文档和教程都相当全面和清晰,我建议每个对此解决方案感兴趣的人都可以看看那些相对较少的 google-fu 工作。
另外,一些人可能会感兴趣,我的互联网流量过滤器如下 -
该过滤器是根据一些关于什么算作“本地流量”的答案设计的,我知道它不包含一些边缘情况,例如双 NAT 配置,等等,但我想看到有关此的建议。
我知道
net = [net stringByReplacingOccurrencesOfString:@".0" withString:@""];
只是一种快速破解,在某些特殊情况下很容易失败,但是嘿没有人抱怨,至少没有人抱怨然而。The final working solution I have is to use
libpcap
to achieve this. Of course there are some downsides, which includes it requires elevated privileges and must capture all filtered packets to calculate statistics, but at least it works perfectly well.Many documentations and tutorials on
libpcap
is fairly thorough and clear, I suggest every one interested in this solution to look at those with relatively little google-fu effort.Also it may interest a few that my filter for internet traffic is simply the following -
The filter is designed with some of the answers about what counts as 'local traffic', I know it does not encompass some edge cases such as double NAT configurations, etc., but I would like to see suggestions about this.
I know
net = [net stringByReplacingOccurrencesOfString:@".0" withString:@""];
is just a quick hack which could easily fail under some peculiar circumstances but hey no one is complaining, at least not yet.