async def websocket_handler(request): peername = request.transport.get_extra_info('peername') if peername is not None: host, port = peername loop = asyncio.get_event_loop() queue = asyncio.Queue(loop=loop) ws = web.WebSocketResponse() await ws.prepare(request) key = b'1234567890123456' # DEFAULT PASSWORD, NEVER USE! key = os.environ['PASS'].encode() future1 = None future2 = None preaddrind = 0 secretdata, nonce = None, None gotdata = None async for msg in ws: if msg.type == aiohttp.WSMsgType.BINARY: secretdata = msg.data[:-16] nonce = msg.data[-16:] gotdata = mydecrypt((secretdata, nonce), key) secretdata, nonce = None, None if preaddrind == 0: preaddrind = 1 addrtype = gotdata[0] if addrtype == 3: addrlen = gotdata[1] if addrtype == 1: remotehost = socket.inet_ntoa(gotdata[1:5]) remoteport = struct.unpack('>H', gotdata[5:7])[0] if addrtype == 3: remotehost = gotdata[2:2 + addrlen] remoteport = struct.unpack( '>H', gotdata[2 + addrlen:4 + addrlen])[0] remotehost = remotehost.decode() if addrtype == 1 or addrtype == 3: logger.debug('%r Connect to %r at address %r' % (peername, remotehost, remoteport)) try: reader, writer = await asyncio.open_connection( host=remotehost, port=remoteport) future1 = asyncio.run_coroutine_threadsafe( remotereader(key, reader, ws), loop) future2 = asyncio.run_coroutine_threadsafe( remotewriter(writer, queue), loop) except Exception as e: logger.debug('%r Connect remote %r at address %r' % (peername, remotehost, remoteport)) logger.exception( 'Exception while connecting remote server %r' % e) senddata = b'*** remote unaccess ***' encdata = myencrypt(senddata, key) await ws.send_bytes(encdata[0] + encdata[1]) break else: break else: await queue.put(gotdata) elif msg.type == aiohttp.WSMsgType.CLOSED: await queue.put(None) break elif msg.type == aiohttp.WSMsgType.ERROR: await queue.put(None) logger.debug('ws connection closed with exception %r' % ws.exception()) break if future1: future1.cancel() if future2: future2.cancel() return ws
async def localproxy(reader, writer): addrToSend = "" loop = asyncio.get_event_loop() queue = asyncio.Queue(loop=loop) key = config['key'].encode() url = config['url'] proxy = config['proxy'] connectstr = '' client_address = writer.get_extra_info('peername') logger.info('client connected: %r %r' % client_address) get_text = await reader.read(262) writer.write(b'\x05\x00') await writer.drain() data = await reader.read(4) if len(data) == 4 and url != '': fullurl = 'https://' + url + '/ws' mode = data[1] addrtype = data[3] addrToSend = data[3:4] if addrtype == 1: ip_bytes = await reader.read(4) addr = socket.inet_ntoa(ip_bytes) addrToSend = addrToSend + ip_bytes elif addrtype == 3: addrlen_byte = await reader.read(1) addrlen = ord(addrlen_byte) addr = await reader.read(addrlen) addrToSend = addrToSend + addrlen_byte + addr addr = addr.decode() port = await reader.read(2) addrToSend = addrToSend + port reply = b"\x05\x00\x00\x01\x00\x00\x00\x00" logger.info('%r connect remote :%r %r' % (client_address, addr, struct.unpack('>H', port)[0])) if mode != 1: logger.info('unsupported mode: %r' % mode) reply = b"\x05\x07\x00\x01" writer.write(reply) await writer.drain() writer.close() if mode == 1: writer.write(reply + port) await writer.drain() config['concurrent'] = config['concurrent'] + 1 logger.info('Concurrent connetion %d' % config['concurrent']) async with aiohttp.ClientSession() as session: try: wsconnectargs = {} if proxy: wsconnectargs['proxy'] = proxy async with session.ws_connect(fullurl, **wsconnectargs) as ws: senddata = addrToSend encdata = myencrypt(senddata, key) await ws.send_bytes(encdata[0] + encdata[1]) future1 = asyncio.run_coroutine_threadsafe( localreader(client_address, key, reader, ws), loop) future2 = asyncio.run_coroutine_threadsafe( localwriter(client_address, writer, queue), loop) secretdata, nonce = None, None decMsg = None async for msg in ws: if msg.type == aiohttp.WSMsgType.BINARY: secretdata = msg.data[:-16] nonce = msg.data[-16:] decMsg = mydecrypt((secretdata, nonce), key) secretdata, nonce = None, None if decMsg != b'*** remote unaccess ***': await queue.put(decMsg) else: await queue.put(None) break decMsg = None elif msg.type == aiohttp.WSMsgType.CLOSED: break elif msg.type == aiohttp.WSMsgType.ERROR: logger.info( '%r ws connection closed with exception %s' % (client_address, ws.exception())) break future1.cancel() future2.cancel() except aiohttp.client_exceptions.ClientConnectorError: logger.info( '%r ws connection time out!', client_address ) #aiohttp.client_exceptions.ClientConnectorError config['concurrent'] = config['concurrent'] - 1 logger.info('Concurrent connetion %d' % config['concurrent']) writer.close() gc.collect()