搜索
查看: 417|回复: 0

goagent利用webshell搭代理

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2014-9-1 19:06:10 | 显示全部楼层 |阅读模式
python版:
  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. # Contributor:
  4. #      Phus Lu        <phus.lu@gmail.com>

  5. __version__ = '3.0.7'
  6. __password__ = ''
  7. __hostsdeny__ = ()  # __hostsdeny__ = ('.youtube.com', '.youku.com')

  8. import sys
  9. import os
  10. import re
  11. import time
  12. import struct
  13. import zlib
  14. import base64
  15. import logging
  16. import httplib
  17. import urlparse
  18. import errno
  19. import string
  20. try:
  21.     from io import BytesIO
  22. except ImportError:
  23.     from cStringIO import StringIO as BytesIO
  24. try:
  25.     from google.appengine.api import urlfetch
  26.     from google.appengine.runtime import apiproxy_errors
  27. except ImportError:
  28.     urlfetch = None
  29. try:
  30.     import sae
  31. except ImportError:
  32.     sae = None
  33. try:
  34.     import bae.core.wsgi
  35. except ImportError:
  36.     bae = None
  37. try:
  38.     import socket
  39.     import select
  40. except ImportError:
  41.     socket = None
  42. try:
  43.     import OpenSSL
  44. except ImportError:
  45.     OpenSSL = None

  46. URLFETCH_MAX = 2
  47. URLFETCH_MAXSIZE = 4*1024*1024
  48. URLFETCH_DEFLATE_MAXSIZE = 4*1024*1024
  49. URLFETCH_TIMEOUT = 60

  50. def message_html(title, banner, detail=''):
  51.     MESSAGE_TEMPLATE = '''
  52.     <html><head>
  53.     <meta http-equiv="content-type" content="text/html;charset=utf-8">
  54.     <title>$title</title>
  55.     <style><!--
  56.     body {font-family: arial,sans-serif}
  57.     div.nav {margin-top: 1ex}
  58.     div.nav A {font-size: 10pt; font-family: arial,sans-serif}
  59.     span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}
  60.     div.nav A,span.big {font-size: 12pt; color: #0000cc}
  61.     div.nav A {font-size: 10pt; color: black}
  62.     A.l:link {color: #6f6f6f}
  63.     A.u:link {color: green}
  64.     //--></style>
  65.     </head>
  66.     <body text=#000000 bgcolor=#ffffff>
  67.     <table border=0 cellpadding=2 cellspacing=0 width=100%>
  68.     <tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff><b>Message</b></td></tr>
  69.     <tr><td> </td></tr></table>
  70.     <blockquote>
  71.     <H1>$banner</H1>
  72.     $detail
  73.     <p>
  74.     </blockquote>
  75.     <table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=#3366cc><img alt="" width=1 height=4></td></tr></table>
  76.     </body></html>
  77.     '''
  78.     return string.Template(MESSAGE_TEMPLATE).substitute(title=title, banner=banner, detail=detail)


  79. try:
  80.     from Crypto.Cipher.ARC4 import new as _Crypto_Cipher_ARC4_new
  81. except ImportError:
  82.     logging.warn('Load Crypto.Cipher.ARC4 Failed, Use Pure Python Instead.')
  83.     class _Crypto_Cipher_ARC4_new(object):
  84.         def __init__(self, key):
  85.             x = 0
  86.             box = range(256)
  87.             for i, y in enumerate(box):
  88.                 x = (x + y + ord(key[i % len(key)])) & 0xff
  89.                 box[i], box[x] = box[x], y
  90.             self.__box = box
  91.             self.__x = 0
  92.             self.__y = 0
  93.         def encrypt(self, data):
  94.             out = []
  95.             out_append = out.append
  96.             x = self.__x
  97.             y = self.__y
  98.             box = self.__box
  99.             for char in data:
  100.                 x = (x + 1) & 0xff
  101.                 y = (y + box[x]) & 0xff
  102.                 box[x], box[y] = box[y], box[x]
  103.                 out_append(chr(ord(char) ^ box[(box[x] + box[y]) & 0xff]))
  104.             self.__x = x
  105.             self.__y = y
  106.             return ''.join(out)


  107. def rc4crypt(data, key):
  108.     return _Crypto_Cipher_ARC4_new(key).encrypt(data) if key else data


  109. class RC4FileObject(object):
  110.     """fileobj for rc4"""
  111.     def __init__(self, stream, key):
  112.         self.__stream = stream
  113.         self.__cipher = _Crypto_Cipher_ARC4_new(key) if key else lambda x:x
  114.     def __getattr__(self, attr):
  115.         if attr not in ('__stream', '__cipher'):
  116.             return getattr(self.__stream, attr)
  117.     def read(self, size=-1):
  118.         return self.__cipher.encrypt(self.__stream.read(size))


  119. def gae_application(environ, start_response):
  120.     cookie = environ.get('HTTP_COOKIE', '')
  121.     options = environ.get('HTTP_X_GOA_OPTIONS', '')
  122.     if environ['REQUEST_METHOD'] == 'GET' and not cookie:
  123.         if '204' in environ['QUERY_STRING']:
  124.             start_response('204 No Content', [])
  125.             yield ''
  126.         else:
  127.             timestamp = long(os.environ['CURRENT_VERSION_ID'].split('.')[1])/2**28
  128.             ctime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp+8*3600))
  129.             html = u'GoAgent Python Server %s \u5df2\u7ecf\u5728\u5de5\u4f5c\u4e86\uff0c\u90e8\u7f72\u65f6\u95f4 %s\n' % (__version__, ctime)
  130.             start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
  131.             yield html.encode('utf8')
  132.         raise StopIteration

  133.     # inflate = lambda x:zlib.decompress(x, -zlib.MAX_WBITS)
  134.     wsgi_input = environ['wsgi.input']
  135.     input_data = wsgi_input.read()

  136.     try:
  137.         if cookie:
  138.             if 'rc4' not in options:
  139.                 metadata = zlib.decompress(base64.b64decode(cookie), -zlib.MAX_WBITS)
  140.                 payload = input_data or ''
  141.             else:
  142.                 metadata = zlib.decompress(rc4crypt(base64.b64decode(cookie), __password__), -zlib.MAX_WBITS)
  143.                 payload = rc4crypt(input_data, __password__) if input_data else ''
  144.         else:
  145.             if 'rc4' in options:
  146.                 input_data = rc4crypt(input_data, __password__)
  147.             metadata_length, = struct.unpack('!h', input_data[:2])
  148.             metadata = zlib.decompress(input_data[2:2+metadata_length], -zlib.MAX_WBITS)
  149.             payload = input_data[2+metadata_length:]
  150.         headers = dict(x.split(':', 1) for x in metadata.splitlines() if x)
  151.         method = headers.pop('G-Method')
  152.         url = headers.pop('G-Url')
  153.     except (zlib.error, KeyError, ValueError):
  154.         import traceback
  155.         start_response('500 Internal Server Error', [('Content-Type', 'text/html')])
  156.         yield message_html('500 Internal Server Error', 'Bad Request (metadata) - Possible Wrong Password', '<pre>%s</pre>' % traceback.format_exc())
  157.         raise StopIteration

  158.     kwargs = {}
  159.     any(kwargs.__setitem__(x[2:].lower(), headers.pop(x)) for x in headers.keys() if x.startswith('G-'))

  160.     if 'Content-Encoding' in headers:
  161.         if headers['Content-Encoding'] == 'deflate':
  162.             payload = zlib.decompress(payload, -zlib.MAX_WBITS)
  163.             headers['Content-Length'] = str(len(payload))
  164.             del headers['Content-Encoding']

  165.     logging.info('%s "%s %s %s" - -', environ['REMOTE_ADDR'], method, url, 'HTTP/1.1')
  166.     #logging.info('request headers=%s', headers)

  167.     if __password__ and __password__ != kwargs.get('password', ''):
  168.         start_response('403 Forbidden', [('Content-Type', 'text/html')])
  169.         yield message_html('403 Wrong password', 'Wrong password(%r)' % kwargs.get('password', ''), 'GoAgent proxy.ini password is wrong!')
  170.         raise StopIteration

  171.     netloc = urlparse.urlparse(url).netloc

  172.     if __hostsdeny__ and netloc.endswith(__hostsdeny__):
  173.         start_response('403 Forbidden', [('Content-Type', 'text/html')])
  174.         yield message_html('403 Hosts Deny', 'Hosts Deny(%r)' % netloc, detail='url=%r' % url)
  175.         raise StopIteration

  176.     if netloc.startswith(('127.0.0.', '::1', 'localhost')):
  177.         start_response('400 Bad Request', [('Content-Type', 'text/html')])
  178.         html = ''.join('<a href="https://%s/">%s</a><br/>' % (x, x) for x in ('google.com', 'mail.google.com'))
  179.         yield message_html('GoAgent %s is Running' % __version__, 'Now you can visit some websites', html)
  180.         raise StopIteration

  181.     fetchmethod = getattr(urlfetch, method, None)
  182.     if not fetchmethod:
  183.         start_response('405 Method Not Allowed', [('Content-Type', 'text/html')])
  184.         yield message_html('405 Method Not Allowed', 'Method Not Allowed: %r' % method, detail='Method Not Allowed URL=%r' % url)
  185.         raise StopIteration

  186.     deadline = URLFETCH_TIMEOUT
  187.     validate_certificate = bool(int(kwargs.get('validate', 0)))
  188.     accept_encoding = headers.get('Accept-Encoding', '')
  189.     errors = []
  190.     for i in xrange(int(kwargs.get('fetchmax', URLFETCH_MAX))):
  191.         try:
  192.             response = urlfetch.fetch(url, payload, fetchmethod, headers, allow_truncated=False, follow_redirects=False, deadline=deadline, validate_certificate=validate_certificate)
  193.             break
  194.         except apiproxy_errors.OverQuotaError as e:
  195.             time.sleep(5)
  196.         except urlfetch.DeadlineExceededError as e:
  197.             errors.append('%r, deadline=%s' % (e, deadline))
  198.             logging.error('DeadlineExceededError(deadline=%s, url=%r)', deadline, url)
  199.             time.sleep(1)
  200.             deadline = URLFETCH_TIMEOUT * 2
  201.         except urlfetch.DownloadError as e:
  202.             errors.append('%r, deadline=%s' % (e, deadline))
  203.             logging.error('DownloadError(deadline=%s, url=%r)', deadline, url)
  204.             time.sleep(1)
  205.             deadline = URLFETCH_TIMEOUT * 2
  206.         except urlfetch.ResponseTooLargeError as e:
  207.             errors.append('%r, deadline=%s' % (e, deadline))
  208.             response = e.response
  209.             logging.error('ResponseTooLargeError(deadline=%s, url=%r) response(%r)', deadline, url, response)
  210.             m = re.search(r'=\s*(\d+)-', headers.get('Range') or headers.get('range') or '')
  211.             if m is None:
  212.                 headers['Range'] = 'bytes=0-%d' % int(kwargs.get('fetchmaxsize', URLFETCH_MAXSIZE))
  213.             else:
  214.                 headers.pop('Range', '')
  215.                 headers.pop('range', '')
  216.                 start = int(m.group(1))
  217.                 headers['Range'] = 'bytes=%s-%d' % (start, start+int(kwargs.get('fetchmaxsize', URLFETCH_MAXSIZE)))
  218.             deadline = URLFETCH_TIMEOUT * 2
  219.         except urlfetch.SSLCertificateError as e:
  220.             errors.append('%r, should validate=0 ?' % e)
  221.             logging.error('%r, deadline=%s', e, deadline)
  222.         except Exception as e:
  223.             errors.append(str(e))
  224.             if i == 0 and method == 'GET':
  225.                 deadline = URLFETCH_TIMEOUT * 2
  226.     else:
  227.         start_response('500 Internal Server Error', [('Content-Type', 'text/html')])
  228.         error_string = '<br />\n'.join(errors)
  229.         if not error_string:
  230.             logurl = 'https://appengine.google.com/logs?&app_id=%s' % os.environ['APPLICATION_ID']
  231.             error_string = 'Internal Server Error. <p/>try <a href="javascript:window.location.reload(true);">refresh</a> or goto <a href="%s" target="_blank">appengine.google.com</a> for details' % logurl
  232.         yield message_html('502 Urlfetch Error', 'Python Urlfetch Error: %r' % method,  error_string)
  233.         raise StopIteration

  234.     #logging.debug('url=%r response.status_code=%r response.headers=%r response.content[:1024]=%r', url, response.status_code, dict(response.headers), response.content[:1024])

  235.     data = response.content
  236.     response_headers = response.headers
  237.     if 'content-encoding' not in response_headers and len(response.content) < URLFETCH_DEFLATE_MAXSIZE and response_headers.get('content-type', '').startswith(('text/', 'application/json', 'application/javascript')):
  238.         if 'gzip' in accept_encoding:
  239.             response_headers['Content-Encoding'] = 'gzip'
  240.             compressobj = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0)
  241.             dataio = BytesIO()
  242.             dataio.write('\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff')
  243.             dataio.write(compressobj.compress(data))
  244.             dataio.write(compressobj.flush())
  245.             dataio.write(struct.pack('<LL', zlib.crc32(data) & 0xFFFFFFFFL, len(data) & 0xFFFFFFFFL))
  246.             data = dataio.getvalue()
  247.         elif 'deflate' in accept_encoding:
  248.             response_headers['Content-Encoding'] = 'deflate'
  249.             data = zlib.compress(data)[2:-4]
  250.     if data:
  251.          response_headers['Content-Length'] = str(len(data))
  252.     response_headers_data = zlib.compress('\n'.join('%s:%s' % (k.title(), v) for k, v in response_headers.items() if not k.startswith('x-google-')))[2:-4]
  253.     if 'rc4' not in options:
  254.         start_response('200 OK', [('Content-Type', 'image/gif')])
  255.         yield struct.pack('!hh', int(response.status_code), len(response_headers_data))+response_headers_data
  256.         yield data
  257.     else:
  258.         start_response('200 OK', [('Content-Type', 'image/gif'), ('X-GOA-Options', 'rc4')])
  259.         yield struct.pack('!hh', int(response.status_code), len(response_headers_data))
  260.         yield rc4crypt(response_headers_data, __password__)
  261.         yield rc4crypt(data, __password__)


  262. class LegacyHandler(object):
  263.     """GoAgent 1.x GAE Fetch Server"""
  264.     @classmethod
  265.     def application(cls, environ, start_response):
  266.         return cls()(environ, start_response)

  267.     def __call__(self, environ, start_response):
  268.         self.environ = environ
  269.         self.start_response = start_response
  270.         return self.process_request()

  271.     def send_response(self, status, headers, content, content_type='image/gif'):
  272.         headers['Content-Length'] = str(len(content))
  273.         strheaders = '&'.join('%s=%s' % (k, v.encode('hex')) for k, v in headers.iteritems() if v)
  274.         #logging.debug('response status=%s, headers=%s, content length=%d', status, headers, len(content))
  275.         if headers.get('content-type', '').startswith(('text/', 'application/json', 'application/javascript')):
  276.             data = '1' + zlib.compress('%s%s%s' % (struct.pack('>3I', status, len(strheaders), len(content)), strheaders, content))
  277.         else:
  278.             data = '0%s%s%s' % (struct.pack('>3I', status, len(strheaders), len(content)), strheaders, content)
  279.         self.start_response('200 OK', [('Content-type', content_type)])
  280.         return [data]

  281.     def send_notify(self, method, url, status, content):
  282.         logging.warning('%r Failed: url=%r, status=%r', method, url, status)
  283.         content = '<h2>Python Server Fetch Info</h2><hr noshade="noshade"><p>%s %r</p><p>Return Code: %d</p><p>Message: %s</p>' % (method, url, status, content)
  284.         return self.send_response(status, {'content-type': 'text/html'}, content)

  285.     def process_request(self):
  286.         environ = self.environ
  287.         if environ['REQUEST_METHOD'] == 'GET':
  288.             redirect_url = 'https://%s/2' % environ['HTTP_HOST']
  289.             self.start_response('302 Redirect', [('Location', redirect_url)])
  290.             return [redirect_url]

  291.         data = zlib.decompress(environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])))
  292.         request = dict((k, v.decode('hex')) for k, _, v in (x.partition('=') for x in data.split('&')))

  293.         method = request['method']
  294.         url = request['url']
  295.         payload = request['payload']

  296.         if __password__ and __password__ != request.get('password', ''):
  297.             return self.send_notify(method, url, 403, 'Wrong password.')

  298.         if __hostsdeny__ and urlparse.urlparse(url).netloc.endswith(__hostsdeny__):
  299.             return self.send_notify(method, url, 403, 'Hosts Deny: url=%r' % url)

  300.         fetchmethod = getattr(urlfetch, method, '')
  301.         if not fetchmethod:
  302.             return self.send_notify(method, url, 501, 'Invalid Method')

  303.         deadline = URLFETCH_TIMEOUT

  304.         headers = dict((k.title(), v.lstrip()) for k, _, v in (line.partition(':') for line in request['headers'].splitlines()))
  305.         headers['Connection'] = 'close'

  306.         errors = []
  307.         for i in xrange(URLFETCH_MAX if 'fetchmax' not in request else int(request['fetchmax'])):
  308.             try:
  309.                 response = urlfetch.fetch(url, payload, fetchmethod, headers, False, False, deadline, False)
  310.                 break
  311.             except apiproxy_errors.OverQuotaError as e:
  312.                 time.sleep(4)
  313.             except urlfetch.DeadlineExceededError as e:
  314.                 errors.append('DeadlineExceededError %s(deadline=%s)' % (e, deadline))
  315.                 logging.error('DeadlineExceededError(deadline=%s, url=%r)', deadline, url)
  316.                 time.sleep(1)
  317.             except urlfetch.DownloadError as e:
  318.                 errors.append('DownloadError %s(deadline=%s)' % (e, deadline))
  319.                 logging.error('DownloadError(deadline=%s, url=%r)', deadline, url)
  320.                 time.sleep(1)
  321.             except urlfetch.InvalidURLError as e:
  322.                 return self.send_notify(method, url, 501, 'Invalid URL: %s' % e)
  323.             except urlfetch.ResponseTooLargeError as e:
  324.                 response = e.response
  325.                 logging.error('ResponseTooLargeError(deadline=%s, url=%r) response(%r)', deadline, url, response)
  326.                 m = re.search(r'=\s*(\d+)-', headers.get('Range') or headers.get('range') or '')
  327.                 if m is None:
  328.                     headers['Range'] = 'bytes=0-%d' % URLFETCH_MAXSIZE
  329.                 else:
  330.                     headers.pop('Range', '')
  331.                     headers.pop('range', '')
  332.                     start = int(m.group(1))
  333.                     headers['Range'] = 'bytes=%s-%d' % (start, start+URLFETCH_MAXSIZE)
  334.                 deadline = URLFETCH_TIMEOUT * 2
  335.             except Exception as e:
  336.                 errors.append('Exception %s(deadline=%s)' % (e, deadline))
  337.         else:
  338.             return self.send_notify(method, url, 500, 'Python Server: Urlfetch error: %s' % errors)

  339.         headers = response.headers
  340.         if 'content-length' not in headers:
  341.             headers['content-length'] = str(len(response.content))
  342.         headers['connection'] = 'close'
  343.         return self.send_response(response.status_code, headers, response.content)


  344. def forward_socket(local, remote, timeout=60, tick=2, bufsize=8192, maxping=None, maxpong=None, pongcallback=None, trans=None):
  345.     try:
  346.         timecount = timeout
  347.         while 1:
  348.             timecount -= tick
  349.             if timecount <= 0:
  350.                 break
  351.             (ins, _, errors) = select.select([local, remote], [], [local, remote], tick)
  352.             if errors:
  353.                 break
  354.             if ins:
  355.                 for sock in ins:
  356.                     data = sock.recv(bufsize)
  357.                     if trans:
  358.                         data = data.translate(trans)
  359.                     if data:
  360.                         if sock is remote:
  361.                             local.sendall(data)
  362.                             timecount = maxpong or timeout
  363.                             if pongcallback:
  364.                                 try:
  365.                                     #remote_addr = '%s:%s'%remote.getpeername()[:2]
  366.                                     #logging.debug('call remote=%s pongcallback=%s', remote_addr, pongcallback)
  367.                                     pongcallback()
  368.                                 except Exception as e:
  369.                                     logging.warning('remote=%s pongcallback=%s failed: %s', remote, pongcallback, e)
  370.                                 finally:
  371.                                     pongcallback = None
  372.                         else:
  373.                             remote.sendall(data)
  374.                             timecount = maxping or timeout
  375.                     else:
  376.                         return
  377.     except socket.error as e:
  378.         if e[0] not in (10053, 10054, 10057, errno.EPIPE):
  379.             raise
  380.     finally:
  381.         if local:
  382.             local.close()
  383.         if remote:
  384.             remote.close()


  385. def paas_application(environ, start_response):
  386.     if environ['REQUEST_METHOD'] == 'GET':
  387.         start_response('302 Found', [('Location', 'https://www.google.com')])
  388.         raise StopIteration

  389.     wsgi_input = environ['wsgi.input']
  390.     data = wsgi_input.read(2)
  391.     metadata_length, = struct.unpack('!h', data)
  392.     metadata = wsgi_input.read(metadata_length)

  393.     metadata = zlib.decompress(metadata, -zlib.MAX_WBITS)
  394.     headers = {}
  395.     for line in metadata.splitlines():
  396.         if line:
  397.             keyword, value = line.split(':', 1)
  398.             headers[keyword.title()] = value.strip()
  399.     method = headers.pop('G-Method')
  400.     url = headers.pop('G-Url')
  401.     timeout = URLFETCH_TIMEOUT

  402.     kwargs = {}
  403.     any(kwargs.__setitem__(x[2:].lower(), headers.pop(x)) for x in headers.keys() if x.startswith('G-'))

  404.     if __password__ and __password__ != kwargs.get('password'):
  405.         random_host = 'g%d%s' % (int(time.time()*100), environ['HTTP_HOST'])
  406.         conn = httplib.HTTPConnection(random_host, timeout=timeout)
  407.         conn.request('GET', '/')
  408.         response = conn.getresponse(True)
  409.         status_line = '%s %s' % (response.status, httplib.responses.get(response.status, 'OK'))
  410.         start_response(status_line, response.getheaders())
  411.         yield response.read()
  412.         raise StopIteration

  413.     if __hostsdeny__ and urlparse.urlparse(url).netloc.endswith(__hostsdeny__):
  414.         start_response('403 Forbidden', [('Content-Type', 'text/html')])
  415.         yield message_html('403 Forbidden Host', 'Hosts Deny(%s)' % url, detail='url=%r' % url)
  416.         raise StopIteration

  417.     headers['Connection'] = 'close'
  418.     payload = environ['wsgi.input'].read() if 'Content-Length' in headers else None
  419.     if 'Content-Encoding' in headers:
  420.         if headers['Content-Encoding'] == 'deflate':
  421.             payload = zlib.decompress(payload, -zlib.MAX_WBITS)
  422.             headers['Content-Length'] = str(len(payload))
  423.             del headers['Content-Encoding']

  424.     logging.info('%s "%s %s %s" - -', environ['REMOTE_ADDR'], method, url, 'HTTP/1.1')

  425.     if method == 'CONNECT':
  426.         if not socket:
  427.             start_response('403 Forbidden', [('Content-Type', 'text/html')])
  428.             yield message_html('403 Forbidden CONNECT', 'socket not available', detail='`import socket` raised ImportError')
  429.             raise StopIteration
  430.         rfile = wsgi_input.rfile
  431.         sock = rfile._sock
  432.         host, _, port = url.rpartition(':')
  433.         port = int(port)
  434.         remote_sock = socket.create_connection((host, port), timeout=timeout)
  435.         start_response('200 OK', [])
  436.         forward_socket(sock, remote_sock)
  437.         yield 'out'
  438.     else:
  439.         try:
  440.             scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
  441.             HTTPConnection = httplib.HTTPSConnection if scheme == 'https' else httplib.HTTPConnection
  442.             if params:
  443.                 path += ';' + params
  444.             if query:
  445.                 path += '?' + query
  446.             conn = HTTPConnection(netloc, timeout=timeout)
  447.             conn.request(method, path, body=payload, headers=headers)
  448.             response = conn.getresponse()

  449.             headers_data = zlib.compress('\n'.join('%s:%s' % (k.title(), v) for k, v in response.getheaders()))[2:-4]
  450.             start_response('200 OK', [('Content-Type', 'image/gif')])
  451.             yield struct.pack('!hh', int(response.status), len(headers_data))+headers_data
  452.             while 1:
  453.                 data = response.read(8192)
  454.                 if not data:
  455.                     response.close()
  456.                     break
  457.                 yield data
  458.         except httplib.HTTPException:
  459.             raise


  460. app = gae_application if urlfetch else paas_application
  461. if bae:
  462.     application = bae.core.wsgi.WSGIApplication(app)
  463. elif sae:
  464.     application = sae.create_wsgi_app(app)
  465. else:
  466.     application = app

  467. if __name__ == '__main__':
  468.     logging.basicConfig(level=logging.INFO, format='%(levelname)s - - %(asctime)s %(message)s', datefmt='[%b %d %H:%M:%S]')
  469.     import gevent
  470.     import gevent.server
  471.     import gevent.wsgi
  472.     import gevent.monkey
  473.     gevent.monkey.patch_all(dns=gevent.version_info[0] >= 1)

  474.     server = gevent.wsgi.WSGIServer(('', int(sys.argv[1])), application)
  475.     logging.info('local paas_application serving at %s:%s', server.address[0], server.address[1])
  476.     server.serve_forever()
复制代码

PHP版:
  1. <?php

  2. // Note:
  3. //     Please try to use the https url to bypass keyword filtering.
  4. //     Otherwise, dont forgot set [paas]passowrd in proxy.ini
  5. // Contributor:
  6. //     Phus Lu        <phus.lu@gmail.com>

  7. $__version__  = '3.0.5';
  8. $__password__ = '123';
  9. $__timeout__  = 20;

  10. class URLFetch {
  11.     protected $body_maxsize = 4194304;
  12.     protected $headers = array();
  13.     protected $body = '';
  14.     protected $body_size = 0;

  15.     function __construct() {
  16.     }

  17.     function urlfetch_readheader($ch, $header) {
  18.         $kv = array_map('trim', explode(':', $header, 2));
  19.         if (isset($kv[1])) {
  20.             $key = join('-', array_map('ucfirst', explode('-', $kv[0])));
  21.             $value = $kv[1];
  22.             if ($key == 'Set-Cookie') {
  23.                 if (!array_key_exists('Set-Cookie', $this->headers)) {
  24.                     $this->headers['Set-Cookie'] = $value;
  25.                 } else {
  26.                     $this->headers['Set-Cookie'] .= "\r\nSet-Cookie: " . $value;
  27.                 }
  28.             } else {
  29.                 $this->headers[$key] = $kv[1];
  30.             }
  31.         }
  32.         return strlen($header);
  33.     }

  34.     function urlfetch_readbody($ch, $data) {
  35.         $bytes = strlen($data);
  36.         if ($this->body_size + $bytes > $this->body_maxsize) {
  37.             return -1;
  38.         }
  39.         $this->body_size += $bytes;
  40.         $this->body .= $data;
  41.         return $bytes;
  42.     }

  43.     function urlfetch($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate) {

  44.         $this->headers = array();
  45.         $this->body = '';
  46.         $this->body_size = 0;

  47.         if ($payload) {
  48.             $headers['Content-Length'] = strval(strlen($payload));
  49.         }
  50.         $headers['Connection'] = 'close';

  51.         $curl_opt = array();

  52.         $curl_opt[CURLOPT_TIMEOUT]        = $deadline;
  53.         $curl_opt[CURLOPT_CONNECTTIMEOUT] = $deadline;
  54.         $curl_opt[CURLOPT_RETURNTRANSFER] = true;
  55.         $curl_opt[CURLOPT_BINARYTRANSFER] = true;
  56.         $curl_opt[CURLOPT_FAILONERROR]    = true;

  57.         if (!$follow_redirects) {
  58.             $curl_opt[CURLOPT_FOLLOWLOCATION] = false;
  59.         }

  60.         if ($deadline) {
  61.             $curl_opt[CURLOPT_CONNECTTIMEOUT] = $deadline;
  62.             $curl_opt[CURLOPT_TIMEOUT] = $deadline;
  63.         }

  64.         if (!$validate_certificate) {
  65.             $curl_opt[CURLOPT_SSL_VERIFYPEER] = false;
  66.             $curl_opt[CURLOPT_SSL_VERIFYHOST] = false;
  67.         }

  68.         switch (strtoupper($method)) {
  69.             case 'HEAD':
  70.                 $curl_opt[CURLOPT_NOBODY] = true;
  71.                 break;
  72.             case 'GET':
  73.                 break;
  74.             case 'POST':
  75.                 $curl_opt[CURLOPT_POST] = true;
  76.                 $curl_opt[CURLOPT_POSTFIELDS] = $payload;
  77.                 break;
  78.             case 'PUT':
  79.             case 'DELETE':
  80.                 $curl_opt[CURLOPT_CUSTOMREQUEST] = $method;
  81.                 $curl_opt[CURLOPT_POSTFIELDS] = $payload;
  82.                 break;
  83.             default:
  84.                 print(message_html('502 Urlfetch Error', 'Invalid Method: ' . $method,  $url));
  85.                 exit(-1);
  86.         }

  87.         $header_array = array();
  88.         foreach ($headers as $key => $value) {
  89.             if ($key) {
  90.                 $header_array[] = join('-', array_map('ucfirst', explode('-', $key))).': '.$value;
  91.             }
  92.         }
  93.         $curl_opt[CURLOPT_HTTPHEADER] = $header_array;

  94.         $curl_opt[CURLOPT_HEADER]         = false;
  95.         $curl_opt[CURLOPT_HEADERFUNCTION] = array(&$this, 'urlfetch_readheader');
  96.         $curl_opt[CURLOPT_WRITEFUNCTION]  = array(&$this, 'urlfetch_readbody');

  97.         $ch = curl_init($url);
  98.         curl_setopt_array($ch, $curl_opt);
  99.         $ret = curl_exec($ch);
  100.         $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  101.         $errno = curl_errno($ch);
  102.         if ($errno)
  103.         {
  104.             $error =  $errno . ': ' .curl_error($ch);
  105.         } else {
  106.             $error = '';
  107.         }
  108.         curl_close($ch);

  109.         $this->headers['Connection'] = 'close';
  110.         $content_length = isset($this->headers['Content-Length']) ? 1*$this->headers['Content-Length'] : 0;

  111.         if ($status < 200 && $errno == 23 && $content_length && $this->body_size < $content_length) {
  112.             $status = 206;
  113.             $range_end = $this->body_size - 1;
  114.             $this->headers['Content-Range'] = "bytes 0-$range_end/$content_length";
  115.             $this->headers['Accept-Ranges'] = 'bytes';
  116.             $this->headers['Content-Length'] = $this->body_size;
  117.         }

  118.         $response = array('status' => $status, 'headers' => $this->headers, 'content' => $this->body, 'error' => $error);
  119.         return $response;
  120.     }
  121. }


  122. function message_html($title, $banner, $detail) {
  123.     $error = <<<ERROR_STRING
  124. <html><head>
  125. <meta http-equiv="content-type" content="text/html;charset=utf-8">
  126. <title>${title}</title>
  127. <style><!--
  128. body {font-family: arial,sans-serif}
  129. div.nav {margin-top: 1ex}
  130. div.nav A {font-size: 10pt; font-family: arial,sans-serif}
  131. span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}
  132. div.nav A,span.big {font-size: 12pt; color: #0000cc}
  133. div.nav A {font-size: 10pt; color: black}
  134. A.l:link {color: #6f6f6f}
  135. A.u:link {color: green}
  136. //--></style>

  137. </head>
  138. <body text=#000000 bgcolor=#ffffff>
  139. <table border=0 cellpadding=2 cellspacing=0 width=100%>
  140. <tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff><b>Error</b></td></tr>
  141. <tr><td>&nbsp;</td></tr></table>
  142. <blockquote>
  143. <H1>${banner}</H1>
  144. ${detail}

  145. <p>
  146. </blockquote>
  147. <table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=#3366cc><img alt="" width=1 height=4></td></tr></table>
  148. </body></html>
  149. ERROR_STRING;
  150.     return $error;
  151. }


  152. function decode_request($data) {
  153.     list($headers_length) = array_values(unpack('n', substr($data, 0, 2)));
  154.     $headers_data = gzinflate(substr($data, 2, $headers_length));
  155.     $body = substr($data, 2+intval($headers_length));

  156.     $method  = '';
  157.     $url     = '';
  158.     $headers = array();
  159.     $kwargs  = array();

  160.     foreach (explode("\n", $headers_data) as $kv) {
  161.         $pair = explode(':', $kv, 2);
  162.         $key  = $pair[0];
  163.         $value = trim($pair[1]);
  164.         if ($key == 'G-Method') {
  165.             $method = $value;
  166.         } else if ($key == 'G-Url') {
  167.             $url = $value;
  168.         } else if (substr($key, 0, 2) == 'G-') {
  169.             $kwargs[strtolower(substr($key, 2))] = $value;
  170.         } else if ($key) {
  171.             $key = join('-', array_map('ucfirst', explode('-', $key)));
  172.             $headers[$key] = $value;
  173.         }
  174.     }
  175.     if (isset($headers['Content-Encoding'])) {
  176.         if ($headers['Content-Encoding'] == 'deflate') {
  177.             $body = gzinflate($body);
  178.             $headers['Content-Length'] = strval(strlen($body));
  179.             unset($headers['Content-Encoding']);
  180.         }
  181.     }
  182.     return array($method, $url, $headers, $kwargs, $body);
  183. }

  184. function print_response($status, $headers, $content, $support_gzip=true) {
  185.     $headers['Content-Length'] = strval(strlen($content));
  186.     $strheaders = '';
  187.     foreach ($headers as $key => $value) {
  188.         $strheaders .= $key. ':' . $value . "\n";
  189.     }
  190.     $content_type = isset($headers['Content-Type']) ? $headers['Content-Type'] : '';
  191.     if ($support_gzip && !isset($headers['Content-Encoding']) && $content_type && (substr($content_type, 0, 5) == 'text/' || substr($content_type, 0, 16) == 'application/json' || substr($content_type, 0, 22) == 'application/javascript')) {
  192.         $strheaders .= 'Content-Encoding:gzip';
  193.         $content = gzcompress($content);
  194.     }
  195.     $response_headers_data = gzdeflate(rtrim($strheaders));
  196.     header('Content-Type: image/gif');
  197.     print(pack('nn', $status, strlen($response_headers_data)) . $response_headers_data);
  198.     print($content);
  199. }


  200. function post()
  201. {
  202.     list($method, $url, $headers, $kwargs, $body) = @decode_request(@file_get_contents('php://input'));

  203.     if ($GLOBALS['__password__']) {
  204.         if (!isset($kwargs['password']) || $GLOBALS['__password__'] != $kwargs['password']) {
  205.             header("HTTP/1.0 403 Forbidden");
  206.             echo '403 Forbidden';
  207.             exit(-1);
  208.         }
  209.     }

  210.     if (isset($kwargs['hostip']) && isset($headers['Host'])) {
  211.         $ip = $kwargs['hostip'];
  212.         $url = preg_replace('#(.+://)([\w\.\-]+)#', '${1}'.$ip, $url);
  213.     }

  214.     $headers['Connection'] = 'close';

  215.     $urlfetch = new URLFetch();
  216.     $response = $urlfetch->urlfetch($url, $body, $method, $headers, False, $deadline, False);
  217.     $status = $response['status'];
  218.     if (200 <= $status && $status < 400) {
  219.         print_response($status, $response['headers'], $response['content'], isset($headers['Accept-Encoding']) && strpos($headers['Accept-Encoding'], 'gzip'));
  220.     } else {
  221.         header('HTTP/1.0 502');
  222.         echo message_html('502 Urlfetch Error', 'PHP Curl Urlfetch Error: ' . $status,  $response['error']);
  223.     }
  224. }

  225. function get() {
  226.     $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
  227.     $domain = preg_replace('/.*\\.(.+\\..+)$/', '$1', $host);
  228.     if ($host && $host != $domain && $host != 'www'.$domain) {
  229.         header('Location: http://www.' . $domain);
  230.     } else {
  231.         header('Location: https://www.google.com');
  232.     }
  233. }

  234. function main() {
  235.     if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  236.         post();
  237.     } else {
  238.         get();
  239.     }
  240. }

  241. main();
复制代码

上传到web目录配置goagent的ini即可。
过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

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