def verify_capture(self, dst_ip_if, src_ip_if, capture, reverse): last_info = dict() for i in self.interfaces: last_info[i.sw_if_index] = None dst_ip_sw_if_index = dst_ip_if.sw_if_index for packet in capture: l3 = IP if packet.haslayer(IP) else IPv6 ip = packet[l3] if packet.haslayer(UDP): l4 = UDP else: if packet.haslayer(ICMP): l4 = ICMP else: l4 = ICMPv6Unknown # Scapy IPv6 stuff is too smart for its own good. # So we do this and coerce the ICMP into unknown type if packet.haslayer(UDP): data = scapy.compat.raw(packet[UDP][Raw]) else: if l3 == IP: data = scapy.compat.raw(ICMP( scapy.compat.raw(packet[l3].payload))[Raw]) else: data = scapy.compat.raw(ICMPv6Unknown( scapy.compat.raw(packet[l3].payload)).msgbody) udp_or_icmp = packet[l3].payload data_obj = Raw(data) # FIXME: make framework believe we are on object payload_info = self.payload_to_info(data_obj) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_ip_sw_if_index) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_ip_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertTrue(next_info is not None) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data self.assertTrue(next_info is not None) # MAC: src, dst if not reverse: self.assertEqual(packet.src, dst_ip_if.local_mac) host = dst_ip_if.host_by_mac(packet.dst) # IP: src, dst # self.assertEqual(ip.src, src_ip_if.remote_ip4) if saved_packet is not None: self.assertEqual(ip.src, saved_packet[l3].src) self.assertEqual(ip.dst, saved_packet[l3].dst) if l4 == UDP: self.assertEqual(udp_or_icmp.sport, saved_packet[l4].sport) self.assertEqual(udp_or_icmp.dport, saved_packet[l4].dport)
def create_stream(self, src_ip_if, dst_ip_if, reverse, packet_sizes, is_ip6, expect_blocked, expect_established, add_extension_header): pkts = [] rules = [] permit_rules = [] permit_and_reflect_rules = [] total_packet_count = 8 for i in range(0, total_packet_count): modulo = (i // 2) % 2 can_reflect_this_packet = (modulo == 0) is_permit = i % 2 remote_dst_index = i % len(dst_ip_if.remote_hosts) remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index] if is_permit == 1: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) else: to_be_blocked = False if (expect_blocked and not expect_established): to_be_blocked = True if (not can_reflect_this_packet): to_be_blocked = True if to_be_blocked: payload = "to be blocked" else: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) if reverse: dst_mac = 'de:ad:00:00:00:00' src_mac = remote_dst_host._mac dst_ip6 = src_ip_if.remote_ip6 src_ip6 = remote_dst_host.ip6 dst_ip4 = src_ip_if.remote_ip4 src_ip4 = remote_dst_host.ip4 dst_l4 = 1234 + i src_l4 = 4321 + i else: dst_mac = src_ip_if.local_mac src_mac = src_ip_if.remote_mac src_ip6 = src_ip_if.remote_ip6 dst_ip6 = remote_dst_host.ip6 src_ip4 = src_ip_if.remote_ip4 dst_ip4 = remote_dst_host.ip4 src_l4 = 1234 + i dst_l4 = 4321 + i # default ULP should be something we do not use in tests ulp_l4 = TCP(sport=src_l4, dport=dst_l4) # potentially a chain of protocols leading to ULP ulp = ulp_l4 if can_reflect_this_packet: if is_ip6: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) if add_extension_header: # prepend some extension headers ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() / IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4) # uncomment below to test invalid ones # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4 else: ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) # IPv4 does not allow extension headers, # but we rather make it a first fragment flags = 1 if add_extension_header else 0 ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) / ulp / Raw(payload)) elif modulo == 1: if is_ip6: ulp_l4 = ICMPv6Unknown(type=128 + (i % 2), code=i % 2) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = ICMP(type=8 + (i % 2), code=i % 2) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4) / ulp / Raw(payload)) if i % 2 == 1: info.data = p.copy() size = packet_sizes[(i // 2) % len(packet_sizes)] self.extend_packet(p, size) pkts.append(p) rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET rule_prefix_len = 128 if p.haslayer(IPv6) else 32 rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP if p.haslayer(UDP): rule_l4_sport = p[UDP].sport rule_l4_dport = p[UDP].dport else: if p.haslayer(ICMP): rule_l4_sport = p[ICMP].type rule_l4_dport = p[ICMP].code else: rule_l4_sport = p[ICMPv6Unknown].type rule_l4_dport = p[ICMPv6Unknown].code if p.haslayer(IPv6): rule_l4_proto = ulp_l4.overload_fields[IPv6]['nh'] else: rule_l4_proto = p[IP].proto new_rule = { 'is_permit': is_permit, 'is_ipv6': p.haslayer(IPv6), 'src_ip_addr': inet_pton(rule_family, p[rule_l3_layer].src), 'src_ip_prefix_len': rule_prefix_len, 'dst_ip_addr': inet_pton(rule_family, p[rule_l3_layer].dst), 'dst_ip_prefix_len': rule_prefix_len, 'srcport_or_icmptype_first': rule_l4_sport, 'srcport_or_icmptype_last': rule_l4_sport, 'dstport_or_icmpcode_first': rule_l4_dport, 'dstport_or_icmpcode_last': rule_l4_dport, 'proto': rule_l4_proto, } rules.append(new_rule) new_rule_permit = new_rule.copy() new_rule_permit['is_permit'] = 1 permit_rules.append(new_rule_permit) new_rule_permit_and_reflect = new_rule.copy() if can_reflect_this_packet: new_rule_permit_and_reflect['is_permit'] = 2 else: new_rule_permit_and_reflect['is_permit'] = is_permit permit_and_reflect_rules.append(new_rule_permit_and_reflect) return { 'stream': pkts, 'rules': rules, 'permit_rules': permit_rules, 'permit_and_reflect_rules': permit_and_reflect_rules }
def create_stream( self, src_ip_if, dst_ip_if, reverse, packet_sizes, is_ip6, expect_blocked, expect_established, add_extension_header, icmp_stateful=False, ): pkts = [] rules = [] permit_rules = [] permit_and_reflect_rules = [] total_packet_count = 8 for i in range(0, total_packet_count): modulo = (i // 2) % 2 icmp_type_delta = i % 2 icmp_code = i is_udp_packet = modulo == 0 if is_udp_packet and icmp_stateful: continue is_reflectable_icmp = (icmp_stateful and icmp_type_delta == 0 and not is_udp_packet) is_reflected_icmp = is_reflectable_icmp and expect_established can_reflect_this_packet = is_udp_packet or is_reflectable_icmp is_permit = i % 2 remote_dst_index = i % len(dst_ip_if.remote_hosts) remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index] if is_permit == 1: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) else: to_be_blocked = False if expect_blocked and not expect_established: to_be_blocked = True if not can_reflect_this_packet: to_be_blocked = True if to_be_blocked: payload = "to be blocked" else: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) if reverse: dst_mac = "de:ad:00:00:00:00" src_mac = remote_dst_host._mac dst_ip6 = src_ip_if.remote_ip6 src_ip6 = remote_dst_host.ip6 dst_ip4 = src_ip_if.remote_ip4 src_ip4 = remote_dst_host.ip4 dst_l4 = 1234 + i src_l4 = 4321 + i else: dst_mac = src_ip_if.local_mac src_mac = src_ip_if.remote_mac src_ip6 = src_ip_if.remote_ip6 dst_ip6 = remote_dst_host.ip6 src_ip4 = src_ip_if.remote_ip4 dst_ip4 = remote_dst_host.ip4 src_l4 = 1234 + i dst_l4 = 4321 + i if is_reflected_icmp: icmp_type_delta = 1 # default ULP should be something we do not use in tests ulp_l4 = TCP(sport=src_l4, dport=dst_l4) # potentially a chain of protocols leading to ULP ulp = ulp_l4 if is_udp_packet: if is_ip6: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) if add_extension_header: # prepend some extension headers ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() / IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4) # uncomment below to test invalid ones # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4 else: ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) # IPv4 does not allow extension headers, # but we rather make it a first fragment flags = 1 if add_extension_header else 0 ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) / ulp / Raw(payload)) elif modulo == 1: if is_ip6: ulp_l4 = ICMPv6Unknown(type=128 + icmp_type_delta, code=icmp_code) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = ICMP(type=8 - 8 * icmp_type_delta, code=icmp_code) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4) / ulp / Raw(payload)) if i % 2 == 1: info.data = p.copy() size = packet_sizes[(i // 2) % len(packet_sizes)] self.extend_packet(p, size) pkts.append(p) rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET rule_prefix_len = 128 if p.haslayer(IPv6) else 32 rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP if p.haslayer(UDP): rule_l4_sport = p[UDP].sport rule_l4_dport = p[UDP].dport else: if p.haslayer(ICMP): rule_l4_sport = p[ICMP].type rule_l4_dport = p[ICMP].code else: rule_l4_sport = p[ICMPv6Unknown].type rule_l4_dport = p[ICMPv6Unknown].code if p.haslayer(IPv6): rule_l4_proto = ulp_l4.overload_fields[IPv6]["nh"] else: rule_l4_proto = p[IP].proto new_rule = AclRule( is_permit=is_permit, proto=rule_l4_proto, src_prefix=ip_network((p[rule_l3_layer].src, rule_prefix_len)), dst_prefix=ip_network((p[rule_l3_layer].dst, rule_prefix_len)), sport_from=rule_l4_sport, sport_to=rule_l4_sport, dport_from=rule_l4_dport, dport_to=rule_l4_dport, ) rules.append(new_rule) new_rule_permit = copy.copy(new_rule) new_rule_permit.is_permit = 1 permit_rules.append(new_rule_permit) new_rule_permit_and_reflect = copy.copy(new_rule) if can_reflect_this_packet: new_rule_permit_and_reflect.is_permit = 2 else: new_rule_permit_and_reflect.is_permit = is_permit permit_and_reflect_rules.append(new_rule_permit_and_reflect) self.logger.info("create_stream pkt#%d: %s" % (i, payload)) return { "stream": pkts, "rules": rules, "permit_rules": permit_rules, "permit_and_reflect_rules": permit_and_reflect_rules, }