예제 #1
0
 def test_equal(self):
     header1 = ShadowsocksPacketHeader(
         port=80,
         addr_type=constants.SOCKS5_ADDRTYPE_HOST,
         addr='www.google.com')
     header2 = ShadowsocksPacketHeader(
         port=80,
         addr_type=constants.SOCKS5_ADDRTYPE_HOST,
         addr='www.google.com')
     self.assertEqual(header1, header2)
예제 #2
0
    def test_fields(self):
        header = ShadowsocksPacketHeader()
        header.port = 999
        header.addr_type = 1
        header.addr = '192.168.18.1'

        self.assertEqual(header.port, 999)
        self.assertEqual(header.addr_type, 1)
        self.assertEqual(header.addr, '192.168.18.1')

        # specified fields that do not assigned will return None instead of rasing KeyError
        self.assertIsNone(header.sha1_hmac)

        with self.assertRaises(KeyError):
            header.not_exist = 9
예제 #3
0
    def test_data_relay(self):
        # Create a pair of connected sockets
        lsock, rsock = socketpair()
        loop = asyncio.get_event_loop()

        _args = {
            constants.ARG_CIPHER_METHOD: encrypt.AES_256_CFB,
            constants.ARG_PASSWORD: '******'
        }
        config = Namespace(**_args)

        # Register the socket to wait for data
        connect_coro = loop.create_connection(
            lambda: ShadowsocksProxyServerProtocol(loop, config), sock=lsock)
        transport, protocol = loop.run_until_complete(connect_coro)

        cipher_method = encrypt.AES_256_CFB
        password = '******'

        encoder = encoder = ShadowsocksEncryptionWrapperEncoder(
            encrypt_method=cipher_method, password=password, encript_mode=True)

        decoder = ShadowsocksEncryptionWrapperEncoder(
            encrypt_method=cipher_method,
            password=password,
            encript_mode=False)

        packer = StreamPacker()

        protocol.loop = loop
        header = ShadowsocksPacketHeader(
            addr='example.com',
            port=80,
            addr_type=constants.SOCKS5_ADDRTYPE_HOST)
        http_request_content = b'GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.43.0\r\nAccept: */*\r\n\r\n'

        # Simulate the reception of data from the network
        encoded_data = packer.pack(header=header, data=http_request_content)
        encoded_data = encoder.encode(encoded_data)
        loop.call_soon(rsock.send, encoded_data)

        def reader():
            data = rsock.recv(100)
            if not data or len(data) == 0:
                return

            data = decoder.decode(data)
            _, http_response_content = packer.unpack(data, header=None)
            self.assertEqual(http_response_content[:4], b'HTTP')
            # We are done: unregister the file descriptor
            loop.remove_reader(rsock)
            lsock.close()
            rsock.close()
            # Stop the event loop
            loop.stop()

        # Register the file descriptor for read event
        loop.add_reader(rsock, reader)
        # Run the event loop
        loop.run_forever()
예제 #4
0
    def test_client(self):
        # Create a pair of connected sockets
        lsock, rsock = socketpair()
        loop = asyncio.get_event_loop()

        _args = {
            constants.ARG_CIPHER_METHOD: encrypt.AES_256_CFB,
            constants.ARG_PASSWORD: '******'
        }
        config = Namespace(**_args)

        # Register the socket to wait for data
        connect_coro = loop.create_connection(
            lambda: ShadowsocksProxyServerProtocol(loop, config), sock=rsock)
        _, server_protocol = loop.run_until_complete(connect_coro)

        def data_callback(client, data):
            self.assertEqual(data[:4], b'HTTP')
            lsock.close()
            rsock.close()
            # Stop the event loop
            loop.stop()

        def conn_lost_callback(*args):
            pass

        connect_coro = loop.create_connection(
            lambda: ShadowsocksClientRelayProtocol(data_callback,
                                                   conn_lost_callback, config),
            sock=lsock)

        _, client_protocol = loop.run_until_complete(connect_coro)

        header = ShadowsocksPacketHeader(
            addr='example.com',
            port=80,
            addr_type=constants.SOCKS5_ADDRTYPE_HOST)
        http_request_content = b'GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.43.0\r\nAccept: */*\r\n\r\n'

        client_protocol.send_data(header.to_bytes() + http_request_content)

        # Simulate the reception of data from the network
        # loop.call_soon(rsock.send, encoded_data)
        # Run the event loop

        loop.run_forever()
예제 #5
0
    def data_received(self, data):
        if self.decoder:
            data = self.decoder.decode(data)

        if not self.relay_target_addr:
            try:
                self.relay_target_addr, data = self.stream_packer.unpack(
                    data, header=ShadowsocksPacketHeader())
            except AttributeError:
                settings.PROTO_LOG.error(
                    'parsing header error from %s:%d',
                    *self.transport.get_extra_info('peername'))
                self.transport.close()
            else:
                if not self.relay_target_addr:
                    # need more data to be a header
                    return

        else:
            _, data = self.stream_packer.unpack(data)
            if not data:
                return

        if self.relay_state == constants.RELAY_STATE_CONECTED:
            # TODO: inspect the relay client' connection status, try to reconnect if disconn
            asyncio.ensure_future(self.send_data_to_remote(self.client, data),
                                  loop=self.loop)

        elif self.relay_state == constants.RELAY_STATE_CONNECTING:
            settings.PROTO_LOG.error(
                'unexpected state: receive data before connection completes')

        elif self.relay_state == constants.RELAY_STATE_NOT_CONNECTED:

            f = asyncio.ensure_future(self.set_up_relay(
                self.relay_target_addr.addr, self.relay_target_addr.port),
                                      loop=self.loop)
            self.relay_state = constants.RELAY_STATE_CONNECTING

            def send_data(future):
                succed = future.result()
                if succed:
                    self.relay_state = constants.RELAY_STATE_CONECTED
                    asyncio.ensure_future(self.send_data_to_remote(
                        self.client, data),
                                          loop=self.loop)
                else:
                    self.relay_state = constants.RELAY_STATE_NOT_CONNECTED
                    settings.PROTO_LOG.warning(
                        'can not create relay connection to %s:%d',
                        self.relay_target_addr.addr,
                        self.relay_target_addr.port)
                    self.transport.close()

            f.add_done_callback(send_data)
예제 #6
0
    def test_client(self):
        # Create a pair of connected sockets
        lsock, rsock = socketpair()
        loop = asyncio.get_event_loop()

        _args = {constants.ARG_CIPHER_METHOD: encrypt.AES_256_CFB, constants.ARG_PASSWORD: '******'}
        config = Namespace(**_args)

        # Register the socket to wait for data
        connect_coro = loop.create_connection(lambda: ShadowsocksProxyServerProtocol(loop, config), sock=rsock)
        _, server_protocol = loop.run_until_complete(connect_coro)

        def data_callback(client, data):
            self.assertEqual(data[:4], b'HTTP')
            lsock.close()
            rsock.close()
            # Stop the event loop
            loop.stop()

        def conn_lost_callback(*args):
            pass

        connect_coro = loop.create_connection(
            lambda: ShadowsocksClientRelayProtocol(data_callback, conn_lost_callback, config), sock=lsock)

        _, client_protocol = loop.run_until_complete(connect_coro)

        header = ShadowsocksPacketHeader(addr='example.com', port=80, addr_type=constants.SOCKS5_ADDRTYPE_HOST)
        http_request_content = b'GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: curl/7.43.0\r\nAccept: */*\r\n\r\n'

        client_protocol.send_data(header.to_bytes() + http_request_content)

        # Simulate the reception of data from the network
        # loop.call_soon(rsock.send, encoded_data)
        # Run the event loop

        loop.run_forever()
예제 #7
0
    def test_fields(self):
        header = ShadowsocksPacketHeader()
        header.port = 999
        header.addr_type = 1
        header.addr = '192.168.18.1'

        self.assertEqual(header.port, 999)
        self.assertEqual(header.addr_type, 1)
        self.assertEqual(header.addr, '192.168.18.1')

        # specified fields that do not assigned will return None instead of rasing KeyError
        self.assertIsNone(header.sha1_hmac)

        with self.assertRaises(KeyError):
            header.not_exist = 9
예제 #8
0
    def test_to_bytes_and_from_bytes(self):
        header1 = ShadowsocksPacketHeader(
            port=80,
            addr_type=constants.SOCKS5_ADDRTYPE_HOST,
            addr='www.google.com')
        bytes1 = b'\x03\x0ewww.google.com\x00\x50'
        self.assertEqual(header1.to_bytes(), bytes1)
        header1_new = ShadowsocksPacketHeader()
        header1_new.from_bytes(bytes1)
        self.assertEqual(header1_new, header1)

        header2 = ShadowsocksPacketHeader(
            port=53, addr_type=constants.SOCKS5_ADDRTYPE_IPV4, addr='8.8.8.8')
        bytes2 = b'\x01\x08\x08\x08\x08\x00\x35'
        self.assertEqual(header2.to_bytes(), bytes2)
        header2_new = ShadowsocksPacketHeader()
        header2_new.from_bytes(bytes2)
        self.assertEqual(header2_new, header2)

        header3 = ShadowsocksPacketHeader(
            port=80,
            addr_type=constants.SOCKS5_ADDRTYPE_IPV6,
            addr='2404:6800:4005:805::1011')
        bytes3 = b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00\x00\x10\x11\x00\x50'
        self.assertEqual(header3.to_bytes(), bytes3)
        header3_new = ShadowsocksPacketHeader()
        header3_new.from_bytes(bytes3)
        self.assertEqual(header3_new, header3)
예제 #9
0
    def test_to_bytes_and_from_bytes(self):
        header1 = ShadowsocksPacketHeader(port=80, addr_type=constants.SOCKS5_ADDRTYPE_HOST, addr='www.google.com')
        bytes1 = b'\x03\x0ewww.google.com\x00\x50'
        self.assertEqual(header1.to_bytes(), bytes1)
        header1_new = ShadowsocksPacketHeader()
        header1_new.from_bytes(bytes1)
        self.assertEqual(header1_new, header1)

        header2 = ShadowsocksPacketHeader(port=53, addr_type=constants.SOCKS5_ADDRTYPE_IPV4, addr='8.8.8.8')
        bytes2 = b'\x01\x08\x08\x08\x08\x00\x35'
        self.assertEqual(header2.to_bytes(), bytes2)
        header2_new = ShadowsocksPacketHeader()
        header2_new.from_bytes(bytes2)
        self.assertEqual(header2_new, header2)

        header3 = ShadowsocksPacketHeader(port=80, addr_type=constants.SOCKS5_ADDRTYPE_IPV6,
                                          addr='2404:6800:4005:805::1011')
        bytes3 = b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00\x00\x10\x11\x00\x50'
        self.assertEqual(header3.to_bytes(), bytes3)
        header3_new = ShadowsocksPacketHeader()
        header3_new.from_bytes(bytes3)
        self.assertEqual(header3_new, header3)