使用脚本收发 protobuf 协议数据

使用,脚本,收发,protobuf,协议,数据 · 浏览次数 : 295

小编点评

**使用 shell 脚本进行 protobuf 二进制数据测试** **步骤 1:安装 pbjs** ```bash brew install nodebrew install npmnpm install -g protobufjsnpm install -g pbjspbjs ``` **步骤 2:加载 protobuf 二进制数据** ```bash pbjs msg.proto --decode ProbeIpv6Response ``` **步骤 3:提取设备 IP** ```bash jq -r '.selfAddr.addrV6' probe_v6.json240e:304:8183:2bcc:c16d:22d0:74ba:23e ``` **步骤 4:测试结果** ```bash echo jq -r '.selfAddr.addrV6' probe_v6.json240e:304:8183:2bcc:c16d:22d0:74ba:23e ``` **结果:** ``` 240e:304:8183:2bcc:c16d:22d0:74ba:23e ``` **总结:** 使用 shell 脚本可以测试 protobuf 二进制数据的设备 IP。通过以上步骤,您可以手动验证设备 IP,并从结果中获得有关设备 IP 的信息。

正文

问题背景

最近做了一个 ipv6 相关的功能,发现使用 getifaddrs 获取的本地 ipv6 地址有可能不是真实的网络 ipv6 地址:

例如上图中通过 getifaddrs 获得了多个本地 ipv6 地址,其中 <fe80> 开头的已知是本地 ipv6 地址,被排除;还有 <2408> 这种,其实也是 "假 ipv6" 地址,对应的设备并不能访问 ipv6 网络。

对于这种假 v6 地址,无法通过遍历的方式进行枚举排除,而一旦将 v4 网络环境错认为是 v6 环境,对后面的网络操作影响比较大。需要引入一种准确判断当前网络是否有 ipv6 访问能力的方法,为此 server 端同学专门给了一个判断接口。

probe_v6_addr

出于安全考虑,这里只列出接口名称部分:

http://xxx.xxxxxxxxxx.xxxxxxx.xxxxx.xxx/xxx/probe_v6_addr

访问这个接口有两种返回,当不存在 v6 网络环境时:

no v6 addr

当存在时,返回本机的 ipv6 地址:

$ curl -s http://xxx.xxxxxxxxxx.xxxxxxx.xxxxx.xxx/xxx/probe_v6_addr
+
%240e:304:8183:2bcc:c16d:22d0:74ba:23e??-
'2408:832e:c272:b36e:55bc:554a:8952:553e,
&240e:3a0:7005:6ae2:d05a:754a:c21b:6c35??+
%240e:310:915:d939:9041:c01c:82db:a043??-
'2408:832e:c271:3851:6926:e953:e741:b1a3??+
%240e:378:1e0c:db62:7088:a216:87c:4ccd??OP46C3:/

虽然有部分二进制信息干扰,但是 ipv6 地址部分还是看得比较清楚的。返回的地址和 ifconfig 的结果可以相互印证:

$ ifconfig | grep inet6
          inet6 addr: fe80::fc8e:84ff:fec0:1534/64 Scope: Link
          inet6 addr: 240e:505:7e01:2994:f43c:5fc9:609e:5de6/64 Scope: Global
          inet6 addr: fe80::f43c:5fc9:609e:5de6/64 Scope: Link
          inet6 addr: fe80::8fd0:cd9e:52cd:5bc3/64 Scope: Link
          inet6 addr: 2409:8100:7b00:5781:a4a8:71ce:b11:3c5e/64 Scope: Global
          inet6 addr: fe80::a4a8:71ce:b11:3c5e/64 Scope: Link
          inet6 addr: ::1/128 Scope: Host
          inet6 addr: fe80::29f8:41f:7564:501d/64 Scope: Link
          inet6 addr: 240e:404:7e01:5d77:29f8:41f:7564:501d/64 Scope: Global
          inet6 addr: fe80::3d14:7716:4771:88fa/64 Scope: Link
          inet6 addr: 240e:304:8183:2bcc:c16d:22d0:74ba:23e/64 Scope: Global
          inet6 addr: 240e:304:8183:2bcc:d8c5:dce4:a89c:8a88/64 Scope: Global

其中 ipv6 地址240e:304:8183:2bcc:c16d:22d0:74ba:23e/64在两边都存在。

protobuf

上面的接口确实是基于二进制数据的协议,虽然是私有协议,但是采用了 protobuf 来进行规范,在提高性能的同时,也保留了一定的通用性。

但是这样一来,往常惯用的 curl + shell 大法要失灵了,给测试和验证工作带来了不小的麻烦。

不过好在有 proto 文件,生成一段解析的 c++ 代码也不是不可能:

> cat msg.proto
message ProbeIpv6Request {
    string xxxxx     = 1;
    string xxxx      = 2;
    string xxxxxxxx  = 3;
    string xxxxxxx   = 4;
}

message V6AddrType {
    string addrV6 = 1;
    uint32 portV6 = 2;
}

message ProbeIpv6Response {
    string              xxxxx    = 1;
    V6AddrType          selfAddr = 2;
    repeated V6AddrType brosAddr = 3;
}

这个 proto 文件揭示了两点:

  • 该接口也是有请求数据的:ProbeIpv6Request,不过可以省略
  • 该接口的响应 ProbeIpv6Response 主要包含两部分:
    • selfAddr 是设备自己的地址,有且只有一个
    • brosAddr 是设备的广播地址,可能存在多个 (repeated)
    • 地址都是由一个字符串地址和一个整型端口组成

如果使用 protoc 程序根据 msg.proto 生成 c++ 代码,再写程序解析数据,就用不着写这篇文章了。毕竟那种方式太牛刀杀鸡了,下面演示一种使用 shell 脚本就能搞定 protobuf 协议的新方法。

pbjs

在介绍新方法之前,先介绍本文的主角 pbjs。首先是在 mac 上的安装:

brew install node
brew install npm
npm install -g protobufjs
npm install -g pbjs

pbjs 是 nodejs 提供的,用来将 protobuf 二进制数据转换为 json,所以需要先安装 nodejs、npm 环境,linux 上的安装大同小异,此处不再赘述。

执行成功后验证 pbjs 是否安装:

> pbjs
Usage: pbjs [options] <schema_path>

Options:
  -V, --version        output the version number
  --es5 <js_path>      Generate ES5 JavaScript code
  --es6 <js_path>      Generate ES6 JavaScript code
  --ts <ts_path>       Generate TypeScript code
  --decode <msg_type>  Decode standard input to JSON
  --encode <msg_type>  Encode standard input to JSON
  -h, --help           output usage information
> which pbjs
/Users/yunhai01/tools/node-v14.17.0-darwin-x64/bin/pbjs
> ls -lh /Users/yunhai01/tools/node-v14.17.0-darwin-x64/bin/pbjs
lrwxr-xr-x  1 yunhai01  staff    31B Apr 16 18:26 /Users/yunhai01/tools/node-v14.17.0-darwin-x64/bin/pbjs -> ../lib/node_modules/pbjs/cli.js

看起来这就是一个 node module 的软链接。

pbjs 的功能有很多,help 信息中已经罗列出来了,例如生成 js 代码 (--es5/--es6),生成 ts 代码 (--ts),不过最让我感兴趣的还是 --decode,意思是可以将数据解析为 json,下面用上一节的二进制数据做个练手,假设数据已经保存在名为 response.bin 的文件:

> pbjs msg.proto --decode ProbeIpv6Response < response.bin
{
  "selfAddr": {
    "addrV6": "240e:304:8183:2bcc:c16d:22d0:74ba:23e",
    "portV6": 47832
  },
  "brosAddr": [
    {
      "addrV6": "240e:333:6b00:b00e:38db:2815:306b:3d9b",
      "portV6": 18947
    },
    {
      "addrV6": "240e:333:1707:ca6f:24d3:61ae:86cf:a6fa",
      "portV6": 18112
    },
    {
      "addrV6": "2409:8a38:9002:70b3:19a3:66a3:d778:65cc",
      "portV6": 18780
    },
    {
      "addrV6": "2408:8266:700:1a62:8ad0:4097:9220:577b",
      "portV6": 18595
    },
    {
      "addrV6": "240e:3a0:9001:4013:99c0:11c4:7d3b:e8e5",
      "portV6": 18319
    }
  ]
}

哈哈,果然成功,过程异常丝滑!

jq

有了 json 数据就好办了,下面上 jq 提取设备 IP,假设已经将数据保存在了 response.json 文件中:

> jq -r '.selfAddr.addrV6'  probe_v6.json
240e:304:8183:2bcc:c16d:22d0:74ba:23e

和之前猜测的 IP 地址结果一致。

结语

pbjs 不光可以用来解析响应,也可以用来构造 protobuf 格式的请求,主要就是依赖它的 --encode 参数:

pbjs msg.proto --encode ProbeIpv6Request < request.json > request.bin

注意 --decode/--encode 一次只能处理一个消息类型,而协议文件中可能包括多个,所以需要为它指定要处理的消息名,之前使用的是 ProbeIpv6Response 消息,这里改为 ProbeIpv6Request 消息。

关于 request.json 文件,简单的可以直接手动构造,复杂的可以借助 jq --arg 动态生成,这方面详细的信息可以参考我之前写的这几篇文章:《用 shell 脚本做 tcp 协议模拟》、《使用 shell 脚本自动申请进京证 (六环外) 》。

至此 protobuf 二进制数据也不再是脚本不可触控的区域,有这方面接口测试需求的同学们快用起来吧 ~

后记

使用基于 pbjs 的脚本在 android 设备上验证上述接口后,能正确返回结果,并且发现了几个小问题,为后面写 c++ 代码接入铺平了道路,比起编译 sdk 再打 apk 包验证,成本实在是低太多了,pbjs 确确实实提升了我的效率。

参考

[1]. Protocol Buffers for JavaScript

[2]. 工作笔记:protobufjs使用教程,支持proto文件打包成typescript或javascript脚本

 

与使用脚本收发 protobuf 协议数据相似的内容:

使用脚本收发 protobuf 协议数据

服务器使用二进制的 protobuf 协议,如何使用脚本模拟请求?答案是将它转成 json 再用 jq 处理,一起来看看吧~

DBSAT脚本快速收集方法

DBSAT是Oracle官方提供的脚本,用于数据库的安全评估检查,用户可以放心下载使用。 下载链接具体参见MOS: Oracle Database Security Assessment Tool (DBSAT) (Doc ID 2138254.1) 下面介绍DBSAT脚本快速收集方法: 1.上传d

【VMware vSphere】使用RVTools中的PowerShell脚本创建导出vSphere环境信息的自动化任务。

RVTools 是 VMware 生态系统中一个非常受欢迎且免费的 Windows 实用工具,用于收集并显示 VMware vSphere 环境中的相关信息,如虚拟机、主机及集群等相关配置。RVTools 利用 VMware vSphere Management SDK 8.0 和 CIS REST

[转帖]OS Watcher (OSW)系统性能监控软件

https://www.anbob.com/archives/1143.html OS Watcher简称OSW(oswbb),用于收集并归档操作系统cpu,memery,disk io,network等相关信息的工具,是oracle提供的脚本工具集,全是shell编写,OSW内部是使用操作系统提供

Rancher系列文章-Rancher v2.6使用脚本实现导入集群

概述 最近在玩 Rancher, 先从最基本的功能玩起, 目前有几个已经搭建好的 K8S 集群, 需要批量导入, 发现官网已经有批量导入的文档了. 根据 Rancher v2.6 进行验证微调后总结经验. 1. Rancher UI 获取创建集群参数 访问Rancher_URL/v3/cluster

youtube-dl下载太慢了,我选yt-dlp

前言 最近过年嘛,过年前照例来下载一些贺岁歌曲,现在国内没啥人做贺岁专辑,这方面还得看马来西亚华人,他们每年都有出专辑,质量很不错! 国内平台自然是没有(或者不全的),需要在YouTube下载~ 之前我都是用Chrome插件下载完再使用脚本合并视频,有点繁琐,今年试试自动下载的黑科技~ 作为对比的这

使用python脚本玩转古早TCAD软件(待更新)

前言 TCAD(Technology Computer Aided Design),虽然原名中没有与半导体器件有关的词汇,但这种软件便是半导体工艺模拟及器件模拟的工具,可以说是EDA软件的一种。TCAD软件同其他EDA软件一样,底层需要复杂的数学模型和数物模型支撑,能大幅减少半导体制造的研发成本,为

使用shell脚本在Linux中管理Java应用程序

目录前言一、目录结构二、脚本实现1. 脚本内容2. 使用说明2.1 配置脚本2.2 脚本部署2.3 操作你的Java应用总结 前言 在日常开发和运维工作中,管理基于Java的应用程序是一项基础且频繁的任务。本文将通过一个示例脚本,展示如何利用Shell脚本简化这一流程,实现Java应用的一键式启动、

使用 shell 脚本拼接 srt 字幕文件 (srtcat)

将多个 srt 文件拼接成一个,找了好多工具,都太重了,自己用 shell 手搓一个。一开始没觉得这个小工具有多么难,以为半天肯定能搞定,结果足足搞了三天。绊倒我的居然是时间字段的拆分和前导零的删除,看看 shell 里有多少种实现方案,以及我为何选择了当前的方案。

使用 shell 脚本自动申请进京证 (六环外)

活动在帝都的外地车对进京证应该不陌生,六环外进京证虽然不限次数,但是超过中午就办不了当天的了,你是否还在为出门前才发现忘了办理当天的进京证而懊恼?你是否为办理每周的进京证定过闹钟?如今这一切不堪回首都将过去,欢迎使用 jinjing365 自动办理六环外进京证。