Web 3D地球实时统计访问来源

前言

这篇文章介绍一个Web 3D地球实时统计访问来源的开源项目,效果如下,当服务器有http流量进来时,web通过3D地球+飞线实时绘制客户端的来源

项目地址:github.com/houxinlin/l...

实现原理

要在服务器上捕获http流量,也就是抓包,抓包有两种方案,一是使用类似pcap的库从内核捕获网络数据包,另一种比较复杂是使用ebpf拦截系统的函数点,以检测流量,本项目是使用pcap实现。

要通过代码把流量抓下来,其实逻辑比较简单,大概如下

  1. 打开设备 (Open Device)
    首先得告诉程序我们要监听哪个网卡(比如 eth0 还是 wlan0)。这里通常需要开启混杂模式 ,否则网卡默认只会接收发给它自己的包,而忽略广播或其他流量。
  2. 设置过滤器 (Set BPF Filter)
    这一步很重要,服务器上的流量太杂了,SSH、数据库、等数据包。我们只想看 HTTP 流量,所以需要设置一个过滤规则,比如 tcp port 80 or tcp port 443。这用的就是 BPF (Berkeley Packet Filter) 语法,效率极高,直接在内核层就把不相关的包扔掉了。
  3. 循环抓包 (Loop)
    前两步配置好后,就是在一个死循环里不断地从句柄中读取数据包(Packet)。

伪代码大概长这样:

c 复制代码
// 1. 打开网卡 eth0,65535是最大捕获长度,1是开启混杂模式
handle = pcap_open_live("eth0", 65535, 1, 1000, errbuf);

// 2. 编译并设置过滤规则
pcap_compile(handle, &fp, "tcp port 80", 0, net);
pcap_setfilter(handle, &fp);

// 3. 每抓到一个包就回调 process_packet 函数
pcap_loop(handle, -1, process_packet, NULL);

pcap_loop 捕获到数据时,拿到手的是一堆原始的二进制字节,截获到的数据包,需要解析出以太网帧头,以太头由 14 字节固定长度构成,用于指明目标与源 MAC 地址,以及数据使用的上层协议类型,如下。

其中数据类型表示以太网帧中载荷(Payload)是什么协议的数据。

协议类型 十六进制 说明
IPv4 0x0800 表示数据部分是 IPv4 数据包
ARP 0x0806 地址解析协议
IPv6 0x86DD IPv6 数据包

在项目中,解析时直接跳过14字节去解析ip报文即可,因为用不到以太数据,解析到ip头后就可以获取客户端的地址了,ip头格式如下。

获取ip包信息代码如下

c 复制代码
void process(u_char *d, struct pcap_pkthdr *h, u_char *p) {
    struct ip *ip4_pkt = (struct ip *) (p + link_offset);
    uint32_t ip_hl = ip4_pkt->ip_hl * 4;
    uint8_t ip_proto = ip4_pkt->ip_p;
    char ip_src[INET_ADDRSTRLEN];
    char ip_dst[INET_ADDRSTRLEN];
    unsigned char *data;
    uint32_t len = h->caplen;

    inet_ntop(AF_INET, (const void *) &ip4_pkt->ip_src, ip_src, sizeof(ip_src));
    inet_ntop(AF_INET, (const void *) &ip4_pkt->ip_dst, ip_dst, sizeof(ip_dst));
 }

接下来拿到客户端的ip后,解析出ip的经纬度通过websocket发送到前端即可,经纬度有两种办法可以获取。

  1. 使用maxminddb

    他是一种离线的经纬度查询系统,但是测试后不太准确,优点是速度极快。

  2. 在线服务

    寻找大量的在线ip转经纬度服务,找到他的api接口,在程序中使用负载均衡(因为免费服务都要分钟内次数限制)

但是,目前广泛的做法是nginx做web监听,使用https 443端口,虽然抓包获取ip来源没问题,但是有时候我们想通过http请求头中的字段获取ip,比如真实的用户IP往往藏在HTTP请求头的 X-Forwarded-For 或者 X-Real-IP 类似的字段里,这就需要解析tcp数据包,从tcp的Payload中解析出http请求头信息。

c 复制代码
GET /api/v1/stats HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0...
X-Forwarded-For: 203.0.113.195
...

项目直接调用github.com/nodejs/http... 这个库去解析http头,他是被广泛验证的高性能 C 解析库(这也是 Node.js 早期底层使用的解析器)。

相关推荐
一灯架构5 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
小李子呢02115 小时前
前端八股CSS(2)---动画的实现方式
前端·javascript
mldong7 小时前
Python开发者狂喜!200+课时FastAPI全栈实战合集,10大模块持续更新中🔥
后端
GreenTea7 小时前
从 Claw-Code 看 AI 驱动的大型项目开发:2 人 + 10 个自治 Agent 如何产出 48K 行 Rust 代码
前端·人工智能·后端
渣渣xiong8 小时前
从零开始:前端转型AI agent直到就业第五天-第十一天
前端·人工智能
布局呆星8 小时前
Vue3 | 组件通信学习小结
前端·vue.js
C澒8 小时前
IntelliPro 企业级产研协作平台:前端智能生产模块设计与落地
前端·ai编程
OpenTiny社区9 小时前
重磅预告|OpenTiny 亮相 QCon 北京,共话生成式 UI 最新技术思考
前端·开源·ai编程
前端老实人灬9 小时前
web前端面试题
前端