dorainm 发表于 2007-7-31 02:59

代理之翼 wingproxy

代理之翼 wingproxy<br><br>基于系统库劫持技术的透明代理(链)的实现<br><br>1. 序言<br>2. 代理服务器<br>3. 系统库劫持<br>4. 代理之翼<br>5. 结束<br><br><br>1. 序言<br>   
自1969年美国国防部远景研究规划局(Advanced Research Projects
Agency)为军事实验用而建立的ARPANET(阿帕网)起,Internet发展至今,从初期只有四台主机,到现在仅仅中国就有13700万网民
5940万台主机,网络的发展不由让我们叹为观止。<br>   
Internet之所以吸引万千的用户,在于它的资源共享和互动性,当今Internet上服务器提供的服务一般有电子邮件服务、Web服务、FTP服
务、DNS服务等;如果需要享受这些服务,终端主机必须要和提供服务的服务器主机建立连接交互,但是服务器主机分布在世界各地,并且由于网络分布的原因,
到达各个服务器的时间也不一样,一致资源共享速度差异,甚至有些服务器根本无法连接到;因此,Internet中出现服务器主机提供一种叫做代理
(proxy)的服务。<br><br><br><br>2. 代理服务器<br>    代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站。<br>   
在一般情况下,我们使用网络浏览器直接去连接其他Internet站点取得网络信息时,须送出Request信号来得到回答,然后对方再把信息以bit
方式传送回来。(注:以Web服务器和浏览器举例)代理服务器是介于浏览器和Web服务器之间的一台服务器,有了它之后,浏览器不是直接到Web服务器去
取回网页而是向代理服务器发出请求,Request信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。而且,大部分代理
服务器都具有缓冲的功能,就好象一个大的Cache,它有很大的存储空间,它不断将新取得数据储存到它本机的存储器上,如果浏览器所请求的数据在它本机的
存储器上已经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。<br>    代理服务器提供的代理服务也分很多协议,比如HTTP、SOCKS4、SOCKS5等,可以在相应的RFC文档中找到这些协议的具体描述。<br><br>    代理服务器的作用有:<br>    1、通过代理可以连接到原先无法到达的服务器:比如我们以前教育网无法直接到达国外网络,我们用代理服务器提供的HTTP代理服务,可以访问www.google.com。<br>    2、通过代理可以提高访问速度:教育网络访问Internet状况比较拥挤,那个网速慢啊!找一些代理来上网,提高网速。<br>   
3、隐藏自己真实的IP:这个也是代理的一大妙用,比如什么大赛,参赛项目在网络上评选,一个IP一段时间内只能投一票,有些热爱团队的,从网络上搜索到
代理列表,让自己的浏览器挨个换代理去投票,服务器端以为那么多IP的用户为这一个优秀的项目投票咧(其实这个功能很广泛的,网络攻击时候,隐藏自己或者
嫁祸他人,都需要代理,甚至代理链!)。<br>    4、突破网络限制:;<br>   
5、进行网络的集中安全管理:让一个局域网统一通过一个代理服务器访问Internet,这样子保障局域网直接面对Internet上攻击的伤害,也让管
理者更方便地分配网络的使用和权限;目前好多公司采取这种策略给员工们上网,再加上cache服务器,还能提高网络的利用效率;<br>   
6、更安全地保护权限:这个是一个实际应用例子,很有实用价值;Internet中服务器被攻击频繁,服务器处于机房当中,我们只能远程管理;虽然攻击者
不知道账号密码,但如果有耐心暴力破解,总有一天能够获得我们服务器的权限;我通常会这么做,在服务器的iptable里面限制了ssh的22号端口的对
外访问,运行一个代理服务软件,绑定最好很怪异冷僻的一个端口,比如41037号端口,然后在防火墙中开启这个端口的对外访问权限,远程管理服务器的时
候,踩着41037端口的代理连接到“本地”的ssh服务端口上;而一个攻击者扫描服务器的端口时候,他会发现ssh端口关闭着,如果他有足够耐心扫描1
-65535端口的话,他会迷茫地发现41037号端口开放,不知道是提供什么服务的。<br><br>   
目前使用的很多软件都支持代理功能,比如开源的Web浏览器Firefox、最人性化的Web浏览器Opera、功能强大的电子邮件客户端
evolution、Internet自由开放的聊天平台irc的客户端xchat、集合N种聊天协议于一身的通讯软件gaim,甚至
BitTorrent下载软件。只需要在软件的配置文件或者设置窗口里面,填写代理服务器的协议、地址、端口号以及认证码(比如账号密码),就可以享受代
理服务器提供的便捷服务。<br>    但是也有很多软件不支持代理功能,比如常见的FTP客户端ftp,在线电视播放软件sopcast,以及常用的电子邮件接收工具fetchmail、发送工具msmtp等等。<br><br>3. 系统库<br><br>   
编译器在编译源码的时候,它并不是把一些系统调用、比如printf / socket/
connect之类的函数的汇编源码或者机器码直接包含在目标程序中,它只不过在这个位子上保存着一个符号链接;而操作系统为针对当前的硬件环境、硬件驱
动,会为其上运行的程序提供统一功能的系统库调用。<br>   
当这个程序被执行的时候,它被操作系统动态装载时,系统会检测是否存在一些不被程序包含的库,比如找到了connect,操作系统就去系统库里面调出
connect,这样,这个程序才能被正确执行;也因为没有编译的时候包涵进去机器码,我们的程序就可以不用重新编译就可以在操作系统的提供下在不同的系
统硬件下运行。<br><br>    如果要对一个已经编译好了的二进制程序进行完善或者添加功能,劫持系统库是一个非常不错的方法;在环境变LD_PRELOAD中指定一个共享库的路径,当程序被运行起来是,它会首先装载那个共享库,然后做做程序的运行。<br>    如果我们在载入的共享库中,利用dlsym劫持了程序对系统库的调用,重写函数,让程序原先调用系统库中的某个功能函数的,现在变成了共享库中的某个功能函数,这样,就可以完成对编译好的二进制程序某些功能的完善与添加。<br><br>    下面是劫持系统库演示<br><br>    程序getuser是利用getenv函数,获取环境变量USER的一个程序,源码如下:<br>========================================================<br>/* filename: getuser.c<br>   author: dorainm<br>   email: dorainm@gmail.com*/<br>#include &lt;stdlib.h&gt;<br>#include &lt;stdio.h&gt;<br>int main( void )<br>{<br>       char *p;<br>       if( (p=getenv("USER"))!=NULL )<br>       {<br>               printf("USER = %s\n",p);<br>       }<br>       return 0;<br>};<br>========================================================<br><br>    共享库hijackgetenv.so的作用就是劫持系统库中符号链接getenv,重写函数,达到修改或者添加getenv函数功能的目的,代码如下:<br>========================================================<br>/* filename: hijackgetenv.c<br>   author: dorainm<br>   email: dorainm@gmail.com*/<br>#include &lt;sys/types.h&gt;<br>#include &lt;unistd.h&gt;<br>#define __USE_GNU<br>#include &lt;dlfcn.h&gt;<br>#undef __USE_GNU<br>#include &lt;stdio.h&gt;<br>static char *(*_d_hijack_getenv)( const char *name );<br>char *getenv( const char *name )<br>{<br>       putenv( "USER=\"not dorainm\"" );<br>       return _d_hijack_getenv( name );<br>};<br>void _init( void )<br>{<br>       _d_hijack_getenv = dlsym( RTLD_NEXT, "getenv" );<br>       return;<br>};<br>========================================================<br>     <br>    该共享库劫持getenv后,重写了一个把环境变量USER修改为"not dorainm"的getenv函数。<br>    劫持系统库的主程序,首先要修改环境变量LD_PRELOAD指向hijackgetenv.so的路径,然后用exec之类的函数来运行程序,最后修改回LD_PRELOAD,源码如下:<br>========================================================<br>/* filename: hijack.c<br>   author: dorainm<br>   email: dorainm@gmail.com*/<br>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>int main( int argc, char **argv )<br>{<br>    putenv( "LD_PRELOAD=./hijackgetenv.so" );<br>    execvp( argv[1], &amp;argv[1] );<br>    putenv( "LD_PRELOAD=" );<br>    perror( "executed error " );<br>    return 0;<br>};<br>========================================================<br>  <br>    现在编译getuser:<br>========================================================<br>[dorainm@dorainm dlsmy]$ gcc getuser.c -o getuser   <br>========================================================<br> <br>    编译共享库hijackgetenv.so:<br>========================================================<br>[dorainm@dorainm dlsmy]$ gcc -c hijackgetenv.c -fPIC<br>[dorainm@dorainm dlsmy]$ ld -lc -shared -ldl -o hijackgetenv.so<br>hijackgetenv.o   <br>========================================================<br><br>    最后编译劫持系统库的主程序:<br>========================================================<br>[dorainm@dorainm dlsmy]$ gcc hijack.c -o hijack   <br>========================================================<br><br>    运行程序,演示劫持系统库:<br>========================================================<br>[dorainm@dorainm dlsmy]$ ./getuser<br>USER = dorainm<br>[dorainm@dorainm dlsmy]$ ./hijack ./getuser<br>USER = "not dorainm"<br>[dorainm@dorainm dlsmy]$<br>========================================================<br>  <br>    第一次程序正常运行,获得了环境变量USER,第二次hijack主程序劫持系统库、重写函数后,getuser读取到的USER,果然变成了被劫持修改后的"not dorainm"。<br>    劫持系统库演示成功!<br><br>4. 代理之翼<br><br>开发环境<br><br>硬件<br>CPU    Intel(R) Pentium(TM) iii 860MHz<br>Memory    128M SD<br>Monitor    640x480 [col=80 row=28]<br>软件<br>O.S.    GNU/Linux 2.6.15<br>Console    GNU/tty 5.93<br>Shell    GNU/Bash 3.1.7<br>Editor    GNU/Emacs 21.4.1<br>Linker    GNU/ld 2.16.91<br>Maker    GNU/make 3.80<br>Compiler    GNU/gcc 4.1.1<br>Debug    GNU/gdb 6.3.0<br><br>运行环境<br>硬件<br>CPU    166MHz<br>Memory    16M<br>软件<br>O.S.    GNU/Linux,UNIX,BSD<br>Linker    GNU/ld<br>Maker    GNU/make<br>Compiler    GNU/gcc<br><br>    一个client程序会调用系统库中提供的connect函数,来实现与server的连接,然后client与server就可以进行交互了;<br>   
现在我们自己构建一个共享库,然后劫持系统库,重写connect函数,让原先直接连接server的connect函数,变成连接代理(链)服务器后,
再到server的一个新的connect;这回,当client调用connect时候,已经不再是系统库中的connect函数了,而是我们构造的假
冒的connect,client就在不知情的情况下,连接了N台代理服务器,然后最后与server连接,接下来,继续调用recv/send与
server进行交互,透明地实现了代理功能!!<br><br>    程序实现演示,解压缩程序源码<br>========================================================<br>$ tar xzvf wingproxy-1.0.tar.gz<br>wingproxy/<br>wingproxy/README<br>wingproxy/doc/<br>wingproxy/doc/wingproxy.1<br>wingproxy/NEWS<br>wingproxy/CHANGELOG<br>wingproxy/AUTHOR<br>wingproxy/src/<br>wingproxy/src/proxy_chain.c<br>wingproxy/src/wingproxy.c<br>wingproxy/src/proxy_http.h<br>wingproxy/src/proxy_socks4.c<br>wingproxy/src/d_base64.c<br>wingproxy/src/proxy_socks5.h<br>wingproxy/src/proxy_socks4.h<br>wingproxy/src/variable.h<br>wingproxy/src/d_base64.h<br>wingproxy/src/proxy_chain.h<br>wingproxy/src/wingproxy.h<br>wingproxy/src/proxy_socks5.c<br>wingproxy/src/proxy_http.c<br>wingproxy/src/main.c<br>wingproxy/src/Makefile<br>wingproxy/COPYING<br>wingproxy/INSTALL<br>wingproxy/etc/<br>wingproxy/etc/wingproxy.conf<br>wingproxy/Makefile<br>$ cd wingproxy/src<br>$ make<br>gcc    -c -o d_base64.o d_base64.c<br>gcc    -c -o proxy_socks4.o proxy_socks4.c<br>gcc    -c -o proxy_socks5.o proxy_socks5.c<br>gcc    -c -o proxy_http.o proxy_http.c<br>gcc    -c -o proxy_chain.o proxy_chain.c<br>gcc -fPIC -c wingproxy.c d_base64.o proxy_socks4.o proxy_socks5.o proxy_http.o  proxy_chain.o<br>ld -shared -lc -ldl -o libwingproxy.so wingproxy.o d_base64.o proxy_socks4.o proxy_socks5.o proxy_http.o  proxy_chain.o<br>gcc -g -o wingproxy main.c d_base64.o proxy_socks4.o proxy_socks5.o proxy_http.o  proxy_chain.o<br>$ sudo make install<br>install -d /usr/share/wingproxy<br>install -d /usr/share/wingproxy/lib<br>install -d /usr/share/wingproxy/etc<br>install -d /usr/bin<br>install -d /usr/share/man/man1<br>install libwingproxy.so -m 755 /usr/share/wingproxy/lib<br>install ../etc/wingproxy.conf -m 644 /usr/share/wingproxy/etc<br>install wingproxy -m 755 /usr/bin<br>install ../doc/wingproxy.1 -m 644 /usr/share/man/man1/wingproxy.1<br>========================================================<br><br><br>    修改~/.wingproxyrc或者用root权限修改/etc/wingproxy.conf,可以设制代理(链)服务器<br>========================================================<br># wingproxy.conf<br>#     wingproxy configure file<br>#<br>#FIELDS:<br>#  PROTOCOL:PROXYHOST:PROXYPORT:AUTHUSER:AUTHPSWD<br>#<br>#PROTOCOL:<br>#  SOCKS4 SOCKS5 HTTP<br>#<br>#PROXYHOST:<br>#  ip address for proxy server<br>#<br>#PROXYPORT:<br>#  the port of the proxy server work on<br>#<br>#AUTHUSER:<br>#  username for authentication<br>#    use (NULL) if the proxy without it<br>#<br>#AUTHPSWD:<br>#  password for authentication<br>#    use (NULL) if the proxy without it<br>#<br>#EXAMPLE:<br>############# begin of wingroxy.conf ################<br>#SOCKS4:10.0.0.18:1080:dorainm:(NULL)<br>#SOCKS5:10.0.0.100:1080:dorainm:dorainm@gmail.com<br>#HTTP:10.0.0.254:(NULL):(NULL)<br>############# end of wingproxy.conf #################<br>#<br>#<br>SOCKS5:10.0.0.55:1080:(NULL):(NULL)<br>SOCKS4:10.0.0.18:1080:(NULL):(NULL)<br>HTTP:10.0.0.100:8080:(NULL):(NULL)<br>========================================================<br><br>    查看wingproxy运行语法<br>========================================================<br>c$ wingproxy<br>wingproxy v1.0 by dorainm, dorainm@gmail.com<br>usage : wingproxy command [...]<br>========================================================<br><br>    设制好代理服务器后,只要用wingproxy+command就可以运行了,比如<br>========================================================<br>$ wingproxy ftp 10.0.1.164<br>Connected to 10.0.1.164.<br>220 dorainm's FTP server (vsFTPd 2.0.4)<br>Name (10.0.1.164:dorainm):<br>========================================================<br><br>    相关附件下载<br><br><a href="http://groups.google.com/group/dorainm/web/wingproxy-1.0.tar.gz" target="_blank" >wingproxy-1.0.tar.gz</a> <br><br>(附件还是google group上的,不知道会不会长期有效?还是再来一个吧)<br><br><table  align="center" border="1" bordercolor="#dddddd" cellpadding="0" cellspacing="0" width="360">
<tr height="60"><td align="center" width="60"><img src="http://blog.chinaunix.net/fileicon/zip.gif" alt="" border="0"></td><td>
    <table  border="0" cellpadding="0" cellspacing="0" width="100%">
    <tr height="20"><td align="center" width="40">文件:</td><td>wingproxy-1.0.tar.gz</td></tr>
    <tr height="20"><td align="center" width="40">大小:</td><td>16KB</td></tr>
    <tr height="20"><td align="center" width="40">下载:</td><td><a href="http://blog.chinaunix.net/upfile/070616030615.gz" target="_blank" >下载</a></td></tr>
    </table>
</td></tr>
</table>


页: [1]

编程论坛