示例#1
0
 async def _handle_user(self, user):
     # ignore client SOCKS5 greeting
     data = await user.reader.read(256)
     logger.debug('ignore SOCK5 greeting ({} bytes)'.format(len(data)))
     # response greeting without auth
     server_greeting = socks.ServerGreeting()
     await self.safe_write(user.writer, server_greeting.to_bytes())
     # recv CMD
     try:
         msg = await socks.Message.from_reader(user.reader)
     except asyncio.streams.IncompleteReadError:
         self._delete_user(user)
         return
     if msg.code is not socks.CMD.CONNECT:
         logger.warn('unhandle msg {}'.format(msg))
         rep = socks.Message(socks.VER.SOCKS5,
                             socks.REP.COMMAND_NOT_SUPPORTED,
                             socks.ATYPE.IPV4, ('0', 0))
         await self.safe_write(user.writer, rep.to_bytes())
         return
     logger.info('connecting {}:{}'.format(msg.addr[0], msg.addr[1]))
     # send to tunnel
     connect_reqeust = protocol.Request(user.user_id, 0, msg)
     await self.safe_write(self.tunnel_writer,
                           connect_reqeust.to_packet(self.fuzz))
     await self._pipe_user(user)
示例#2
0
 async def connect(self, host, port):
     self.state = self.CMD
     loop = asyncio.get_event_loop()
     bind_addr = ('255.255.255.255', 0)
     try:
         logger.info('connecting {}:{}'.format(host, port))
         fut = loop.create_connection(Client, host, port)
         transport, client = await \
             asyncio.wait_for(fut, timeout=config.timeout)
     except (asyncio.TimeoutError, ConnectionRefusedError,
             socket.gaierror) as e:
         logger.warn('connect {}'.format(e))
         socks_err = socks.Message(socks.VER.SOCKS5,
                                   socks.REP.NETWORK_UNREACHABLE,
                                   socks.ATYPE.IPV4, bind_addr)
         rep = protocol.Reply(self.remote, self.user, socks_err)
         self.tunnel_transport.write(rep.to_packet(self.fuzz))
         self.state = self.IDLE
         return
     client.channel = self
     self.remote_transport = transport
     self.remote = transport._sock_fd
     bind_addr = transport.get_extra_info('sockname')
     socks_ok = socks.Message(socks.VER.SOCKS5, socks.REP.SUCCEEDED,
                              socks.ATYPE.IPV4, bind_addr)
     rep = protocol.Reply(self.remote, self.user, socks_ok)
     self.tunnel_transport.write(rep.to_packet(self.fuzz))
     self.state = self.DATA
     logger.debug('channel {} opened'.format(self))
示例#3
0
 def packet_received(self, packet_data):
     if self.state == self.GREETING:
         packet = protocol.read_packet(io.BytesIO(packet_data), self.cipher)
         if packet.mtype is not protocol.MTYPE.HELLO:
             self.transport.abort()
             self.state = self.CLOSING
             return
         self.transport.write(protocol.Hello().to_packet(self.cipher))
         self.tunnel = Tunnel(self.transport, self.fuzz)
         self.state = self.NEGOTIATING
     elif self.state == self.NEGOTIATING:
         packet = protocol.read_packet(io.BytesIO(packet_data), self.cipher)
         if packet.mtype is not protocol.MTYPE.HANDSHAKE:
             self.transport.abort()
             self.state = self.CLOSING
         fuzz = self.choose_fuzzer(packet.fuzz.fuzz_list)
         logger.info('choose {}'.format(fuzz))
         response = protocol.HandShake(fuzz=fuzz)
         self.transport.write(response.to_packet(self.cipher))
         self.fuzz = fuzz
         self.tunnel.fuzz = fuzz
         self.state = self.OPEN
     elif self.state == self.OPEN:
         packet = protocol.read_packet(io.BytesIO(packet_data), self.fuzz)
         self.tunnel.handle_request(packet)
     else:
         logger.warn('tunel is closing')
示例#4
0
 def data_received(self, data):
     # logger.debug('{}: {}'.format(self.user, data))
     if self.state == self.INIT:
         client_greeting = socks.ClientGreeting.from_stream(
             io.BytesIO(data))
         server_greeting = socks.ServerGreeting()
         self.transport.write(server_greeting.to_bytes())
         self.state = self.CMD
     elif self.state == self.CMD:
         msg = socks.Message.from_stream(io.BytesIO(data))
         global concurrent
         logger.info('connecting {}:{} ({})'.format(msg.addr[0],
                                                    msg.addr[1],
                                                    concurrent))
         bind_addr = ('127.0.0.1', 9999)
         if msg.code is not socks.CMD.CONNECT:
             rep = socks.Message(socks.VER.SOCKS5,
                                 socks.REP.COMMAND_NOT_SUPPORTED,
                                 socks.ATYPE.IPV4, bind_addr)
             self.transport.write(rep.to_bytes())
             return
         # connect
         asyncio.ensure_future(self.connect(msg.addr[0], msg.addr[1]))
     elif self.state == self.DATA:
         self.client_transport.write(data)
     else:
         logger.warn('receiving data from user in CLOSED state')
示例#5
0
    async def _handle_client(self, client_reader, client_writer):
        # ignore client greeting
        data = await client_reader.read(32)
        logger.debug('Ignore client greeting ({} bytes)'.format(len(data)))
        server_greeting = socks.ServerGreeting()
        client_writer.write(server_greeting.to_bytes())
        # recv CMD
        msg = await socks.Message.from_reader(client_reader)
        if msg.code is not socks.CMD.CONNECT:
            logger.warn('unhandle msg {}'.format(msg))
            return
        fut = asyncio.open_connection(msg.addr[0], msg.addr[1])
        try:
            remote_reader, remote_writer = await asyncio.wait_for(fut, 3)
        except (asyncio.TimeoutError, ConnectionRefusedError):
            logger.warn('connet {}:{} failed'.format(msg.addr[0], msg.addr[1]))
            err_reply = socks.Message(ver=socks.VER.SOCKS5,
                                      code=socks.REP.CONNECTION_REFUSED,
                                      atype=socks.ATYPE.IPV4,
                                      addr=('127.0.0.1', 9999))
            client_writer.write(err_reply.to_bytes())
            return

        logger.info('connected to {}:{}'.format(msg.addr[0], msg.addr[1]))
        # send REP
        bind_address = remote_writer.transport._extra['sockname']
        reply = socks.Message(ver=socks.VER.SOCKS5,
                              code=socks.REP.SUCCEEDED,
                              atype=socks.ATYPE.IPV4,
                              addr=bind_address)
        client_writer.write(reply.to_bytes())
        # piping
        await asyncio.gather(pipe('remote', remote_reader, client_writer),
                             pipe('user', client_reader, remote_writer))
示例#6
0
 def forward(self, payload, upstream=True):
     if self.state != self.DATA:
         logger.warn('channel is not ready')
         return
     if upstream:
         return self.remote_transport.write(payload)
     packet = protocol.Relaying(self.remote, self.user, payload)
     return self.tunnel_transport.write(packet.to_packet(self.fuzz))
示例#7
0
 async def _pipe_user(self, user):
     # may start before connection to remote is established
     while True:
         try:
             data = await user.reader.read(2048)
         except ConnectionResetError:
             logger.warn('user connection reset')
             data = b''
         if len(data) == 0:
             self._user_closed(user)
             break
         assert user.established
         packet = protocol.Relaying(user.user_id, user.remote_id, data)
         await self.safe_write(self.tunnel_writer,
                               packet.to_packet(self.fuzz))
示例#8
0
async def pipe(name, reader, writer):
    while True:
        try:
            data = await reader.read(2048)
        except ConnectionResetError as e:
            logger.warn('connection reset by ' + name)
            break
        except asyncio.CancelledError as e:
            logger.debug('pipe canceled.')
            break
        if len(data) == 0:
            logger.debug('{} connection closed'.format(name))
            break
        writer.write(data)
    return None
示例#9
0
 def handle_request(self, packet):
     if packet.mtype is protocol.MTYPE.REQUEST:
         msg = packet.msg
         if msg.code is not socks.CMD.CONNECT:
             logger.warn('unsupported msg: {}'.format(msg))
             return
         user = packet.src
         chan = Channel(self.transport, self.fuzz, user)
         asyncio.ensure_future(chan.connect(msg.addr[0], msg.addr[1]))
         self.channels[user] = chan
     elif packet.mtype is protocol.MTYPE.RELAYING:
         user = packet.src
         self.channels[user].forward(packet.payload)
     elif packet.mtype is protocol.MTYPE.CLOSE:
         user = packet.src
         self.channels[user].close()
     else:
         logger.warn('unkown packet {}'.format(packet))
示例#10
0
 async def _handle_tunnel(self, reader, writer):
     logger.debug('_handle_tunnel started')
     while True:
         packet = await protocol.async_read_packet(reader, self.fuzz)
         if packet.mtype is protocol.MTYPE.REPLY:
             # received a SOCKS reply, update mapping
             # and forward to corresponding user
             remote_id = packet.src
             user_id = packet.dst
             user = self._get_user(user_id)
             if user is None:
                 # Tell server to close
                 continue
             await self.safe_write(user.writer, packet.msg.to_bytes())
             user.remote_id = remote_id
         elif packet.mtype is protocol.MTYPE.RELAYING:
             # received raw data, forwarding
             remote_id = packet.src
             user_id = packet.dst
             user = self._get_user(user_id)
             if user is None:
                 # Tell server to close
                 continue
             await self.safe_write(user.writer, packet.payload)
         elif packet.mtype is protocol.MTYPE.CLOSE:
             # close user tansport
             user_id = packet.src
             logger.debug(
                 'remote disconnected, close user {}'.format(user_id))
             user = self._get_user(user_id)
             if user is None:
                 # ignore
                 continue
             self._delete_user(user)
         else:
             logger.warn('unknown packet {}'.format(packet))
     logger.debug('_handle_tunnel exited')
示例#11
0
 async def safe_write(self, writer, data):
     writer.write(data)
     try:
         await writer.drain()
     except ConnectionResetError as e:
         logger.warn('write error: {}'.format(e))
示例#12
0
 def tunnel_done(task):
     logger.warn('tunnel is closed')
     sys.exit(2)
示例#13
0
 def connection_lost(self, exc):
     global concurrent
     concurrent -= 1
     if exc is not None:
         logger.warn('remote closed: {}'.format(exc))
     self.channel.close()
示例#14
0
 def data_received(self, data):
     if self.state == self.OPEN:
         self.server_transport.write(data)
     else:
         logger.warn('receiving data from server in CLOSED state')