PC端和Openwrt端的i-Shanghai自动登录研究
上海有免费的i-Shanghai,速度还不错,唯一麻烦的是每次登录都要通过手机号和用户名密码进行验证。作为组装级的程序猿,如不能做到自动登录是十分痛苦的事情。。。于是,加班之余展开了为期一周的研究。。。最终实现了PC端和Openwrt端的i-Shanghai自动登录。。。。
首先,分析阶段:
i-Shanghai的wifi连接上以后,任意打开某网页,例如:www.baidu.com,就会自动跳转到如下页面:
'https://wlan.ct10000.com/?basetype=3&nasPortId='.$nasPortId.'&UserInputURL=http://www.baidu.com/&nasIp='.$nasIp;
里面的id和ip估计就是热点的id和ip了。。。
这个页面包含一个框架,实际的登录页面就是在框架里面的,我认为这是基于安全性的考虑,框架的地址,类似:
'https://wlan.ct10000.com/'.$longString
直接打开框架地址后,出现了熟悉的登录框,通过分析元素发现,提交的要素有些是hidden的,且最后的提交按钮是调用javascript,经测试直接通过模拟点击是不行了(perl的www::mechanize似乎不支持javascript),这样的设计也是为了安全考虑吧,只有最后一条路——抓包分析了。
最麻烦的是,为了安全考虑,这些网址都是https的,通过wireshark抓包是没有用的,只能通过Fiddler或者chrome的开发者模式抓包,通过抓包,知道了提交的要素和地址:
提交的内容是:
paramStr paramStrEnc province prefix logintype UserName PassWord
提交的地址是:
https://wlan.ct10000.com/authServlet
前2个提交内容在框架页面就已经生成了,里面应该包含了热点的id等相关信息,如果提交时不带上或者带错了这些信息,就会提示此处不是热点。。。
其次,剩下的就是编码的活了,PC端可以用perl脚本,Openwrt端不能用perl,因为perl在op上的官方的库不支持https。。。。只好改用python,整个python安装需要7MB的路由器rom空间,也就是说,路由器至少要有16MB的flash,刷完op以后才能装整个python环境。
与pc端的perl脚本相比,op端的python脚本有不少差别,由于op上还要考虑dns的因素,故为了防止无法解析wlan.ct10000.com,需要提前获得其ip地址,另外为了防止与全局ss冲突,还需要在其ignorelist里面加入该ip地址,并且在crontab中设定定时登录任务。。
下面附上PC端i-Shanghai自动登录perl脚本,模拟iPhone登录(python脚本不提供,免得被不法奸商利用):
#/usr/bin/perl -w use strict; use warnings; use WWW::Mechanize; my $username = '13888888888'; my $pass = '222222'; my $nasIp = '133.133.133.133'; my $nasPortId = 'lag-1:8888.888'; my $url = 'https://wlan.ct10000.com/?basetype=3&nasPortId='.$nasPortId.'&UserInputURL=http://www.baidu.com/&nasIp='.$nasIp; my $impcontent; #打开浏览器 my $ua = WWW::Mechanize->new(); $ua->cookie_jar(HTTP::Cookies->new()); $ua->agent_alias('Windows IE 6'); #打开网址 my $response = $ua->get($url); my $decontent =$response->decoded_content; $decontent =~ s/\n//g; #打开框架网址 if($decontent =~ /mainFrame\" src=\"(.*)\" noresize/) { $url = 'https://wlan.ct10000.com'.$1; } $response = $ua->get($url); $decontent =$response->decoded_content; $decontent =~ s/\n/0D0A/g; $decontent =~ s/\s//g; #取出框架要素 my $paramStr=''; if($decontent =~ /id=\"paramStr\"value=\"(.*)?\"\/>0D0A<inputtype=\"hidden\"name=\"paramStrEnc\"/) { $paramStr=$1; } my $paramStrEnc=''; if($decontent =~ /id=\"paramStrEnc\"value=\"(.*)?\"\/>0D0A<inputtype=\"hidden\"name=\"province\"id=\"province\"/) { $paramStrEnc=$1; } my $province='telecom.dynamic@ish'; my $prefix='NE'; my $logintype='2'; #简易uri编码,不用调用URI::Encode $paramStr =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%02X", ord $1 /eg; $paramStr =~ s/0D0A/\%0D\%0A/g; $paramStrEnc =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%02X", ord $1 /eg; $province =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%02X", ord $1 /eg; my $location = 'https://wlan.ct10000.com/style/ish_fx/index.jsp?paramStr=' . $paramStr; my $content = 'paramStr=' . $paramStr . '¶mStrEnc=' . $paramStrEnc . '&province=' . $province . '&prefix=' . $prefix . '&logintype=' . $logintype . '&UserName=' . $username . '&PassWord=' . $pass; print $content; my $url2='https://wlan.ct10000.com/authServlet'; #发起登陆 $response = $ua->post($url2, 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding' => 'gzip, deflate', 'Accept-Language' => 'zh-CN,zh;q=0.8', 'Cache-Control' => 'max-age=0', 'Connection' => 'keep-alive', 'Content-Length' => '1067', 'Content-Type' => 'application/x-www-form-urlencoded', 'Cookie' => 'JSESSIONID=22B2B92222C0F258866778895E2F4450F80', 'Host' => 'wlan.ct10000.com', 'Origin' => 'https://wlan.ct10000.com', 'Referer' => $location, 'Upgrade-Insecure-Requests' => '1', 'User-Agent' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5', 'Content' => $content ); # $decontent = $response->decoded_content; # print $decontent;