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

相关推荐
王中阳Go6 小时前
两个入口答案不一致先别调模型:6 行入口口径对账表(附脚本)
人工智能·后端·python·大语言模型·1024程序员节
小poop6 小时前
CSS 基础与实战:从入门到精通网页美化
前端
码事漫谈7 小时前
消除AI幻觉,普通人能做的五件事
后端
Csvn7 小时前
运行时性能
前端
Never_every998 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck9 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
金銀銅鐵9 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
空中湖9 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
Mk5987811 小时前
给 Agent 装上对话框 —— AgentScope-Java 接入 Spring Boot 与 SSE 流式实战
后端
付威202311 小时前
从 Loop 到 Runtime:rpi Agent Loop 与 Cordis 的边界、取舍与组合
后端