zoukankan      html  css  js  c++  java
  • 用CONNECT方法突破HTTP代理服务器的扩展名封锁(python) [转] MyNewID 博客园

    用CONNECT方法突破HTTP代理服务器的扩展名封锁(python) [转] - MyNewID - 博客园

    公司里的电脑是通过一台内部代理服务器上网的,为了节省带宽,对下载进行了限制。方法是过滤URL中的扩展名,如'exe','rar','tar.gz'等,并且限制了连接时间,当连接时间超过2分钟就主动断开。这样平常就只能看看网页了,要下载就要申请,非常麻烦。虽说可以通过“问号大法”来解决URL过滤,wget来解决断点续传,但这样还是不好,下大一点的文件或网速慢一点时,要断线好几十次。一次偶然的机会发现公司的代理服务器没有限制CONNECT命令,哈哈,终于可以解决下载问题了。

    通过向代理服务器发送CONNECT命令,可以让代理服务器和目标主机的目标端口建立一个连接,这样本机和目标主机就有了一个通道。从此以后向代理服务器发送命令就等于向目标主机发送命令。这和一般的GET方式不同,完全不受过滤机制的影响。先来看看两种方式的不同之处,

    GET方式:

    socket.connect('HTTP代理服务器IP',HTTP代理服务器端口)
    
    socket.send('GET http://XXX.XXX.XXX/XXX.EXE HTTP/1.1\r\n
    
                      HOST: XXX.XXX.XXX\r\n\r\n')
    


    CONNECT方式:

    socket.connect('HTTP代理服务器IP',HTTP代理服务器端口)
    
    socket.send('CONNECT XXX.XXX.XXX:80 HTTP/1.1\r\n\r\n')
    
    socket.recv(1024)
    
    socket.send('GET /XXX.EXE HTTP/1.1\r\n
    
                      HOST: XXX.XXX.XXX\r\n\r\n')
    


    就是这么简单,下面就用python来完成编码。python有很多对http协议的封装库,如urllib2,httplib等。但我不知urllib2如何设置connect方式的代理,懒得去研究了。所以直接用socket来实现。相对于C++,用python来操作socket是如此的简单优雅。
    pget.py:

    import socket
    
    import sys
    
    
    
    #如果参数<1则显示信息
    
    if len(sys.argv)<2:
    
        print 'proxyGet v0.3 \n\
    
    Written by Wangfan\n\
    
    Powered by Python 2.5\n\n\
    
    Usage:\n\
    
        pget [URL]'
    
        sys.exit()
    
    
    
    #URL处理函数,得到文件名、HOST、GET请求
    
    def parseURL(url):
    
        url=url.split('/')
    
        file_name=url[-1].strip()
    
        host=url[2]
    
        del url[0]
    
        del url[0]
    
        del url[0]        
    
        header_get='/'+'/'.join(url)
    
        return (file_name,host,header_get)
    
        
    
    urlInfo=parseURL(sys.argv[1])
    
    print '***pget v0.3***\n\n\
    
    File Name:  %s\n\
    
         From:  %s\n\
    
          GET:  %s\n\
    
    ' %(urlInfo[0],urlInfo[1],urlInfo[2])
    
    
    
    #确认可以开始下载
    
    input_char=raw_input('ok?(press "y" to start,press other to exit):')
    
    if input_char!='y':
    
        sys.exit()
    
    
    
    #初始化socket
    
    s=socket.socket()
    
    
    
    #连接代理服务器
    
    s.connect(('10.100.1.206',3128))
    
    
    
    #发送CONNECT命令,连接目标主机
    
    s.send('CONNECT '+urlInfo[1]+':80 HTTP/1.1\n\n')
    
    
    
    #得到回应
    
    print 'Proxy:',s.recv(1024).strip()
    
    
    
    #发送下载请求和头信息
    
    s.send('GET '+urlInfo[2]+' HTTP/1.1\r\n\
    
    Host: '+urlInfo[1]+'\r\n\
    
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3\r\n\
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\
    
    Accept-Language: en-us,en;q=0.5\r\n\
    
    Accept-Encoding: gzip,deflate\r\n\
    
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n\
    
    Keep-Alive: 300\r\n\
    
    Proxy-Connection: keep-alive\r\n\r\n')
    
    r=''
    
    headers=''
    
    content_length=0
    
    header_end=False
    
    
    
    #循环读取,处理回应的头信息和内容
    
    while True:
    
        r+=s.recv(1)
    
        downloaded=len(r)
    
        if header_end==False:
    
            if r.find('\r\n\r\n')!=-1:
    
                headers=r.split('\r\n\r\n')[0]
    
                print headers
    
                for header in headers.split('\r\n'):
    
                    if header.split(':')[0]=='Content-Length':
    
                        content_length=int(header.split(':')[-1])
    
                    if header.split(':')[0]=='Location':
    
                        sys.exit()
    
                r=''
    
                header_end=True
    
                if content_length==0:
    
                    sys.exit()
    
        if downloaded%1024==0:
    
            #输出下载进度
    
            print '\r[',int((downloaded/1024)/float(content_length/1024)*100),'%]',downloaded/1024,'KB /',content_length/1024,'KB',
    
    
    
        #如果已下载的内容长度等于头信息中长度则跳出
    
        if downloaded==content_length:
    
            break
    
    
    
    #保存文件
    
    fp=open(urlInfo[0],'wb')
    
    fp.write(r)
    
    fp.close() 
    
    s.close()
    
    sys.exit()
    



    由于不想占用过多的带宽,所以没有加入多线程。但是,可以扩展的地方还有很多,比如断点续传等,以后有空再完善吧,先做个可以用的原型:)

  • 相关阅读:
    系统管理命令之tty
    系统管理命令之id
    idea中使用junit测试时使用Scanner类无法正常测试
    002-字段不为null
    java8中接口中的default方法
    java之接口适配器
    java之对象适配器
    java之类适配器
    java之多态(六)
    java之多态(五)
  • 原文地址:https://www.cnblogs.com/lexus/p/2476713.html
Copyright © 2011-2022 走看看