摘要:本文主要是针对通过路由器wan口连接校园网(web认证)登陆一个账号,多个设备连接路由器共享同一账号,在若干分钟后会被检测出代理(或共享)行为,账号被暂时封禁的问题。并同时实现了web自动认证,不必繁琐的登陆了。
维基百科openwrt介绍:
OpenWrt是适合于嵌入式设备的一个Linux发行版。
相对原厂固件而言,OpenWrt不是一个单一、静态的固件,而是提供了一个可添加软件包的可写的文件系统。这使用户可以自由的选择应用程序和配置,而不必受设备提供商的限制,并且可以使用一些适合某方面应用的软件包来定制你的设备。对于开发者来说,OpenWrt是一个框架,开发者不必麻烦地构建整个固件就能得到想要的应用程序;对于用户来说,这意味着完全定制的能力,与以往不同的方式使用设备,OPKG包含超过3500个软件。
默认使用LuCI作为web交互界面。
设备:刷入openwrt系统的路由器一部
(作者使用的是大麦DW220D)
固件版本:OpenWrt Barrier Breaker 14.07 /LuCI Trunk (0.12+svn-r10530)
内核版本:3.10.49
涉及内容:
背景/原理:当使用路由器wan口连接校园网后,终端对校园网服务器来说是透明的(NAT地址转换),校园网服务器会在用户联网后若干分钟(SWU是20分钟)分析数据包,检测是否有多设备共享的行为,所以只需要每隔十分钟进行一次断网/联网操作。事实上,Supermartin已按此原理开发了Windows环境的自动联网工具(破解重庆电信校园网,一个寝室共用一个宽带账号),但寝室内长期开启电脑在功耗上难以令人接受。校园网web认证归根结底是发送http应用层协议数据包(最常见的是post、get)实现,故步骤大致分为两步:
分析数据包可以通过抓包和分析页面JavaScript来进行。开启浏览器开发者工具(F12)进行一次web登陆,然后通过灵敏的嗅觉,找到关键post包,如图1。
可以看到,虽然userid和password关键字内容是明确(未加密)的,但queryString和service的出现和内容有点不明就里,应结合JS分析出queryString和service的构造方式和内涵意义。再次打开开发者工具,html代码定位到登陆按钮如图,发现登陆按钮绑定了一个doauthen()函数,如图2.
发现本页面引入了两个js文件,在其中一个js里找到了登陆函数:
其中ePortalUrl是请求地址前缀:http://222.198.127.170/eportal/InterFace.do?method=
login : function(userId, password, service, queryString,operatorPwd,operatorUserId,validcode,callback) {
/* 1.登录 */
var content = "userId=" + userId + "&password=" + password + "&service=" + service + "&queryString=" + queryString+"&operatorPwd="+operatorPwd+"&operatorUserId="+operatorUserId+"&validcode="+validcode;
post(ePortalUrl + "login", content, callback);
},
和下线函数:
logout : function(userIndex,callback) {
/* 4.下线 */
var content = "userIndex=" + userIndex;
post(ePortalUrl + "logout", content,callback);
},
可以发现,登陆需要的post关键词比较多,而下线只需要一个userIndex
在JS文件发现queryString是由前页面提交的get数据,经过两次encodeURIComponent()转码,如图3
JavaScript encodeURLComponent()意义是替换原字符串的某些特殊字符(详细请见encodeURLComponen意义)。
而service对应%25E9%25BB%2598%25E8%25AE%25A4
则是图3可选下拉框默认
一词的两次encodeURLComponent()转码。这个比较固定,所以只用找一下queryString的get数据来源。
在进入认证地址http://XXX.XXX.XXX.XXX
,认证页面未登陆时,地址栏会变成
http://XXX.XXX.XXX.XXX/eportal/index.jsp?wlanuserip=10.69.XXX.XX&wlanacname=NAS&ssid=Ruijie&nasip=172.28.XXX.X&mac=143dXXXX9&t=wireless-v2-plain&url=http://123.123.123.123/
而get数据就是"?"后面部分
wlanuserip=10.69.XXX.XX&wlanacname=NAS&ssid=Ruijie&nasip=172.28.XXX.X&mac=143dXXXX9&t=wireless-v2-plain&url=http://123.123.123.123/
说明在这之前浏览器进行了一次跳转,执行了一次get操作,在未登陆的情况,在未跳转的页面就能找到这些信息;事实上,这些信息是未登录设备连接服务器,服务器返回的注册信息。可以通过很多方法拿到这个页面(必须在未登陆状态),比如:
openwrt下wget得到的该页面如图4
至此,登陆所需要的四个关键词id,password,service,queryString全部清晰了,只需要构建POST包发送这些关键词到图1请求URL就可以完成登陆了。
先使用了python根据1.1的背景发送了post包,发现直接返回了userindex,图5故只需要进行字符串操作就可以得到userindex关键词了。
curl post操作命令格式:
curl -d "args" "protocol://address:port/url"
openwrt上的shell是轻量的解析器ash,语法比较不算严格,有一定编程基础的人可以很快的学会并应用,详情可见shell教程。(该网站免费的内容已经足够了)
使用计算机直插路由器lan口,使用putty,Xshell等工具进行SSH连接(有些版本要到路由器设置页面开启接收lan口SSH连接),地址为路由器管理地址,一般是192.168.1.1,输入root用户名和密码进入路由器。
#!/bin/ash
eUc()#encode url 模拟前文的二次编码操作,函数都使用echo的返回值
{ s0=$1
s1=${s0//=/%3D}
s2=${s1//&/%26}
s3=${s2//:/%3A}
s4=${s3//\//%2F}
s5=${s4//%/%25}
echo $s5
return 0
}
getQs()#only work on unlogged status/获取queryString,使用
{
inf=$(wget http://222.198.127.170 -O -)
s1=${inf:73}
s2=${s1%\'*}
echo $(eUc $s2)
}
login()#par1:id, par2:psw,par3:qS, return Userid/登陆操作,后面是参数顺序
{
s0=$(curl -d "userId=$1&password=$2&service=%25E9%25BB%2598%25E8%25AE%25A4&queryString=$3&operatorPwd=&operatorUserId=&validcode=" "http://222.198.127.170/eportal/InterFace.do?method=login")
s1=${s0#*:\"}
s2=${s1%%\"*}
echo $s2
}
logout()# par1:userId #退出当前登陆,后面是参数顺序
{
curl -d "userId=$1" "http://222.198.127.170/eportal/InterFace.do?method=logout"
}
logoutAll()#par1:ID, par2:password #使用ID和psw强制退出所有登陆,后面是参数顺序
{
curl -d "userId=$1&pass=$2" "http://222.198.127.170/eportal/InterFace.do?method=logoutByUserIdAndPass"
}
#main() begin
#因shell的特殊性,id和psw加不加引号都没关系
id=校园网账号
psw=校园网密码
#init
logoutAll $id $psw
qS=$(getQs)
userId=$(login $id $psw $qS)
#
while :
do
logout userId
qS=$(getQs)
userId=$(login $id $psw $qS)
sleep 600s#每10分钟执行一次
done
#end
vi保存的操作顺序是 ESC : wq enter
在linux脚本执行前需要授权,授权命令为:
chmod +x /etc/net.sh
执行脚本:
/etc/net.sh
按理说到这里就结束了,但使用SSH进入openwrt执行脚本,退出SSH时会停止脚本的执行,这里使用screen包来使其后台执行,使用screen类似于windows窗口,若干个窗口可以同时执行。安装命令如下:
opkg update
opkg install screen
在页面直接输入screen进入子页面,在该页面执行:
/etc/net.sh
程序正常执行后 键入 Ctrl+a 再按d 退出至主页面,这时候就可以输入exit退出连接了。
要再次进入该窗口,可以使用screen -ls获知之前窗口的编号,再以screen -r 编号命令进入。