我们不能失去信仰

我们在这个世界上不停地奔跑...

0%

基于OpenWrt的创业

创业前期环境简介

2017-6 至 2018-6 (大二下学期 至 大三下学期)

校内网络个人账号同时在线人数以及流量限制

​ 一个周期为 30 天

​ 一个周期流量为 20G

​ 如果用完,必须等待本期结束才能续费

​ 学校采用城市热点客户端(Dr.com),上网需要输入学号和密码。同一时间只能一个用户在线。

这就导致了一种情况,以我而言,在这个周期刚开始的一个星期内,因为下载一些教学资料,慕课网视频,就用完了流量。
我自己有两台电脑,却无法同时上网,这样就很不方便,两台机器做实验都无法完成。

在大二上学期末,我准备改变一下境况,首先最直观的想法是想到了路由器。能不能把网络分出来,然后让多个设备可以一块连接。
然后,我就从淘宝买了一个极路由做一下尝试,因为极路由是可以刷机的,我使用了 OpenWrt 一个基于开源协议的嵌入式系统,类似 Linux 系统。因为曾经一直怀揣着做一个黑客的梦想,抓包分析流量自然会一点,然后,在 Google 搜了很多关于破解 Dr.com 无果后,就自己动手开始进行流量分析,基于 Windows 的客户端。我使用了 Wireshark 来监听流量,过滤后截获到拨号连接的时候的数据包。

drcom0

我发现了一个大致的流程就是首先进行 802.1X 认证,它的包只有密码被加密,账号并没有加密,我从数据包中可以看到账号。
如果认证成功,则开始 DHCP 服务,进行 IP 的分配,至此请求结束。
我是 15年9月入学,当时那会还需要手动根据宿舍楼,寝室号进行 IP 的分配,而在 2017年初, 在生活区就已经开始支持 DHCP 了。
我所在的研究室,还无法支持 DHCP,所以我就也研究了一下。
如果不支持 DHCP ,那么可以手动分配 IP ,然后认证还是和以前一样(当时出了一些bug,反而静态手动配置ip可以上网,想了下兼容性问题,猜测现在学校肯定在有 DHCP 服务的情况下支持手动配置 IP)。而 802.1X 是走链路层协议的,完全可以在没有 IP 的时候进行认证。如果认证成功,那么客户端使用静态 IP 或者 DHCP 服务,完成最后的操作。

在了解了基本流程之后,我决定一试。但是我并没有就直接蒙头开始写代码,因为我还得进行可行性验证。它的密码的加密方式是什么,否则做到一半发现做不下去了。

我了解了一些工具,如: wpa_supplicant 来模拟拨号,配置完成之后,进行正常拨号,然后从校园网后台管理页面,可以看到认证成功了。但是无法上网。对于这个问题走了很多弯路,完全没有办法。
然后我对 Linux 自带的认证方式进行了穷举,发现了某台 Linux 认证成功就可以上网了,为了这个问题,我找了大概两天没合眼。(不过那时候是因为技术烂而已)

然后发现了一个不同点,在那台 Linux 上面,开启了自动 DHCP,所以,认证成功后,自动就获取了 IP。
但是 wpa_supplicant 是先 DHCP 然后再 认证,通常都是认证过了,也无法上网,因为没有IP,我可以写一个定时任务或者一个 shell 脚本来控制 DHCP, 但是非常不稳定。

因为使用过 centos 6/7 ubuntu,所以在路由器里面,最好就是设置开机自动启动,自动拨号,否则,每次还需要去手动 ssh,岂不是太不方便了,这些如今看来非常简单的问题,对于当时的我就显得比较困难。后来通过在 /etc/init.d/下面放脚本来实现。

第一个能真正使用的路由器版本就这样被开发出来了。

v1.0

路由器,我解决了本校校园网的其中一个问题: 突破限制,达到一个账号多个设备使用。


关于继续开发第二期路由:

v1.1

从需求开发不断改进

​ v1.0 勉强通过现有的软件之间的组合进行了实现。但是总是在某些时候,如对网络稳定性要求较高的场景中,如果突然断线,就只能重启路由器,可以说稳定性不强。(原因有多种,没有深究,直接就换了思路,为了后期扩展)
为了解决这个问题,想在 Drcom 的源码上面下点功夫,于是就在 Github 上面发现了一个基于 Drcom 的开源项目,恰好是 Python 写的,另有 C 语言版本。
当时,我已经接触 Python 有一阵子了。于是立即打算看一下源码,然后对它进行定制修改,就可以达到我想要的操作。

本次改进主要用于:

  1. wpa_supplicant 的套件加起来,依赖安装完之后,内存很快用完,无法进行后期扩展。
  2. 针对路由器稳定性的改进
  3. 简化部署流程

看计算机黑皮书的时候,计算机发展史,听到很多次计算机的内存曾经及其昂贵,算是亲眼见识到了。

那时怎知路由器内存极其可贵。很多厂商为了降低成本,总是内存能少就少,在路由器上面,那个叫做闪存,类似于计算机的硬盘(但是路由器又没有硬盘的)。一个 Python 源代码就 300K 左右,再加上 Python-mini 环境,加起来最少也需要 3m 左右。但是那个路由器总共内存才 8m, 除去自己安装的系统,剩下的内存也就 3.5 左右了。我就无法进行后期的扩展(后面又开发了控制系统)。
然后就使用了 C 语言版本的,Linux 上面正好带有 gcc,直接编译完就可以运行,这样算下来,只用了不到 1m 的内存。
更重要的是这个版本稳定多了。

通过大概一个星期的正常使用,发现网络基于稳定。于是想着是否可以出售一下。

v1.1 改进版路由器诞生


对于 v 2.0 版本路由器设计

  1. 现在还有一个问题,流量仍然会有限制。

  2. 萌生出售的想法

  3. 开发更为方便的移动端

  4. 简化用户操作

还存在一个大问题,就是虽然可以多设备同时上网了,但是总流量是有限的。是否可以突破流量限制,那样,就比较好出售了。(学校某些同学校园网不用,以 3元/G 出售,一个 20G 的号一个月可以卖 60元)
我也同班同学,有的人流量总是不够用,每个月总要花大概五六十元去买其他人的流量。(就是别人把别人号给你)

目光再次转移到 Drcom ,深入 Drcom 。对网络安全曾经很感兴趣的我,从一些老版本软件肯定会存在某些 bug 入手。我发现本校使用的客户端版本较低,并且已经常年没有更新。
我开始人工审查校园网的管理页面,里面有查询信息,修改密码,报停/复通、强制下线等功能。

然后写了一个爬虫,进行模拟操作,在正常使用校园网的时候,如果进行某一操作是否会引发异常。

后面发现,在某次操作中,可以阻止本次流量上传至服务器。

当时惊喜万分。先介绍一下校园网提供的功能:

强制下线,可以让用户离线(如果连wifi,直接把wifi关了,然后只能等到心跳包超时,它才会自动下线)这里就不对 WIFI 如何离线做深入分析了。

image-20181122105817168

报停功能,它的用处是在如寒暑假,还有流量,可以先暂停服务,然后到校后再开通,这样就不会刷新,也不会扣钱。

如果是一个正常的用户,那么他一定会在需要的时候使用报停服务,如果是一个不正常的用户呢,又会有什么样的风险呢?

强制下线流程:

image-20181122110237519

下面说一下报停的流程。

用户点击报停–> 后台判断是否在线 –> 强制下线 –> 报停 –> 完成

image-20181122110837998

这是一个看似没问题的服务流程,他却极有可能假设用户是一个正常的用户,后台在这种情况下处理的出现了漏洞,直接调用了强制下线功能,之后账号变为不可用状态,无法再对其做操作(或者流量计费方式是异步的,并且只对正常账号进行计费)。这样自然就不会把每次的流量计入。

下面是我的猜测:

image-20181122111726475

其中绿色部分就是一个猜测。

至此, 万事具备,只欠开发。

投入开发

直接让用户去登录那个网站并不是不行,但是它不方便。我得包装一下,并且让它变得更加方便才行。因为至少有80%的同学都不知道还有一个校园网管理网站。

  • 产品要让客户用着方便。

接下来,开始了研发。 为了在放假前开始发布一期版本,以验证是否有市场。

在接下来的一个月内,我通过微信测试号先开发、微信企业级公众号(淘宝购买)、阿里云服务器、内网穿透服务(Frp)。开发了一套完整的解决方案。

因为管理网站在内网,阿里云的服务器是访问不到内网信息的,所以我使用 Frp 进行了内网穿透,通过在路由器上面安装 Frp ,并且对后期路由器的控制也是通过它,如控制内网路由器的状态。

  • 通过不断简化,最后配置操作简单到无法再精简,越简单会更好卖。

用户购买路由器 —> 插上电源/连上网线 –> 连上 wifi 输入默认密码,然后输入自己上网账号和密码,保存。 完成上网。

关于漏洞利用那块,我在后台通过用户绑定校园网账号密码实现:

image-20181122113142544

  1. 用户想要下线的时候点击公众号 免流 菜单。
  2. 后台通过拿到用户 openid 现在 Redis 里查看有没有没有过期的 Cookie,如果没有就继续到 MySQL 里查询账号密码做一次模拟登陆。然后帮助用户完成一些列操作,达到免流。
  3. 我采用的是异步的方式,因为微信公众号需要在 5s 内回复。先跟用户回复 正在进行中、然后过一会完成后以模板方式推送详细信息。

image-20181122114245238

关于为什么从开始 Django 后面又全部代码用 Tornado 重构一遍。

原因有三:

  1. 熟悉 Tornado 开发
  2. 对架构改进,方便以后扩展
  3. 多线程对单核 CPU 压力大,使用 epoll 模式。

对无法预知的事情做出的打算

突发情况、断电、断网、会造成流量被计入的风险。

免流操作必须在本次在线的情况下,还未下线进行操作,即可免除使用的流量。

当用户断网的时候,这个是我无法控制的,因为用户可能随时断电,拔掉路由器,所以,我无法在用户切断网之前对它进行自动免流量服务。

我只能做一些补救,在某些时间点上。

​ 为了避免晚上熄灯带来的影响,我开发了一种服务,每晚 22点30 熄灯,这个时候会断电,如果忘记在断电之前进行免流量的话,那么就会被计入,而很多人多是由于某些事情忘了。所以,我开发了定制在 22:25 是否进行免流服务,可以由用户自己选择。然后订阅的用户,我就会在服务器上面对它们在 22:25 进行操作。

其他还有诸多细节,都是通过一次一次实验的出来的,对它们一一做了处理,来保障稳定。

到此为止:

开始是用的 优酷的路由,也可以刷机。

后面想到宿舍网路情况,选用 5V 供电的路由器,本校断电不断网。这样路由器就可以在一个 3000mA 的充电宝的情况下,也能撑四五个小时左右。

以上, V 2.0 出售版开发完成。

移动端管理端

路由器盒子

临近期末卖出了10台左右。

暑假完后开学,收到良好的评价,卖出 30 台左右。

最终微信使用人数达到 300 人 , 路由器使用人数达到 50 人。

对于不需要路由器的同学,我开发了包月购买免流量服务的功能。


其他:

​ 为了方便用户操作(面对80%的人)并不知道如何修改密码,查看流量信息,查看截止日期,报停/复通(因为我校只有网页端,并且网页端还是以 IP 直接访问,非常难记。)

微信公众号开发,校园网流量查询、校园网密码修改、免流量、强制下线、集成一体的微信公众号。

微信公众号:

阿里云 1核 2G 内存主机,Nginx 做静态文件及代理服务器, 上游配置到 tornado 、一开始使用的是 Django 开发,但是 Django 结合 uWSGI 的原理是来一个请求,开启一个线程,当并发量稍微多一点,就会出错,所以,后来使用了 Tornado 、毕竟当时考虑的是只有一核 CPU 。

公众号实现功能:

微信校园网操作、后端通过模拟请求实现,修改密码、获取剩余流量、获取截止日期、强制下线、免流量

后期加入其它与校园网无关功能、主要是选课、查课等。

因担心路由器有可能不符合学校规定,所以从来没有宣传情况下用户量达到300,甚至连本班同学都不知道它的路由器是我开发的。
路由器多为淘宝二手,降低成本。

以上工作,全部由我一人完成。前端后端运维、售前售后。