def remove_links(path: str): bf_init_snapshot(path, 'remove_links') results = bfq.reachability(pathConstraints=PathConstraints(startLocation="/host[0-9]+/"))\ .answer(snapshot='remove_links').frame() removable_interfaces = set() for idx, result in results.iterrows(): if result.TraceCount <= 1: continue visited_interfaces = {} for trace in result.Traces: if trace.disposition == "NO_ROUTE": continue for hop in trace.hops: node = hop.node if "host" in node: continue for step in hop.steps: interface = None if hasattr(step.detail, "inputInterface"): interface = step.detail.inputInterface elif hasattr(step.detail, "outputInterface"): interface = step.detail.outputInterface if interface is not None: iname = f"{node}:{interface}" if iname not in visited_interfaces: visited_interfaces[iname] = 0 visited_interfaces[iname] += 1 interfaces = list(filter(lambda it: it[1] > 1, visited_interfaces.items())) if len(interfaces) > 0: removable_interfaces.add(interfaces[0][0]) print(removable_interfaces) remove_interface_in_config(path, list(removable_interfaces))
def get_reachable_interfaces(snapshot: str, switches: Set[str]) -> Set[str]: # bf_init_snapshot(str(snapshot), "reachable", overwrite=True) nodes = [] results = bfq.nodeProperties().answer().frame() for _, result in results.iterrows(): nodes.append(result.Node) reachable = set() for switch in switches: for node in nodes: results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() for _, result in results.iterrows(): for trace in result.Traces: for hop in trace.hops: for step in hop.steps: if hasattr(step.detail, "outputInterface"): reachable.add( f"{hop.node}:{step.detail.outputInterface}" ) if hasattr(step.detail, "inputInterface"): reachable.add( f"{hop.node}:{step.detail.inputInterface}") return reachable
def eval(self, ori_snapshot: str, new_snapshot: str) -> bool: answer = bfq.reachability(headers=HeaderConstraints(dstIps=self.dst), pathConstraints=PathConstraints(startLocation=self.src)) \ .answer(snapshot=new_snapshot) if hasattr(answer, "frame"): return answer.frame().size > 0 else: return False
def get_affected_node(self, node: str, snapshot: str, generator: Callable[[List[str]], List[str]]) -> Set[str]: affected_node = set() self.name_idx += 1 results = bfq.differentialReachability(pathConstraints=PathConstraints(startLocation="/(host[0-9]+|pc[0-9]+)/")) \ .answer(snapshot=snapshot, reference_snapshot="exp").frame() for idx, result in results.iterrows(): if result.Flow.ingressNode is not None and result.Flow.ingressNode != node: affected_node.add(result.Flow.ingressNode) return set(generator(list(affected_node)))
def check_traffic(self, snapshot: str, reference_snapshot: str): # bf_set_snapshot(name) load_questions() header = HeaderConstraints(srcIps="0.0.0.0/0", dstIps="0.0.0.0/0", ipProtocols=["tcp"]) path = PathConstraints(startLocation="/as2/", endLocation="/as3/") # result = bfq.differentialReachability(headers=header) \ # .answer(snapshot=snapshot, reference_snapshot=reference_snapshot).frame() result = bfq.reachability(headers=header, pathConstraints=path) \ .answer(snapshot=reference_snapshot).frame() result.to_csv('out.csv')
def get_reachable_nodes(snapshot: str, config_path: str, switches: Set[str]) -> Set[str]: nodes = nodes_from_snapshot(config_path) reachable = set() switch_constraint = f"/{'|'.join(switches)}/" for node in nodes: if node in switches: reachable.add(node) continue results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch_constraint, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() if results.size > 0: reachable.add(node) return reachable
def compute_issue_reachable_nodes(s1: str, s2: str): bf_init_snapshot(s1, "s1", overwrite=True) bf_init_snapshot(s2, "s2", overwrite=True) # results = bfq.differentialReachability(pathConstraints=PathConstraints(startLocation="/(host[0-9]+|pc[0-9]+)/")) \ # .answer(snapshot="s1", reference_snapshot="s2").frame() results = bfq.differentialReachability(pathConstraints=PathConstraints(startLocation="/(host[0-9]+|pc[0-9]+)/")) \ .answer(snapshot="s1", reference_snapshot="s2").frame() affected_node = set() for idx, result in results.iterrows(): if result.Flow.ingressNode: affected_node.add(result.Flow.ingressNode) nodes = nodes_from_snapshot(s1) out = open(os.path.join(s2, "reach.json"), "w") reachable = get_reachable_nodes("s2", affected_node).union(affected_node) print(reachable) print(nodes.difference(reachable)) json.dump({ "reachable": list(reachable), "protected": list(nodes.difference(reachable)) }, out, indent=2) reset()
def get_reachable_nodes_intersect(snapshot: str, switches: Set[str]) -> Set[str]: nodes = [] results = bfq.nodeProperties().answer().frame() for _, result in results.iterrows(): nodes.append(result.Node) reachable = {} for switch in switches: for node in nodes: results = bfq.reachability( pathConstraints=PathConstraints(startLocation=switch, endLocation=node)) \ .answer(snapshot=snapshot) results = results.frame() if results.size > 0: if node not in reachable: reachable[node] = 0 reachable[node] += 1 return set( map( lambda it: it[0], filter(lambda elem: elem[1] >= len(switches) // 3, reachable.items())))
def build(self) -> PathConstraints: return PathConstraints(**self.__dict__)
def eval(self, ori_snapshot: str, new_snapshot: str) -> bool: result = bfq.reachability(headers=HeaderConstraints(dstIps=self.dst), pathConstraints=PathConstraints(transitLocations=self.waypoint, startLocation=self.src)) \ .answer(snapshot=new_snapshot).frame() return result.size > 0
def __init__(self): self.header = HeaderConstraints(dstIps="host1", dstPorts="22") self.path = PathConstraints(startLocation="/as3/")