前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >模拟请求|协议复现方案

模拟请求|协议复现方案

作者头像
愧怍
发布2022-12-27 20:45:43
7080
发布2022-12-27 20:45:43
举报

前段时间看了别人的一个写了羊了个羊刷次数网页版,但是 js 代码做了混淆,然后我的那个解混淆的工具还没适配上,短时间内还原不了。但由于是网页版,所以抓包数据还是能看到的,于是就准备复刻了一个(其实就没有也照样能写出来,因为确实没啥难度)。

可在此体验:7y8y.vercel.app (当然由于官方改动,现在功能已经失效了,但看看页面到不成问题,可能需要访问国外网站)

原本我是不考虑写的,但是这背后所涉及到的技术以及技术框架我是特别想聊聊,加之以后我也有很大的可能会再写一个类似的刷 xx 的网页版,所以就考虑写一个类似的模板以便后续应用需求。

相关模板:https://github.com/kuizuo/protocol

与此同时,我也快有半年的时间没碰协议复现(网络通信协议重新实现,后文都简称协议复现)。我更喜欢说这个词,也有的人会说模拟请求,对应的关键词可能有 post 请求,抓包,发包,爬虫等等,但大致的意思是抓取请求数据包,然后脱离宿主机(浏览器,手机),将抓取的数据包重新发送一遍

你也可以理解成爬虫,但和爬虫相比,要做的不只是爬取数据,而是要基于某些请求包(或者说调用他人不提供的 api 接口,即爬取),来实现一定的功能。比如登录协议,签到协议,抢购协议,游戏封包等等,然后不依靠宿主机(即不用登录浏览器或者应用设备)就能实现诸如登录,签到等功能(在后台记录是有的)。因为这些都是基于网络通信协议的,只要抓包(抓取数据包),然后使用编程提供的网络请求模块来模拟请求,达到重新发包,重新请求的目的。在网页中有 http 协议,websocket 协议,而游戏中有相应的与游戏服务器对应的协议,邮件短信文件又是不同的协议(这里的协议都叫网络通信协议),所以我个人更倾向于称之为协议复现。

所以要做协议复现,那基本上有一定的逆向功底和爬虫能力,还有网络通信协议相关的知识了。此次的开发也算是回顾下这些相关技术了。

危险

注:本项目仅用于学习研究使用,请勿将本项目的任何内容用于商业或非法目的,否则后果自负。

在这里容我多废话几句,讲一个我之前的开发经历,可以说这个开发经历算是这篇文章的由来。

小区开门应用

应用需求

在之前住的一个小区,有个门禁系统,需要安装一个开门的 app(后文都称开门 app),然后注册一个账号到物业那边登记为户主或家庭成员。

每次开门的时候,都需要打开这个开门 app,然后点击你要的开的门,接着门就打开了。或者叫保安开个门,总之就是特别麻烦,还不提供创建应用快捷方式。

于是我想的是将接口数据“偷”了过来,将大门列表展示在前端上,然后点击对应的大门,然后将大门 id 转发给原 app 的服务器,就实现了开门的效果,也就是这个小区开门的网页版的核心逻辑。

大致界面如下,展示小区的大门,点击即可开门(远程)

因为是网页版的,所以只需要在浏览器打开对应的网址,点击大门即可(主要还是这个 app 不提供桌面快捷方式,点击这个 app 还需要观看首屏广告,手机网页浏览器提供某个网站的快捷打开) 。此外他人也不用到物业登记,就能开门,对于一些朋友或者住户来说,省去了物业登记的繁琐。

不过这个软件还是有挺多要注意的点:首先就是鉴权了,由于我当时主要目的是为了我自己和身边朋友,网站也没有特意发布到互联网上,所以就没做鉴权相关的,不然正常情况下是一定要做鉴权和调用记录的,以及 ip 白名单的。否则搞不好登录原 app 的账号直接因为调用过于频繁直接给禁用了;最主要的安全问题,这里的安全可不只是网站的安全,而是现实的安全。想想如果有一个可以随意进出小区大门的程序,那么任何人都可以进入这个小区,小区的公共设施,业主生活质量安全等等谁来保障?而且最主要所绑定的账号还是我的,万一小区真出了事,那么我的责任将会非常大。

综合考量,这个应用是绝对不可能大肆发布到网上的。个人自用问题还是不大,因为这种调用量对服务器几乎没有什么压力。

我的初衷也仅仅只是因为作为开发者的我,降低了我点击开门的频率,免去登记的繁琐。

在当时我甚至想基于手机的 GPS 定位,来实现靠近小区自动开门。真羡慕当时我的一堆想法,但也遗憾当时没有去尝试实现这一个想法。

开发

这个应用就大致初衷就说到这了,接下来我要说说开发,这也就是本文说要的重点内容了。下面是我当时的项目结构:

不难看出,这是一个前后端分离的项目,其中前端使用 uniapp 来开发一套代码多端运行,并且使用的是 Hbuilder 编辑器来开发。而后端就是常规的 Node 后端服务,使用的是 Express 框架。

技术栈就介绍完毕,这里我要介绍整个流程。

就说说获取大门列表和开门的两个接口请求:

获取大门列表

后端接口:http://localhost:3000/api/list

这个接口主要的作用就是获取原开门 app 的大门列表,这里简单介绍下代码

router.get('/list', async (req, res, next) => {

  // 模拟请求获取所有大门数据
  let url = `https://xxx.com/api/getDoorList`
  let data = {
    xxx: {}
  }

  let json = await (await axios.post(url, data)).data

  return json // [{...},{...},{...}]
})

然后前端请求后,将列表数据渲染到页面上。

开门请求

后端接口:http://localhost:3000/api/open

router.get('/open', async (req, res, next) => {
  let { id } = req.query

  // 模拟请求开门
  let url = `https://xxx.com/api/openDoorControl`
  let data = {
    id: id
  }

  let json = await (await axios.post(url, data)).data

  return json // { "code": 0 ,"msg": "success" }
})

这里的代码也仅仅只是作为演示,实际代码可不止这么简单,因为还需要涉及到登录,加密等等环节。

我的前端页面访问地址是 http://localhost:5000,我需要 http://localhost:3000/api/list 和 http://localhost:3000/api/openDoor。

可能有些人会问,为啥要后端服务,不直接在前端向开门 app 的服务器发送请求,然后将响应直接渲染到前端上。比如直接在前端代码中写 openopenDoor 函数

async function openDoor(id) => {

  // 模拟请求开门
  let url = `https://xxx.com/api/openDoorControl`
  let data = {
    id: id
  }

  let json = await (await axios.post(url, data)).data

  return json // { "code": 0 ,"msg": "success" }
})

这个疑惑在我初次想使用 web 端来实现协议复现的时候也考虑过,但浏览器不支持。这也是我下面所要说的

同源策略 跨域

一般用户的浏览器是有非常强的页面安全策略的,这里要说的就是同源策略,更细分点就是跨域,比如说 kuizuo.cn 这个站点,想要向 baidu.com 发送请求,请求是能够正常发送过去的,但是 kuizuo.cn 这个站点是接收不到任何数据。因为 kuizuo.cn 和 baidu.com 根本不是同一个网址,专业点说就是不同源,这种不同源的请求在浏览器,称为跨域请求。

跨域请求如果请求的服务端不允许跨域,即响应协议头没有如下内容

access-control-allow-credentials: true
access-control-allow-headers: Content-Type, Authorization, X-Requested-With
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
access-control-allow-origin: *

浏览器会直接拒绝接收响应,但浏览器确实将请求发送给了服务端(打开控制台中的网络是看不到该请求的响应结果的)。

跨域限制只存在于浏览器端,在其他环境下是不存在,请求都是能够发送出去,并且是可以接收到的。所以说为什么不在前端直接向原应用程序的服务器发送请求,罪魁祸首也就是同源策略

不支持修改协议头

像 origin,reference,user-agents 等协议头是无法修改的

origin: https://xxx.com
referer: https://xxx.com/api/test
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.42

而有些请求是会效验你的设备信息,来源地址,这些内容在浏览器中都写在协议头中,且浏览器不支持修改。使用浏览器来发送数据,无疑就是告诉服务器我是浏览器发送的。服务器判断来源不是自家的域名,那就直接拒绝响应。像防盗链就是检测 referer 。

方案

桌面端应用开发

正是因为同源策略的限制,导致做协议复现时往往都会选择在本地中直接运行,比如使用易语言,python 等语言,将应用打包成 exe,然后跑在 window 系统上。

这样的应用会有以下几点缺陷:

  • 易破解:由于你的大部分核心逻辑最终都会进行编译打包成 exe,如果会些破解技术,恰好你不做任何防护手段,要破解你的程序非常容易。所以也就为什么很多 exe 程序(尤其是易语言)会带有 .vmp.exe 也就是 vmp 加壳,让程序很难被分析与破解。并且我就可以开启系统抓包,就可以看到应用程序模拟发送的请求数据包是什么。
  • 不易跨平台:大多数的协议复现都是 exe 桌面应用程序,虽然也有安卓,但一般比较少。对于非 windows 用户或者说手头不方便用电脑的用户就很难体验到,并且还要特意安装一个应用,应用程序更新也需要重新安装。

其实我说的这些,也算是绝大部分都是桌面应用程序的一个“通病”,但也不是没有优点,这在后面介绍后端应用开发的会做一个比较。

后端应用开发

另一种方式就是我自行搭建一个后端服务,然后将我要模拟的请求封装成一个接口供外部调用。只要我的这个后端服务允许跨域请求,那么我在浏览器或者在桌面端应用都能调用该接口。这样做调用者根本不可能知到你这个接口返回的数据的核心代码(除非他能渗透你的服务器)。

别人像要复现一个相同的协议请求的话,就必须自行抓包分析原站点的数据。而原站点可能做了一定的防护手段,例如验证码 浏览器指纹等风控手段。对于一般人而言,非常难破解。但是假设你能复现该请求的话,又非常不想让别人复现,那么自行搭建一个后端服务封装是最好的手段。而在此基础上,你可以做一些限制,比如接口封装,调用收费等等。

这里我就不细说太多了,但也不是说没有缺点,甚至可以说这个缺点不比桌面端应用好到哪里:

  • 部署后端服务:由于搭建了一个后端服务,那么就需要将后端服务部署到服务器上,部署后端服务是小事(但其实也很麻烦,有些写协议复现也不一定会后端开发),但是需要考虑用户的访问量,可能并发量大,那么请求就可能会阻塞导致响应速度变慢。
  • 请求限制:从上流程图也不难看出,由于后端应用是部署在自己的服务器上,同时需要承载多个接口请求,然后模拟的请求都是由自己后端应用服务器发送的,这和桌面端应用不同。桌面端模拟的请求发送是用户自己的电脑,即用户自己电脑的 ip 地址,而后端应用服务器是服务器的 ip。一旦发送的请求多了,必然是会限制请求的,说白了就是将 ip 黑了,无法访问。要解决的最有效的办法就是换 ip,使用一些 ip 代理服务商,在请求 xx 服务器的时候使用动态 ip 来请求,检测被黑 ip 之后就换另一个 ip 来请求,但是这样就需要额外支付一些 ip 的费用。

如果你需要跨平台(web 端,桌面端,手机端)并且想要保护好你的模拟请求的代码,那么就要考虑选择后端应用开发方案。

像我一开始所介绍的小区开门网页版就是属于这一范围,这里就不再赘述其实现过程了。

前端应用开发/反向代理(可行)

假设你手头已经有了某个网站的大部分协议复现的代码接口,但是不想搭建一个后端应用,却想要在前端中使用。有没有解决方案,这也是有的。

一种就是通过浏览器插件来允许任何请求跨域,或者本地开启 http 响应替换,将允许跨域的协议头加到响应中。但这些手段都需要使用者有一定的开发能力,对于普通用户而言就无能为力。

目前绝大多数的网站应该都属于前后端分离的形式,后端只提供服务与接口的,提供的接口一般都带有 /api//v1/ 等请求前缀。那么就可以将前端的请求,通过反向代理,转发到原应用服务器。

反向代理其实也需要服务器,但是和后端应用相比,只需要配置一个 nginx,例如

location /api/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://要转发的服务器域名/api/;
    index index.html index.htm index.jsp;
}

举个例子,原后端应用通过 http://target.com/api/user/me 来获取目标服务器用户信息,如果我的前端应用 http://example.com 想要请求该接口必然会有跨域限制。但是通过反向代理,我的前端应用可以请求 http://example.com/api/user/methods,nginx 会判断 url 是否为 /api/ 前缀,将请求转发给 http://target.com/API。说白了请求 http://example.com/api/user/me 就是在请求 http://target.com/api,同时还不会触发跨域,反向代理也是解决跨域的常用方法之一。

由于请求还是通过服务器发送的,所以后端应用开发有的限制,在反向代理也同样是有的。还有就是对于限制设备请求的服务器,使用这种方案就不行。。。

同时这种开发方案对于多域名的应用来说可能就不是那么友好,因为就需要配置比较多的反向代理,同时只是将接口转发,接口的定制化就不是那么好。只不过你可以原封不动的将原有的请求迁移到前端,假设有了某个网站的大部分协议复现的代码接口,那么这样迁移将会特别方便。

信息

提一嘴,如果使用跨平台开发的,如使用前端技术栈去编写桌面端应用(electron),编写安卓,小程序(uniapp,taro)的话,除了小程序外,其他都没有跨域限制的(具体还要看相应跨平台技术的限制)。

方案选择

最终选择那种开发方式还是取决对应的应用场景,没有绝对的方案,具体考虑哪种方案是需要考虑用户,代码安全,请求量,是否维护来考量了。

写到这,可能对大多数人而言还是不懂,也很正常,因为这些内容都不算属于传统开发的范畴,甚至可以说是做 hui 产的利。

SSR框架

我非常希望使用到浏览器的跨平台性,即多端运行,用户的设备只需要有一个浏览器能打开网页就能体验到。(这其实也算是我为什么学 web 开发的初衷了)

但是在一开始所介绍的小区开门应用中,这样的开发体验其实并不友好。因为我既要编写前端应用还要编写后端服务,相当于两个项目。同时部署应用和传统部署没有特别大的区别,都需要一台服务器,很多时候都是浪费在部署上。

而 SSR 框架可以算是后端应用开发和前端应用开发结合。能很好的解决上述存在的问题,并且也易于部署,下面我会细细道来。

这里我选用的 Nuxt3 框架,羊了个羊刷次数网页版就是基于 Nuxt3 框架来开发的,并且使用 vercel 来进行部署。我手头还写过一个项目 api-service

首先在 SSR 框架,是有对应的后端服务引擎。像 Nuxt3 使用的是 Nitro,而 Next.js 使用的是 koa。都提供了后端服务 API 的解决方案,同时这些都是服务都算是 serverless function(无服务函数),所以在编写与调用非常方便。

此外基于 NetlifyVercel 这些 serverless development 平台,可以非常方便的部署 SSR 框架。同时内置 CI/CD,只需要提交 git commit 就能实现自动构建自动部署。

最主要是的我恰好使用 Node.js 来做爬虫与api接口,因此后端复现接口也使用 js 来实现。

为此我特意编写了一个 Protocol 协议复现模板 ,这里我就不在过多介绍该模板。

总结

协议复现能写非常多的程序,因为协议复现的大多数案例都是基于已有的应用服务上去实现的,而很多人的日常生活都使用这些已有的服务上。有些已有的服务可能对于一些人而言,体验不好,或者是有其他限制。因此就有人对这些已有的服务来进行“扩展”,来实现自己所定制化的需求。

危险

这里我需要谨言慎行,因为大多数的协议复现所请求的站点都是他人的站点,如果你的程序或人为控制不当,导致他人服务器崩溃,又或者是非法访问本不属于你所该访问的数据。因此很有可能会触发相关的法律,这里我就不细说了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年9月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 小区开门应用​
    • 应用需求​
      • 开发​
        • 获取大门列表​
        • 开门请求​
      • 同源策略 跨域​
        • 不支持修改协议头​
        • 方案​
          • 桌面端应用开发​
            • 后端应用开发​
              • 前端应用开发/反向代理(可行)​
                • 方案选择​
                • SSR框架​
                • 总结​
                相关产品与服务
                专用宿主机
                专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档