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 早期底层使用的解析器)。

相关推荐
弈栈录4 分钟前
MySQL 事务、索引与锁:后端开发必须掌握的数据库基础
数据库·后端
明月_清风5 分钟前
AI Agent 最大的问题,可能不是智商,而是“权限”
人工智能·后端
vx_Biye_Design8 分钟前
expressDeepSeek社团咨询助手的学生社团管理系统60746-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·课程设计·express
长安米粒贵9 分钟前
缓存明明加了,为什么数据还是不一致?聊聊 4 个容易忽略的边界
后端
传人10 分钟前
悬停旋转放大和位移效果如何写
前端·javascript·css
yunwei3712 分钟前
eBPF 开发实践:使用 eBPF 隐藏进程或文件信息
linux·后端·性能优化
高频因子挖掘机14 分钟前
行情监控脚本重启后,怎样快速恢复而不重复拉取数据?
后端·github·api
aleafboat16 分钟前
只管去写(day2) 用claude分析老项目技术栈
后端
vx_Biye_Design22 分钟前
springboot宠物领养与救助平台64334-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·mysql·课程设计·宠物
用户77139702070624 分钟前
.NET 依赖注入入门
后端