这个需求也算是 V2EX 上的常客了,我详细说一下思路和方向。
Linux 网络栈是在内核里实现的,流量统计就是 packet 计数(或者计量)这个计数有几个方式:
1. 内核态 pf 用户态 iptables
最简单的方式就是 iptables 对 chain 计数,只要把想统计的流量走一下自定义的 chain (这个 chain 可以什么都不做),就可以利用 chain 自身计数达到目的。
像 openwrt 之类的路由器统计内网流量基本都是这个方式,用 arp 配合 MAC 地址来区分客户端。
这个方式的优点是轻量,缺点是要预先设定规则。你的这个场景,如果几个朋友的 IP 有比较明显的区分度,可以根据 IP 段每个人走一个规则 chain 来统计。但是对于大量无规律来源 IP 就很难写这个规则,或者写出来几万条不实际。
2. conntrack
想要动态处理 ip 规则,就需要做基于状态的统计。conntrack 有自己维护一套映射表,这样就无需预先知道来源 ip 就可以按需统计。优点是灵活性比较高,但是性能影响也会比上一个方法高一些。
这两个方法的实现可以参考
https://openwrt.org/docs/guide-user/services/network_monitoring/bwmon 这个帖子 Available tools 章节,可以参考拿来用。
第一个方案其实很好写,第二个要想自己写可能需要比较多的背景知识。
3. 抓包自己算
就是计量的方式,不是很推荐的做法,为了做流量统计结果把所有数据包都过滤一遍,有点杀鸡用牛刀的意思了。