AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

有赞移动助手 App 本地抓包方案

  • 2019-07-21
  • 本文字数:4608 字

    阅读完需:约 15 分钟

有赞移动助手App本地抓包方案

一、概述

有赞移动助手(下面简称助手 App)网关切换功能(有赞移动 App 一键切换网关实践),在我们有赞移动整个开发,测试回归,产品回归验收等扮演着重要的角色,近期我们在 App 集成了本地抓包的功能,更是如虎添翼。在测试抓包,线上问题排查等场景发挥着重要的作用。

二、背景

在目前的抓包的场景中,大部分通过手机连接 PC,进行 IP 代理,用三方抓包工具(Charles,Fiddler,Wireshark 等)进行抓包,具体有如下痛点:


  • 抓包需要将移动设备的 Wi-Fi 设置中将代理手动设置成 PC 的 IP,和对应的端口号,过程比较繁琐

  • 移动设备需要安装 Charles 提供的 Root 证书

  • 不能随时随地的用移动设备抓包,必须强依赖于 PC 端


因此我们需要在 App 增加本地抓包的功能, 通过一种技术手段可以实时监听到通过移动助手网关功能连接到 ZanProxy 服务器的所有网络请求,经过调研,实现这个功能应该具备以下几个条件:


  • 利用 Socket 协议来实现消息推送经过助手 App 网关功能的网络请求到客户端

  • 当我们切换到其他 APP 进行网络请求时,要让助手 App 能在后台保活,甚至是常驻在后台,来达到对网络监听的目的

  • 需要在有赞助手有对应的页面去展示监听到的网络请求,header,response,request 等数据

三、有赞移动助手

我们助手 App 网关功能的原理是 Android 提供的 VpnService ,iOS 的 NetworkExtension 将 TCP 连接的 IP 数据包通过 tun2socks 转化成 socks5 代理,将数据转发到 ZanProxy 服务器中,实现整个网关功能。

3.1 tun2socks

tun2socks 实现一种机制,它可以让你无需改动任何应用程序而完全同名地机那个数据用 socks 协议封装,转发给一个 socks 代理,然后由代理程序负责于正式服务器之间转发应用数据。使用代理有两种方式,一种是显示配置代理,数据离开你的主机时它的目标地址就是代理服务器。另一种是做透明代理,即在中途把原始数据重定向到一个应用程序,由该代理程序代理转发。tun2socks 在第二种的基础上,完成了 socks 协议的封装,并且实现该机制时使用了强大的 tun 虚拟网卡而不必再去配置复杂的 iptables 规则,如下图所示


3.2 socks 代理

socks 运作原理,就是在 TCP 数据外包一层 socks 协议头,到达 socks 代理服务器后,脱去 socks 头,然后通过 socks 服务器与真实服务器之间建立的连接将 TCP 数据传给真实服务器,socks 代理并不理解任何应用层协议,它只是负责转发应用层数据而已,这一点使 socks 成为了一个通用的代理协议,这一点和 HTTP 代理服务器是完全不同。

四、技术方案

了解了整个流程以后我们回到最初的痛点,需要利用 Socket 协议来让服务器和 App 建立长链接,实时监听通过助手 App 网关的所有 http/https 请求

4.1 Websocket

WebSocket 是 HTML5 新增的一种通信协议。WebSocket 协议是一种持久化的双向通信协议,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大的不同有两点:


  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/UA 都能主动的向对方发送或接收数据,就像 Socket 一样,不同的是 WebSocket 是一种建立在 Web 基础上的一种简单模拟 Socket 的协议。

  • WebSocket 需要通过握手连接,类似于 TCP,它也需要客户端和服务器端进行握手连接,连接成功后才能相互通信。


下面是一个简单的建立握手的时序图:


4.2 Socket.IO

socket.io 是支持浏览器和服务器之间实时、双向基于事件通信的库,它包括 Node.js 服务端 API 和浏览器的 JavaScript 端的 API,是一个完全由 JavaScript 实现、基于 Node.js、支持 WebSocket 协议的用于实时通信、跨平台的开源框架。底层是基于 engine.io,在此基础上增加了 Namespace、room、自动重连等特性。


socket.io 设计的目标是支持任何的浏览器,任何 Mobile 设备。支持主流的 PC 浏览器 (IE,Safari,Chrome,Firefox,Opera 等),Mobile 浏览器(iphone Safari/ipad Safari/Android WebKit/WebOS WebKit 等)。socket.io 旨在使实时应用在每个浏览器和移动设备上成为可能,模糊不同的传输机制之间的差异。


但是,WebSocket 协议是 HTML5 新推出的协议,浏览器对它的支持并不完善,由此可以看出,socket.io 不可能仅仅是对 WebSocket 的实现,它还支持其他的通信方式,如上面介绍过的 AJAX 轮询和 Long Polling。根据浏览器的支持程度,自主选择使用哪种方式进行通讯。

4.2.1 Socket.io 支持的通信方式:

  • WebSocket

  • Adobe Flash Socket

  • AJAX long-polling

  • AJAX multipart streaming

  • Forever IFrame

  • JSONP polling

4.2.2 可靠性

socket.io 即使在下列情况下也能建立联系:


  • 代理和负载平衡器

  • 个人防火墙和杀毒软件

4.2.3 自动重连机制

除非有特殊指示,否则断开连接的客户端将尝试重新连接,直到服务器再次可用为止

4.2.4 断开检测

engine.io 级别实现心跳极值,允许服务器和客户端都知道对方何时不再响应。通过在服务器和客户端设置计时器,在握手连接期间共享超时值(pinginterval 和 pingTimeout 参数),可以实现该功能。

4.2.5 多路复用

为了在应用程序中创建关注点分离(例如每个模块,或者基于权限),socket.io 允许您创建多个名称空间,这些名称空间将作为单独的通信通道,但将共享相同的底层连接。


其他更多的包括,二进制的支持、房间支持等特性,由于想到以后的可扩展性以及客户端的支持程度,以及因此我们选择 socket.io 作为我们消息推送的技术方案。

4.2.6 源码分析

在建立连接后,每个客户端会被自动加入到一个默认的命名空间。在每个命名空间中,socket 会被默认加入两个名为 None 和 sid 的房间。None 的房间用于广播,而 sid 是当前客户端的 session id,用于单播。除默认的房间外,我们可以根据需要将对应 socket 加入自定义房间,roomid 唯一即可。socket.io 基于engine.io,支持 websocket 和 long polling。如果是 long polling,会定时发送 GET, POST 请求,当没有数据时,GET 请求在拉取队列消息时会 hang 住(超时时间为 pingTimeout ),如果 hang 住期间服务器一直没有数据产生,则需要等到客户端发送下一个 POST 请求时,此时服务器会往队列中存储 POST 请求中的消息,这样上一个 GET 请求才会返回。如果 upgrade 到了 Websocket 连接,则探测成功之后会定期 ping/pong 来保活连接。流程如下图所示:


4.3 Socket.IO 应用

在本次需求中移动端 iOS 用的开源库 socket.io-client-swift 是 swift 语言编写的。Andriod 端用的开源库 socket.io-android-chat 。下面以 iOS 为例看下如何使用:


 // MARK: Initializers
/// Type safe way to create a new SocketIOClient. `opts` can be omitted. /// /// - parameter socketURL: The url of the socket.io server. /// - parameter config: The config for this socket. public init(socketURL: URL, config: SocketIOClientConfiguration = []) { self._config = config self.socketURL = socketURL
super.init()
setConfigs(_config) }
复制代码


创建初始化 SocketManager 实例,指定 socketUrl ,指定对应的 nameSpace(名称空间)来保证单独的通信通道,将 UUID(设备唯一 id)当作 cookie 添加到 header 中,保证能够识别是哪台设备和服务端建立的 socket 通信,调用 connect 方法进行 socket 连接。


socket.on(clientEvent: .connect) { data, ack in            print("connect success")            YZVPNSettingsNetwork.bindDevice(deviceId: device ?? "")                .subscribe (                    onNext: {  response in                        print("websocket, 绑定成功 ")                },                    onError: { e in                        print("websocket, 绑定成功 ")                }            )        }
复制代码


在连接成功后将设备信息发到我们服务器进行设备的绑定。


socket.on("rows") { (data, ack) in            guard let cur = data[0] as? String else { return }            print(cur)        }        socket.on(clientEvent: .disconnect) {data, ack in            print("socket disconnect")        }        socket.on(clientEvent: .error) {data, ack in            print("socket error")        }        socket.on(clientEvent: .pong) {data, ack in            print("socket pong" + data.description)        }
复制代码


接下来就是各种事件的监听,进行相应的处理。我们这边和服务端约定好定义了名叫 rows 的事件,那么在该事件中就可以收到 http/https 请求的所有信息 originRequest、requestData、response 信息,那么如何将每个请求的信息对应起来呢?我们这里封装了一个名叫 HttpSession 的类如下:


class  HttpSession : HandyJSON {
var originRequest : String? var requestData : String? var response : String? var id : String? required init() {
}}
复制代码


返回的数据里面有 id 来作为每个 http/https 请求的唯一标示,当接收到数据时,用 id 进行本地映射,将数据塞入对应的 HttpSession 里面,当每个 HttpSession 对象的所有数据都被拿到时,我们再将该条请求信息展示出来。如下图所示:



以上整个本地抓包功能都已经完结,但是还有一个问题,我们去抓包肯定是打开别的 APP 将助手 App 退出到后台甚至是程序挂起状态,那么如何保证在助手 App 退出到后台模式后还能收到服务端推来的 socket 消息呢?那就需要让程序在后台长时间运行,iOS 有以下几种方法:


  • VOIP

  • Background Audio 后台播放音乐

  • Location Services 定位服务

  • Newsstand downloads 后台下载

  • Remote notifications 静默推送

  • 注册一个后台任务


一般而言,音乐应用在后台是避免 kill 的,如果在后台应用可用时间即将为 0 时,播放一段音乐,就会使应用变为假前端状态。可以尝试的解决方案如下:应用申请到后台执行任务后,使用 NSTimer 开启一个定时任务,主要负责监控应用剩余的后台可执行时间,当可用的时间少于一个值时,播放一段默声音乐,然后调用 UIApplication 对象的 beginBackgroundTaskWithExpirationHandler 方法将之前申请的后台执行任务结束掉,最后再重新申请一个后台执行任务,这样就可以实现后台不限时执行任务了


因此我们这边采用后台音乐和 beginBackgroundTaskWithExpirationHandler 方法保证 APP 能在后台不被 kill 。

五、总结

以上就是整个本地抓包涉及到的所有技术点,总结一下 App 如何完成本地抓包的流程:


  1. 当 App 通过 VpnService/NetworkExtension 配置 VPN 和定制、扩展核心网络功能

  2. 通过 tun2Socks,将请求 TCP 数据外包一层 socks 协议头,到达 socks 代理服务器后,脱去 socks 头,然后通过 socks 服务器与真实服务器之间建立的连接将 TCP 数据传给真实服务器,然后进行 ZanProxy 代理访问,完成一次 http/https 的完整请求

  3. 在整个请求过程中,我们用 Socket.IO 将服务端与 助手 App 建立长连接,将访问的 http/https 数据实时推送给 App 端

  4. 助手 App 监听长连接事件,拿到数据进行处理,展示出来


由于篇幅有限,期间还涉及到一些其他的技术点,有兴趣的同学可以去查阅对应的文献资料,也欢迎大家积极参沟通,写出这篇文章,是抛砖引玉,也是为了其他感兴趣的同学提供一些思路。


参考文献


https://socket.io/docs/logging-and-debugging/


https://socket.io/


本文转载自公众号有赞 coder(ID:youzan_coder)


原文链接


https://mp.weixin.qq.com/s/DY6c2_IBtG6XjKHZiNemdQ


2019-07-21 08:0016326

评论 1 条评论

发布
用户头像
类似的应用app store是有的,贵公司的app开源或者上架了吗
2019-07-22 11:01
回复
没有更多了
发现更多内容

专家推荐五个免费的网络安全工具

喀拉峻

网络安全 安全 渗透测试 渗透

社交泛娱出海新引擎,融云「六化」能力助开发者轻装上阵

融云 RongCloud

游戏出海 出海社交 出海

Java&Go三种HTTP客户端性能测试

FunTester

Java 性能测试 测试框架 Go 语言 FunTester

字节跳动亿级DAU客户端发布最佳实践

字节跳动终端技术

数据产品经理实战-指标体系搭建

第519区

数据产品经理 数据产品 指标体系 指标管理

大厂算法面试之leetcode精讲11剪枝&回溯

全栈潇晨

LeetCode 算法面试

【最全攻略】玩转2021LIGHT开发者云大会

恒生LIGHT云社区

技术 开发 行业 行业大会

一页纸需求的应对方法 —— 五步法

CODING DevOps

业务价值 角色梳理 术语定义 主业务流程梳理 纲举目张

dart系列之:数学什么的就是小意思,看我dart如何玩转它

程序那些事

flutter dart 程序那些事 11月日更

ONES Automation 流程自动化解决方案

万事ONES

自动化 SaaS

从双十一的物流大战,看全球通信网络的低延迟优化

融云 RongCloud

音视频 通信 低延迟 全球通信

react源码解析5.jsx&核心api

buchila11

React React Hooks

react源码解析6.legacy模式和concurrent模式

buchila11

React React Hooks

Linux一学就会之Vim编辑器的使用和Xmanager工具的使用。

学神来啦

vim Linux centos 运维 ext4

建立合格的跨职能团队,你需要知道这些!

禅道项目管理

团队 合作共赢

手把手带你写一个 Vue3 的自定义指令

CRMEB

混合云管理软件用哪个品牌好?咨询电话多少?

行云管家

Rust 元宇宙 9 —— 库和序列化

Miracle

rust 元宇宙

Python代码阅读(第66篇):两个列表的包含关系

Felix

Python Code 列表 阅读代码 Python初学者

WICC 广州高峰对话:为开发者标注「航海地图」

融云 RongCloud

开发 游戏 社交 泛娱乐 出海

创新模式驱动生产力提升,融云社交场景化 SDK 探索

融云 RongCloud

直播 sdk 语聊房 场景化

新思科技BSIMM12报告显示开源、云、容器安全活动增长显著

InfoQ_434670063458

新思科技 软件安全 BSIMM

看完这5个核心功能,你会明白低代码平台到底能解决什么问题!

J2PaaS低代码平台

低代码 低代码开发 低代码平台

行业视野 | ONES CEO 王颖奇对话极客公园张鹏

万事ONES

SaaS SaaS平台

元气部落盲盒小程序开发芒趣盲盒app开发

风行无疆

”微博评论“的高性能高可用计算架构设计

Steven

架构实战营

大厂算法面试之leetcode精讲12.堆

全栈潇晨

算法 LeetCode

【IT运维小知识】虚拟化vCenter是什么意思?有啥优势?

行云管家

你有一份「写作跨年」邀请函请查收 | 28天写作计划

TGO鲲鹏会

写作 技术创作 28天写作 内容创作 热门活动

高维数据世界|基于高维稀疏矩阵的潜在变量模型研究

索信达控股

算法 变量模型 模型介绍 高维数据

英特尔宋继强:秉持三个坚持,穿越技术周期,构建未来技术生态

科技新消息

有赞移动助手App本地抓包方案_移动_杨彬_InfoQ精选文章