예제 #1
0
    def run(self):
        if self.action == 'set':
            addr = Address.deserialize(
                re.search(r'Connection:(?P<addr>\S+):alive',
                          self.channel).group('addr'))
            connection = DB.Connection(addr)
            logging.debug(
                "ClusterWorker responding to 'set' on connection '%s' alive status",
                addr)

            user = connection.user
            vpn = connection.vpn
            cluster = DB.Cluster(user, vpn.chal)

            if connection.alive:
                if user.status == 'active':
                    self.ensure_cluster_up(user, vpn, cluster, connection)
                else:
                    raise ValueError("Invalid state {} for user {}".format(
                        user.status, user.id))

            else:
                if user.status == 'active':
                    logging.info("Removed connection %s for active user %s",
                                 connection.id, user.id)

                if user.status == 'disconnected':
                    self.ensure_cluster_stopped(user, vpn, cluster)

                connection.delete()
        else:
            logging.debug("ClusterWorker not responding to '%s' event",
                          self.action)
예제 #2
0
def register_vpn():
    env = get_env()

    chal = DB.Challenge(env['NAUM_CHAL'])
    if len(chal.files) == 0:
        chal.files.extend(env['NAUM_FILES'])

    vpn = DB.Vpn(env['HOSTNAME'])

    vpn.update(veth=env['NAUM_VETHHOST'], veth_state='down', chal=chal)

    DB.vpns.add(vpn)
예제 #3
0
    def run(self):
        if self.action == 'set':
            addr = Address.deserialize(
                re.search(r'Connection:(?P<addr>\S+):alive',
                          self.channel).group('addr'))
            logging.debug(
                "VlanWorker responding to 'set' on connection '%s' alive status",
                addr)
            connection = DB.Connection(addr)

            # If this connection is not alive, this worker reacted to the connection being killed
            if connection.alive:
                user = connection.user
                vpn = connection.vpn

                ensure_veth_up(vpn)

                vlan_if = vlan_if_name(vpn.veth, user.vlan)

                link_status = vpn.links[user.vlan]
                if link_status == 'bridged':
                    logging.info(
                        "New connection %s traversing existing vlan link %s",
                        connection.id, vlan_if)

                else:
                    if not link_status or link_status == 'down':
                        self.bring_up_link(vpn, user)

                    self.bridge_cluster(vpn, user)

        else:
            logging.debug("VlanWorker not responding to '%s' event",
                          self.action)
예제 #4
0
def client_disconnect():
    env = get_env()
    client = '{TRUSTED_IP}:{TRUSTED_PORT}'.format(**env)

    connection = DB.Connection(Address(env['TRUSTED_IP'], env['TRUSTED_PORT']))
    try:
        connection.user.connections.remove(connection)  # That's a mouthful
        if len(connection.user.connections) == 0:
            connection.user.status = 'disconnected'
        connection.alive = False
    except RedisKeyError:
        logging.warn(
            "Connection {} removed from Redis prior to disconnect".format(
                client))
예제 #5
0
def client_connect(ccname):
    env = get_env()

    vpn = DB.Vpn(env['HOSTNAME'])
    if not vpn in DB.vpns:
        register_vpn()

    user = DB.users[env['COMMON_NAME']]
    if user:
        user.status = 'active'

    else:
        user = create_user(vpn, env)

    addr = Address(env['TRUSTED_IP'], env['TRUSTED_PORT'])
    connection = DB.Connection(addr)
    connection.update(addr=addr, vpn=vpn, user=user, alive=True)
    user.connections.add(connection)

    logging.info("New connection from {cn}@{ip}:{port} on vlan {vlan}".format(
        cn=env['COMMON_NAME'], vlan=user.vlan, ip=addr.ip, port=addr.port))

    with open(args.ccname, 'w') as ccfile:
        ccfile.write(CCTEMPLATE.format(vlan=user.vlan))
예제 #6
0
    def bridge_cluster(self, vpn, user):
        cluster = DB.Cluster(user, vpn.chal)
        vlan_if = vlan_if_name(vpn.veth, user.vlan)

        if cluster.exists() and cluster.status == 'up':
            bridge_id = get_bridge_id(cluster.id)
            BrctlCmd(BrctlCmd.ADDIF, bridge_id, vlan_if).run()
            vpn.links[user.vlan] = 'bridged'
            logging.info("Added %s to bridge %s for cluster %s", vlan_if,
                         bridge_id, cluster.id)

        else:
            logging.info(
                "Cluster %s not up. Defering addition of %s to a bridge",
                cluster.id, vlan_if)
예제 #7
0
def create_user(vpn, env):
    existing_vlans = vpn.links.keys()
    vlan = None
    while not vlan:
        vlan = random.randint(10, 4000)
        if vlan in existing_vlans:
            vlan = None

    # Common name must be formatted as if it were a dns name
    user_id = env['COMMON_NAME'].lower()
    user = DB.User(user_id)
    user.update(vlan=vlan, cn=env['COMMON_NAME'], status='active')

    DB.users[env['COMMON_NAME']] = user
    logging.info("Welcome to new user {}".format(env['COMMON_NAME']))

    return user
예제 #8
0
def create_user(vpn, env):
    existing_vlans = vpn.links.keys()
    vlan = None
    while not vlan:
        vlan = random.randint(10, 4000)
        if vlan in existing_vlans:
            vlan = None

    # This is currently implemented as a security measure; Never want user data possibly injected into control info
    # e.g. what if a user called themselves "Vpn:xxxxxxxxxxxx", taht could trigger I listener
    # .... well actually it wouldn't, and I can't think of any dangerous examples, so maybe I'll ditch this for readability
    user_id = base64.b32encode(
        env['COMMON_NAME'].encode('utf-8')).decode('utf-8').lower().strip('=')
    user = DB.User(user_id)
    user.update(vlan=vlan, cn=env['COMMON_NAME'], status='active')

    DB.users[env['COMMON_NAME']] = user
    logging.info("Welcome to new user {}".format(env['COMMON_NAME']))

    return user
예제 #9
0
 def run(self):
     if self.action == 'set':
         vpn = DB.Vpn(
             re.search(r'Vpn:(?P<id>\S+):veth', self.channel).group('id'))
         ensure_veth_up(vpn, True)