Search code examples
objective-ccocoanetwork-programmingmonitoringsysctl

Monitoring network usage excluding local traffic


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.


Solution

  • 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 -

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

    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.