示例#1
0
def run():
    '''Run Ironhouse example'''

    # These direcotries are generated by the generate_certificates script
    base_dir = os.path.dirname(__file__)
    keys_dir = os.path.join(base_dir, 'certificates')
    public_keys_dir = os.path.join(base_dir, 'public_keys')
    secret_keys_dir = os.path.join(base_dir, 'private_keys')

    if not (os.path.exists(keys_dir) and os.path.exists(public_keys_dir)
            and os.path.exists(secret_keys_dir)):
        logging.critical(
            "Certificates are missing - run generate_certificates script first"
        )
        sys.exit(1)

    # Start an authenticator for this context.
    auth = IOLoopAuthenticator()
    auth.allow('127.0.0.1')
    # Tell authenticator to use the certificate in a directory
    auth.configure_curve(domain='*', location=public_keys_dir)

    server_secret_file = os.path.join(secret_keys_dir, "server.key_secret")
    server = setup_server(server_secret_file)
    server_public_file = os.path.join(public_keys_dir, "server.key")
    client_secret_file = os.path.join(secret_keys_dir, "client.key_secret")
    client = setup_client(client_secret_file, server_public_file)
    client.send(b'Hello')

    auth.start()
    ioloop.IOLoop.instance().start()
示例#2
0
	def __init__(self, app=None, keyname="server", bind_addr="tcp://127.0.0.1:5556", crypto=True, zap_auth=True):

		self.app = app
		self.keyname = keyname
		self.bind_addr = bind_addr
		self.crypto = crypto
		self.zap_auth = zap_auth

		self.ctx = zmq.Context()
		self.loop = IOLoop.instance()
		self.identities = {}

		self.server = self.ctx.socket(zmq.ROUTER)

		if self.crypto:
			self.keymonkey = KeyMonkey(self.keyname)
			self.server = self.keymonkey.setupServer(self.server, self.bind_addr)

		self.server.bind(self.bind_addr)
		logging.debug("%s listening for new client connections at %s" % ( self.keyname, self.bind_addr))
		self.server = ZMQStream(self.server)
		# Setup ZAP:
		if self.zap_auth:
			if not self.crypto:
				logging.fatal("ZAP requires CurveZMQ (crypto) to be enabled. Exiting.")
				sys.exit(1)
			self.auth = IOLoopAuthenticator(self.ctx)
			logging.info("ZAP enabled. Authorizing clients in %s." % self.keymonkey.authorized_clients_dir)
			if not os.path.isdir(self.keymonkey.authorized_clients_dir):
				logging.fatal("Directory not found: %s. Exiting." % self.keymonkey.authorized_clients_dir)
				sys.exit(1)
			self.auth.configure_curve(domain='*', location=self.keymonkey.authorized_clients_dir)
		self.setup()
		self.start()
示例#3
0
    def stream(self,
               sock_type,
               address: str,
               callback: Callable = None,
               use_encryption: bool = False,
               server_curve_id: str = None,
               curve_dir: str = None,
               use_zap: bool = False):
        """

        Method used to setup a ZMQ stream which will be bound to a ZMQ.REP socket.
        On this REP stream we register a callback to execute client queries as they arrive.
        The stream is used in conjunction with `tornado` eventloop

        Args:
            sock_type: ZMQ Socket type. For e.g. zmq.REP
            address: Address to bind to
            callback: A callback to invoke as messages arrive on the ZMQ stream
            use_encryption: True if you want CurveZMQ encryption to be enabled
            server_curve_id: Server curve id. Defaults to "id_server_{}_curve".format(socket.gethostname())
            curve_dir: Curve key files directory. Defaults to `~/.curve`
            use_zap: True if you want ZAP authentication to be enabled.

        Raises:
            sqlite_rx.exception.SQLiteRxZAPSetupError: If ZAP is enabled without CurveZMQ
        """

        self.socket = self.context.socket(sock_type)

        if use_encryption or use_zap:

            server_curve_id = server_curve_id if server_curve_id else "id_server_{}_curve".format(
                socket.gethostname())
            keymonkey = KeyMonkey(key_id=server_curve_id,
                                  destination_dir=curve_dir)

            if use_encryption:
                LOG.info("Setting up encryption using CurveCP")
                self.socket = keymonkey.setup_secure_server(
                    self.socket, address)

            if use_zap:
                if not use_encryption:
                    raise SQLiteRxZAPSetupError(
                        "ZAP requires CurveZMQ(use_encryption = True) to be enabled. Exiting"
                    )

                self.auth = IOLoopAuthenticator(self.context)
                LOG.info("ZAP enabled. \n Authorizing clients in %s.",
                         keymonkey.authorized_clients_dir)
                self.auth.configure_curve(
                    domain="*", location=keymonkey.authorized_clients_dir)
                self.auth.start()

        self.socket.bind(address)

        stream = zmqstream.ZMQStream(self.socket, self.loop)
        if callback:
            stream.on_recv(callback)
        return stream
示例#4
0
    def run(self):
        if self._server:
            log.warning('Tried to run an already running server again.')
            return

        if not os.path.isfile(self._server_private_key):
            log.critical(
                'No private key is installed for Lighthouse. Can not create an encrypted connection.'
            )
            sys.exit(2)

        if not os.path.isdir(self._trusted_keys_dir):
            log.warning(
                'Trusted keys directory does not exist. No clients will be able to make connections to this Lighthouse server.'
            )

        # Start an authenticator for this context.
        auth = IOLoopAuthenticator(self._ctx)
        # NOTE: auth.allow('127.0.0.1') can be used to allow access only from specific IPs (whitelisting)

        # Tell authenticator to use the certificate in a directory
        auth.configure_curve(domain='*', location=self._trusted_keys_dir)

        self._setup_server()

        auth.start()
        ioloop.IOLoop.instance().start()
示例#5
0
    def __authenticate(self):
        if not os.path.exists(self.config.get_server_public_key_file()):
            self.logger.fatal('server public key missing: %s' % self.config.get_server_public_key_file())
            exit(1)
        if not os.path.exists(self.config.get_client_secret_key_file()):
            self.fatal('client secret key missing: %s' % self.config.get_client_secret_key_file())
            exit(1)
        auth = IOLoopAuthenticator()

        # Tell authenticator to use the certificate in a directory
        auth.configure_curve(domain='*', location=self.config.get_default_keys_dir())
示例#6
0
    def _setup_auth(self, auth_whitelist: list, loop):
        if loop is None:
            self.auth = ThreadAuthenticator(self.context)
        else:
            self.auth = IOLoopAuthenticator(self.context, io_loop=loop)

        # allow all local host
        self.logger.debug('Auth whitelist %s', auth_whitelist)
        if auth_whitelist is not None:
            self.auth.allow(auth_whitelist)
        self._base_filepath = get_certificate_filepath()
        public_key_location = path.join(self._base_filepath, 'public_keys')
        self.auth.configure_curve(domain='*', location=public_key_location)
        self.auth.start()
示例#7
0
    def __authenticate(self):
        public_keys_dir = self.config.get_public_keys_dir()
        private_keys_dir = self.config.get_private_keys_dir()

        if not (os.path.exists(public_keys_dir)
                and os.path.exists(private_keys_dir)):
            msg = ("Certificates are missing: %s and %s - "
                   "run generate_certificates script first" %
                   (public_keys_dir, private_keys_dir))
            self.config.get_logger(__name__).critical(msg)
            raise Exception(msg)

        auth = IOLoopAuthenticator()
        auth.configure_curve(domain='*', location=public_keys_dir)

        return os.path.join(private_keys_dir, "server.key_secret")
示例#8
0
    def start(self):

        # Setup ZAP:
        if self.zap_auth:
            if not self.crypto:
                print("ZAP requires CurveZMQ (crypto) to be enabled. Exiting.")
                sys.exit(1)
            self.auth = IOLoopAuthenticator(self.ctx)
            self.auth.deny(None)
            print("ZAP enabled.\nAuthorizing clients in %s." %
                  self.keymonkey.authorized_clients_dir)
            self.auth.configure_curve(
                domain='*', location=self.keymonkey.authorized_clients_dir)
            self.auth.start()

        self.periodic.start()
        try:
            self.loop.start()
        except KeyboardInterrupt:
            pass
示例#9
0
 def make_auth(self):
     from zmq.auth.ioloop import IOLoopAuthenticator
     return IOLoopAuthenticator(self.context, io_loop=self.io_loop)
示例#10
0
 def make_auth(self):
     return IOLoopAuthenticator(self.context, io_loop=self.io_loop)
示例#11
0
    (r"/add/([^/]+)", FunctionHandler),
    (r"/commands", CommandsHandler),
    (r"/iptables", IptablesHandler),
    (r"/key", KeyHandler),
])

#start unsecure zmq server

base_dir = os.path.dirname(__file__)
public_keys_dir = os.path.join(base_dir, 'public_keys')
secret_keys_dir = os.path.join(base_dir, 'private_keys')

# Start an authenticator for this context.
ctx_server_unsec = zmq.Context()
server_unsec = ctx_server_unsec.socket(zmq.REP)
auth_unsec = IOLoopAuthenticator()
auth_unsec.configure_curve(domain='*', location='*')
server_secret_file = os.path.join(secret_keys_dir, "server.key_secret")
server_unsec = setup_server_unsec(server_unsec, server_secret_file)
server_public_file = os.path.join(public_keys_dir, "server.key")
auth_unsec.start()

### Start

if __name__ == "__main__":

    application.listen(8888)
    io_loop = ioloop.IOLoop.instance()
    conn = sqlite3.connect('clients.db')
    c = conn.cursor()
    sql = 'create table if not exists' \
示例#12
0
    def message_proxy(self, work_dir):
        """
        drone_data_inboud   is for data comming from drones
        drone_data_outbound is for commands to the drones, topic must either be a drone ID or all for sending
                            a broadcast message to all drones
        """
        public_keys_dir = os.path.join(work_dir, 'certificates', 'public_keys')
        secret_keys_dir = os.path.join(work_dir, 'certificates',
                                       'private_keys')

        # start and configure auth worker
        auth = IOLoopAuthenticator()
        auth.start()
        auth.allow('127.0.0.1')
        auth.configure_curve(domain='*', location=public_keys_dir)

        # external interfaces for communicating with drones
        server_secret_file = os.path.join(secret_keys_dir,
                                          'beeswarm_server.pri')
        server_public, server_secret = load_certificate(server_secret_file)
        drone_data_inbound = beeswarm.shared.zmq_context.socket(zmq.PULL)
        drone_data_inbound.curve_secretkey = server_secret
        drone_data_inbound.curve_publickey = server_public
        drone_data_inbound.curve_server = True
        drone_data_inbound.bind('tcp://*:{0}'.format(
            self.config['network']['zmq_port']))

        drone_data_outbound = beeswarm.shared.zmq_context.socket(zmq.PUB)
        drone_data_outbound.curve_secretkey = server_secret
        drone_data_outbound.curve_publickey = server_public
        drone_data_outbound.curve_server = True
        drone_data_outbound.bind('tcp://*:{0}'.format(
            self.config['network']['zmq_command_port']))

        # internal interfaces
        # all inbound session data from drones will be replayed on this socket
        drone_data_socket = beeswarm.shared.zmq_context.socket(zmq.PUB)
        drone_data_socket.bind(SocketNames.DRONE_DATA.value)

        # all commands received on this will be published on the external interface
        drone_command_socket = beeswarm.shared.zmq_context.socket(zmq.PULL)
        drone_command_socket.bind(SocketNames.DRONE_COMMANDS.value)

        poller = zmq.Poller()
        poller.register(drone_data_inbound, zmq.POLLIN)
        poller.register(drone_command_socket, zmq.POLLIN)
        while True:
            # .recv() gives no context switch - why not? using poller with timeout instead
            socks = dict(poller.poll(100))
            gevent.sleep()

            if drone_command_socket in socks and socks[
                    drone_command_socket] == zmq.POLLIN:
                data = drone_command_socket.recv()
                drone_id, _ = data.split(' ', 1)
                logger.debug("Sending drone command to: {0}".format(drone_id))
                # pub socket takes care of filtering
                drone_data_outbound.send(data)
            elif drone_data_inbound in socks and socks[
                    drone_data_inbound] == zmq.POLLIN:
                raw_msg = drone_data_inbound.recv()
                split_data = raw_msg.split(' ', 2)
                if len(split_data) == 3:
                    topic, drone_id, data = split_data
                else:
                    data = None
                    topic, drone_id, = split_data
                logger.debug("Received {0} message from {1}.".format(
                    topic, drone_id))
                # relay message on internal socket
                drone_data_socket.send(raw_msg)
示例#13
0
    def message_proxy(self, work_dir):
        """
        drone_data_inboud   is for data comming from drones
        drone_data_outbound is for commands to the drones, topic must either be a drone ID or all for sending
                            a broadcast message to all drones
        """
        public_keys_dir = os.path.join(work_dir, 'certificates', 'public_keys')
        secret_keys_dir = os.path.join(work_dir, 'certificates',
                                       'private_keys')

        # start and configure auth worker
        auth = IOLoopAuthenticator()
        auth.start()
        auth.allow('127.0.0.1')
        auth.configure_curve(domain='*', location=public_keys_dir)

        # external interfaces for communicating with drones
        server_secret_file = os.path.join(secret_keys_dir,
                                          'beeswarm_server.pri')
        server_public, server_secret = load_certificate(server_secret_file)
        drone_data_inbound = beeswarm.shared.zmq_context.socket(zmq.PULL)
        drone_data_inbound.curve_secretkey = server_secret
        drone_data_inbound.curve_publickey = server_public
        drone_data_inbound.curve_server = True
        drone_data_inbound.bind('tcp://*:{0}'.format(
            self.config['network']['zmq_port']))

        drone_data_outbound = beeswarm.shared.zmq_context.socket(zmq.PUB)
        drone_data_outbound.curve_secretkey = server_secret
        drone_data_outbound.curve_publickey = server_public
        drone_data_outbound.curve_server = True
        drone_data_outbound.bind('tcp://*:{0}'.format(
            self.config['network']['zmq_command_port']))

        # internal interfaces
        # all inbound session data from drones will be replayed in this socket
        sessionPublisher = beeswarm.shared.zmq_context.socket(zmq.PUB)
        sessionPublisher.bind('inproc://sessionPublisher')

        # all commands received on this will be published on the external interface
        drone_command_receiver = beeswarm.shared.zmq_context.socket(zmq.PULL)
        drone_command_receiver.bind('inproc://droneCommandReceiver')

        poller = zmq.Poller()
        poller.register(drone_data_inbound, zmq.POLLIN)
        poller.register(drone_command_receiver, zmq.POLLIN)
        while True:
            # .recv() gives no context switch - why not? using poller with timeout instead
            socks = dict(poller.poll(100))
            gevent.sleep()

            if drone_command_receiver in socks and socks[
                    drone_command_receiver] == zmq.POLLIN:
                data = drone_command_receiver.recv()
                drone_id, _ = data.split(' ', 1)
                logger.debug("Sending drone command to: {0}".format(drone_id))
                # pub socket takes care of filtering
                drone_data_outbound.send(data)
            elif drone_data_inbound in socks and socks[
                    drone_data_inbound] == zmq.POLLIN:
                split_data = drone_data_inbound.recv().split(' ', 2)
                if len(split_data) == 3:
                    topic, drone_id, data = split_data
                else:
                    data = None
                    topic, drone_id, = split_data
                logger.debug("Received {0} message from {1}.".format(
                    topic, drone_id))
                db_session = database_setup.get_session()
                drone = db_session.query(Drone).filter(
                    Drone.id == drone_id).one()
                drone.last_activity = datetime.now()
                db_session.add(drone)
                db_session.commit()

                if topic == Messages.SESSION_HONEYPOT or topic == Messages.SESSION_CLIENT:
                    sessionPublisher.send('{0} {1}'.format(topic, data))
                elif topic == Messages.KEY or topic == Messages.CERT:
                    # for now we just store the fingerprint
                    # in the future it might be relevant to store the entire public key and private key
                    # for forensic purposes
                    if topic == Messages.CERT:
                        cert = data.split(' ', 1)[1]
                        digest = generate_cert_digest(cert)
                        logging.debug(
                            'Storing public key digest: {0} for drone {1}.'.
                            format(digest, drone_id))
                        db_session = database_setup.get_session()
                        drone = db_session.query(Drone).filter(
                            Drone.id == drone_id).one()
                        drone.cert_digest = digest
                        db_session.add(drone)
                        db_session.commit()
                elif topic == Messages.PING:
                    pass
                elif topic == Messages.IP:
                    ip_address = data
                    logging.debug('Drone {0} reported ip: {1}'.format(
                        drone_id, ip_address))
                    db_session = database_setup.get_session()
                    drone = db_session.query(Drone).filter(
                        Drone.id == drone_id).one()
                    if drone.ip_address != ip_address:
                        drone.ip_address = ip_address
                        db_session.add(drone)
                        db_session.commit()
                        send_zmq_request(
                            'inproc://configCommands',
                            '{0} {1}'.format(Messages.DRONE_CONFIG_CHANGED,
                                             drone_id))
                # drone want it's config transmitted
                elif topic == Messages.DRONE_CONFIG:
                    config_dict = send_zmq_request(
                        'inproc://configCommands',
                        '{0} {1}'.format(Messages.DRONE_CONFIG, drone_id))
                    drone_data_outbound.send('{0} {1} {2}'.format(
                        drone_id, Messages.CONFIG, json.dumps(config_dict)))
                else:
                    logger.warn(
                        'Message with unknown topic received: {0}'.format(
                            topic))