ORF反垃圾邮件系统

邮件服务器-邮件系统-邮件技术论坛(BBS)

 找回密码
 会员注册
查看: 6540|回复: 0
打印 上一主题 下一主题

[转帖]北京电力猫在Linux/Unix 下上网的解决方案

[复制链接]
跳转到指定楼层
顶楼
发表于 2006-3-6 10:46:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
北京中电飞华电力猫在Linux/Unix 下上网的解决方案<br>
作者:马路遥 maluyao@163.com<br>
<br>
关键词:Linux Unix plc 电力猫 中电飞华<br>
<br>
本文的内容和程序均以GPL 方式发布。<br>
<br>
  中电飞华在北京推出了电力猫上网的业务,费用相当低廉。笔者选用的一款是400元包半年的套餐。标称速度是10M 实际下载可以达到60K以上,在北方网通的地盘上速度也算马马虎虎了。<br>
<br>
  中电飞华提供了两种类型的"电力猫",一种用”网线型号“的,用网线直接接入电脑。相当于一个hub或交换机。不需要驱动程序都可以在任何操作系统上使用。另一种为usb接入。没有驱动不能在Linux下使用。但www.intellon.com以GPL的方式开放了windows下驱动程序的源代码。原则上也可以移植到linux/unix上。如果不愿做这个移植工作。建议使用linux/unix 的朋友一定要选择网线型号的电力猫。<br>
  北京地区的中电飞华在Windows 下采用的认证方式据说是华为认证。以IE + ActiveX的方式进行,无法移植到Linux/Unix上,其原理如下:<br>
1.在某个web服务器的cgi程序上进行认证,认证通过后你会得到一个sessionid 的变量。此变量实际使用中最大为31000,应该不会超过32767。这在Linux 下很容易做到。<br>
2.每分钟发送一个udp包到服务器的8090端口,其中包括上述的sessionid 数据。但服务器并不回应。这样连接会一直保持。<br>
通过ethereal 抓包分析出udp数据如下:<br>
数据长度为10个字节,以下以16进制表示:<br>
<br>
05 05 00 00 00 00 00 00 61 54<br>
<br>
第一个数据似乎一直不变。<br>
<br>
第二个数字从零开始,每次会加一,由于两个16进制的长度最多能发256分钟,暂时还部知道256分钟以后此字段如何变化。事实上电力猫连接不甚稳定,也不容易达到这个数字。<br>
中间的6个字段总是0。<br>
最后两个字段的组合是sessionid 的值。<br>
比如你得到的sessionid 是29615 ,那么后两个就是73 AF<br>
29615=0x73AF.<br>
<br>
注销时也是发一个udp包,内容和刚才相似,但头两位数据是<br>
03 0A<br>
我是包半年的用户。不用考虑注销的问题。<br>
<br>
知道这些,就很容易实现Linux Unix下的认证了<br>
<br>
先用写了个脚本(在同一行里)<br>
curl -s -d "username=MY_USER_NAME&password=MYPASSWORD&serviceID=0&webserviceID=0&tempID=0"<a target=_blank href=http://211.160.92.162/login.cgi>http://211.160.92.162/login.cgi</a> grep SessionID |grep VALUE |awk -F '=' '{print $3}' |awk -F '>' '{print $1}'<br>
<br>
我把这个脚本命名为feihua.sh ,加上755 的权限,放到/usr/local/bin 里。当然要把MY_USER_NAME和MYPASSWORD换成自己的用户名和密码。<br>
<br>
这个脚本的返回结果就是sessionid.<br>
用C语言写了下列程序。本人的C 语言比较菜。仅仅是对付能用.(程序名称为plc.c ,放在最后)<br>
gcc plc.c -o /usr/local/bin/plc<br>
<br>
程序在Redhat AS4 上编译和运行都没问题,希望使用其他版本Linux 、FreeBSD以及其他Unix 的朋友们也帮我测试一下。<br>
<br>
执行:<br>
feihua.sh |plc <br>
<br>
这样就可以成功认证了。<br>
<br>
后记:<br>
05末年装了个电力猫,这也是我所在小区宽带的唯一选择。因为多数用linux工作。很不爽。<br>
刚开始用crontab 调用curl 每分钟进行一次web 验证,虽然也能对付,但实在是不舒服。<br>
<br>
因为怀疑所谓的华为认证是比较复杂的机制。也许还涉及到加密解密(现在想想,基本不可能实现)和其他的底层问题。<br>
决定从C语言入手,搞定这个问题。<br>
<br>
  笔者的编程经验虽然可以追溯到18年前使用Fortran语言,java/perl/php/vb/shell 等都会,但都是业余水平。<br>以前也自学过C,除了指针之外,基本都懂了。有点象只能使用机枪而不能使用大炮的坦克手。<br>
<br>
在06年春节其间,为了学习C,从谭浩强到 K&R 的书都看了几遍。算是基本理顺了指针。<br>
但随后发现,为了彻底弄清楚C,先得看看数据结构。<br>
<br>
又发现理解数据结构,还要研究离散数学。反正又大把的时间。索性就这么看下去。<br>
<br>
又弄了几本Unix下C编程的书。这些该死的作者都把Socket编程放到最后。我还没看到呢。<br>
<br>
拿出sniffer 抓一下包,才发现这么简单。早知道抄个java或perl程序,也许半个钟头就搞定了.<br>
<br>
既然已经看了这么多C,下一步想把我本本上Ti 的读卡器、1394、pcmcia卡三合一芯片的Linux驱动搞定。这对我来说,估计是个复杂的工作了,希望在笔记本报废之前,能够完成这个工作。<br>
<br>
暂时靠讲授Linux课程吃饭。勉强也能养家糊口,十年磨一剑,又如何.<br>
<br>
<br>
感谢南京的新梦网友在两年前(2004,那时候他还是高中生)提供的帮助和思路.<br>
<br>
附C程序plc.c<br>
代码错误过多,请看我后续跟贴的新代码<br>
<br>
<br>
CODE:[Copy to clipboard]//plc.c<br>
#include <sys/socket.h><br>
#include <netinet/in.h><br>
#include <netdb.h><br>
#include <stdio.h><br>
#include <unistd.h><br>
#define FIRST 0<br>
#define LAST 1<br>
int main(int argc,char *argv[]){<br>char *host;<br>int sockfd;<br>int len,result;<br>struct sockaddr_in address;<br>struct hostent *hostinfo;<br>struct servent *servinfo;<br>char buffer[10];<br>int sid;<br>scanf("%d",&sid); //读入sessionid ,用管道读入就最简单了<br>
// printf("sid is %d\n",sid);<br>host="211.160.92.162"; //服务器地址<br>hostinfo=gethostbyname(host); //直接用ip的时候应该不用gethostbayname吧?但我不知道。<br>
/* 因为笔者的socket编程水平实在比较菜,所以必需在/etc/services 中加入一行:<br>plc 8090/udp<br>才能用下边的程序,那位大侠帮我改改。<br>其实就是要向服务器的8090端口发个包而已。<br>
*/<br>servinfo=getservbyname("plc","udp");//老土了。<br>sockfd=socket(AF_INET,SOCK_DGRAM,0);<br>address.sin_family=AF_INET;<br>address.sin_port=servinfo->s_port;<br>address.sin_addr=*(struct in_addr *)*hostinfo->h_addr_list;<br>len=sizeof(address);<br>buffer[0]=0x05;//第一个字段的数据<br>int i;<br>for (i=2;i<7;i++)<br>buffer<i>=0x00;<br>buffer[8]=session(sid,FIRST);<br>buffer[9]=session(sid,LAST);<br>/* 根据sessionid 算出最后两个数据的内容 */<br>printf( "%d \n",session(sid,FIRST));//倒数第二个字段的数据<br>printf( "%d \n",session(sid,LAST));//最后一个字段的数据<br>while(1){<br>buffer[1]=add(); //每次加一个数。从零开始,没有考虑超过256分钟的情况。<br>result=sendto(sockfd,buffer,10,0,(struct sockaddr *)&address,len);<br>sleep(60);//等待60秒,应该有更好的方法吧。俺还不会用C的定时器。<br>}<br>exit(0);<br>
<br>
}//end of main<br>
int session(const int sid,const int flag){<br>if(flag==FIRST)<br>return (sid&65280)>>8; //倒数第二个字段, 65280 is 1111111100000000<br>else<br>return (sid&255); //最后一个字段。<br>
}<br>
int add(){<br>static i=-1;<br>i++;<br>return i;<br>
}<br>
<br>
<br>
<img src="../leadbbsfile/UBBicon/em01.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em02.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em03.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em04.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em05.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em06.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em07.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em08.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em10.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em11.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em12.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em13.GIF" width=20 height=20 align=absmiddle border=0><img src="../leadbbsfile/UBBicon/em14.GIF" width=20 height=20 align=absmiddle border=0>
您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

小黑屋|手机版|Archiver|邮件技术资讯网

GMT+8, 2024-4-24 03:52

Powered by Discuz! X3.2

© 2001-2016 Comsenz Inc.

本论坛为非盈利中立机构,所有言论属发表者个人意见,不代表本论坛立场。内容所涉及版权和法律相关事宜请参考各自所有者的条款。
如认定侵犯了您权利,请联系我们。本论坛原创内容请联系后再行转载并务必保留我站信息。此声明修改不另行通知,保留最终解释权。
*本论坛会员专属QQ群:邮件技术资讯网会员QQ群
*本论坛会员备用QQ群:邮件技术资讯网备用群

快速回复 返回顶部 返回列表