def show_dns(self, family): if (family == socket.AF_INET): ip_cfg = self.get_ip4_config() else: ip_cfg = self.get_ip6_config() if ip_cfg is None: print("None") return if (family == socket.AF_INET): print ("Domains: %s") % (ip_cfg.get_domains()) print ("Searches: %s") % (ip_cfg.get_searches()) print("Nameservers:") nameservers = ip_cfg.get_nameservers() for dns in nameservers: print socket.inet_ntop(family, struct.pack("=I", dns)) else: print ("Domains: %s") % (ip_cfg.get_domains()) print ("Searches: %s") % (ip_cfg.get_searches()) print("Nameservers:") num = ip_cfg.get_num_nameservers() for i in range(0,num): dns = ip_cfg.get_nameserver(i) print socket.inet_ntop(family, dns)
def __str__(self): """return a human readable version of an ARP packet""" retval = "ARP\n" retval += "hrd: " retval += "%d\n" % self.hrd retval += "pro: " retval += "%d\n" % self.pro retval += "hln: " retval += "%d\n" % self.hln retval += "pln: " retval += "%d\n" % self.pln retval += "op: " retval += "%d\n" % self.op retval += "sha: " if len(self.sha) >= 6: for byte in range(0,5): retval += "%s:" % hex(ord(self.sha[byte]))[2:4] retval += "%s\n" % hex(ord(self.sha[5]))[2:4] retval += "spa: " retval += "%s\n" % inet_ntop(AF_INET, struct.pack('!L', self.spa)) retval += "tha: " if len(self.tha) >= 6: for byte in range(0,5): retval += "%s:" % hex(ord(self.tha[byte]))[2:4] retval += "%s\n" % hex(ord(self.tha[5]))[2:4] retval += "tpa: " retval += "%s\n" % inet_ntop(AF_INET, struct.pack('!L', self.tpa)) return retval
def __init__(self, addr, port=None): if isinstance(addr, ContactInfo): self.host = addr.host self.port = addr.port return if port is None: if len(addr) == 6: port = addr[4:6] addr = addr[0:4] elif len(addr) == 18: port = addr[16:18] addr = addr[0:16] else: raise ValueError("Unknown combined addr+port format.") if len(addr) == 4: self.host = socket.inet_ntop(socket.AF_INET, addr) elif (len(addr) == 16 and not all(x.isdigit() and x == ":" for x in addr)): self.host = socket.inet_ntop(socket.AF_INET6, addr) else: self.host = addr if isinstance(port, (buffer, basestring)): self.port = (ord(port[0]) << 8) + ord(port[1]) else: self.port = port
def read_address(self, fd): """ read a warts-style ip/mac address """ length = WartsReader.read_uint8_t(self.fd) addr = 0 typ = 0 # an embedded (non-referenced) address if length != 0: typ = WartsReader.read_uint8_t(fd) addr = self.fd.read(length) addr_id = len(self.address_ref) self.address_ref[addr_id] = addr # a referenced address else: addr_id = WartsReader.read_uint32_t(fd) try: addr = self.address_ref[addr_id] except: print "Die: couldn't find referenced address %d" % addr_id sys.exit(-1) if typ == 0: if len(addr) == 4: typ = 1 if len(addr) == 16: typ = 2 if typ == 1: return socket.inet_ntop(socket.AF_INET, addr) elif typ == 2: return socket.inet_ntop(socket.AF_INET6, addr) else: print "Addr type:", typ, "not implemented" assert False
def ping_node(self, node): task = self.taskman.new_task() msgout = codec_pb2.MsgDHTMisc() msgout.request_id = task.task_id if len(node.ip) == 4: node_ip = socket.inet_ntop(socket.AF_INET, node.ip) else: node_ip = socket.inet_ntop(socket.AF_INET6, node.ip) addr_tup = (node_ip, node.port) task.addr = addr_tup task.msg_start = msgout # clamp to "1s ... (rtt * 10) ... 15s" range min_timeout = datetime.timedelta(seconds=1) max_timeout = datetime.timedelta(seconds=15) if node.rtt is None: task.timeout = max_timeout else: task.timeout = node.rtt * 10 if task.timeout > max_timeout: task.timeout = max_timeout if task.timeout < min_timeout: task.timeout = min_timeout task.timeout_actor = ping_node_timeout task.timeout_args = [self, node] self.send_message("ping", msgout, addr_tup)
def summarize_ans1(ans1): if len(ans1) != 4 and len(ans1) != 3: return "" if len(ans1) == 4: iph, tcph, tcpoption, payload = ans1 elif len(ans1) == 3: iph, tcph, tcpoption = ans1 s = "" s += '%s.%d > %s.%d: '%(socket.inet_ntop(socket.AF_INET, \ struct.pack('!L', iph.srcaddr)), tcph.srcport, \ socket.inet_ntop(socket.AF_INET, \ struct.pack('!L', iph.dstaddr)), tcph.dstport) s += 'Flags [0x%x], '%tcph.flag s += 'seq %d, ack %d, '%(tcph.seqno, tcph.ackno) s += 'win %d, '%tcph.window if len(tcpoption) > 0: opt_str = '%s ,'%tcpoption opt_str = re.sub('\[', '', opt_str) opt_str = re.sub('\]', '', opt_str) opt_str = re.sub('\'', '', opt_str) opt_str = re.sub(' ,', '', opt_str) s += "options [" + opt_str + "], " s += 'length %d, '%(iph.length - iph.hdrlen - tcph.hdrlen) s += 'pktlen %d, iphdrlen %d, tcphdrlen %d checksum 0x%x'%(iph.length, iph.hdrlen, \ tcph.hdrlen, tcph.checksum) s += '\n' return s
def send_pcapbreak(pkt, stopped): if stopped.isSet(): return iph, tcph, tcpo, payload = parse_headers(pkt) ipdst_str = socket.inet_ntop(socket.AF_INET, struct.pack('!L', iph.dstaddr)) ipsrc_str = socket.inet_ntop(socket.AF_INET, struct.pack('!L', iph.srcaddr)) try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) s.bind(('',tcph.srcport)) s.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, 1) except (socket.error, socket.gaierror): print "Warn: cannot operate sending packets to break pcap loop" return retry = 0.4 for i in range(0, 5): s.sendto("*", (ipdst_str, PCAP_BREAK_DPORT)) stopped.wait(retry) if stopped.isSet(): break retry *= 2 s.close() # if stopped.isSet() is False: # print "Warn: break packet is not handled" return
def print_event(cpu, data, size): # Decode event event = ct.cast(data, ct.POINTER(ListenEvt)).contents pid = event.pid_tgid & 0xffffffff proto_family = event.proto & 0xff proto_type = event.proto >> 16 & 0xff if proto_family == SOCK_STREAM: protocol = "TCP" elif proto_family == SOCK_DGRAM: protocol = "UDP" else: protocol = "UNK" address = "" if proto_type == AF_INET: protocol += "v4" address = inet_ntop(AF_INET, pack("I", event.laddr[0])) elif proto_type == AF_INET6: address = inet_ntop(AF_INET6, event.laddr) protocol += "v6" # Display if show_netns: print("%-6d %-12.12s %-12s %-6s %-8s %-5s %-39s" % ( pid, event.task, event.netns, protocol, event.backlog, event.lport, address, )) else: print("%-6d %-12.12s %-6s %-8s %-5s %-39s" % ( pid, event.task, protocol, event.backlog, event.lport, address, ))
def printResponse(self, message): if message.HasField('response'): response = message.response policystr = '' if response.HasField('appliedPolicy') and response.appliedPolicy: policystr = ', Applied policy: ' + response.appliedPolicy tagsstr = '' if response.tags: tagsstr = ', Tags: ' + ','.join(response.tags) rrscount = len(response.rrs) print("- Response Code: %d, RRs: %d%s%s" % (response.rcode, rrscount, policystr, tagsstr)) for rr in response.rrs: rrclass = 1 rdatastr = '' if rr.HasField('class'): rrclass = getattr(rr, 'class') rrtype = rr.type if (rrclass == 1 or rrclass == 255) and rr.HasField('rdata'): if rrtype == 1: rdatastr = socket.inet_ntop(socket.AF_INET, rr.rdata) elif rrtype == 28: rdatastr = socket.inet_ntop(socket.AF_INET6, rr.rdata) print("\t - %d, %d, %s, %d, %s" % (rrclass, rrtype, rr.name, rr.ttl, rdatastr))
def parse_buffer(self, buf): # 1) Parse Ethernet eth = dpkt.ethernet.Ethernet(buf) self.src_mac = ':'.join('%02x' % ord(b) for b in eth.src) self.dst_mac = ':'.join('%02x' % ord(b) for b in eth.dst) # 2) Parse IP ip = eth.data if eth.type != dpkt.ethernet.ETH_TYPE_IP: self.error = 'Not IPv4' return more_fragments = bool(ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK if more_fragments or fragment_offset > 0: self.error = 'Fragmented Packet' return self.src_ip = socket.inet_ntop(socket.AF_INET, ip.src) self.dst_ip = socket.inet_ntop(socket.AF_INET, ip.dst) self.len = ip.len self.proto = ip.p # 3) Parse UDP if ip.p != dpkt.ip.IP_PROTO_UDP: self.error = 'Not UDP' return udp = ip.data self.src_port = udp.sport self.dst_port = udp.dport # Remaining Payload: self.sip_message = SIPMessage.parse_from_text(udp.data, self.timestamp)
def extractRecord(resolver, name, answers, level=10): if not level: return None if hasattr(socket, 'inet_ntop'): for r in answers: if r.name == name and r.type == dns.A6: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in answers: if r.name == name and r.type == dns.AAAA: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in answers: if r.name == name and r.type == dns.A: return socket.inet_ntop(socket.AF_INET, r.payload.address) for r in answers: if r.name == name and r.type == dns.CNAME: result = extractRecord( resolver, r.payload.name, answers, level - 1) if not result: return resolver.getHostByName( str(r.payload.name), effort=level - 1) return result # No answers, but maybe there's a hint at who we should be asking about # this for r in answers: if r.type == dns.NS: from twisted.names import client r = client.Resolver(servers=[(str(r.payload.name), dns.PORT)]) return r.lookupAddress(str(name) ).addCallback( lambda records: extractRecord( r, name, records[_ANS] + records[_AUTH] + records[_ADD], level - 1))
def recv_udp(listener, bufsize): debug3('Accept UDP using socket_ext recvmsg.\n') srcip, data, adata, flags = listener.recvmsg( (bufsize,), socket.CMSG_SPACE(24)) dstip = None family = None for a in adata: if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_ORIGDSTADDR: family, port = struct.unpack('=HH', a.cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET: start = 4 length = 4 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop( family, a.cmsg_data[start:start + length]) dstip = (ip, port) break elif a.cmsg_level == SOL_IPV6 and a.cmsg_type == IPV6_ORIGDSTADDR: family, port = struct.unpack('=HH', a.cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET6: start = 8 length = 16 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop( family, a.cmsg_data[start:start + length]) dstip = (ip, port) break return (srcip, dstip, data[0])
def routes (): links = {} for ifi in Link.getLinks(): links[ifi.index] = ifi.attributes.get(Link.Type.Attribute.IFLA_IFNAME).strip('\0') print('Kernel IP routing table') print('%-18s %-18s %-18s %-7s %s' % ('Destination','Genmask','Gateway','Metric','Iface')) for route in Network.getRoutes(): if route.family != socket.AF_INET: continue if route.type not in (Network.Type.Type.RTN_LOCAL,Network.Type.Type.RTN_UNICAST): continue if route.src_len == 32: continue destination = route.attributes.get(Network.Type.Attribute.RTA_DST) gateway = route.attributes.get(Network.Type.Attribute.RTA_GATEWAY) oif = ord(route.attributes.get(Network.Type.Attribute.RTA_OIF)[0]) metric = ord(route.attributes.get(Network.Type.Attribute.RTA_PRIORITY,'\0')[0]) dst = '%s' % socket.inet_ntop(route.family, destination) if destination else '' gw = '%s' % socket.inet_ntop(route.family, gateway) if gateway else '0.0.0.0' mask = NetMask.CIDR[route.src_len] iface = links[oif] print('%-18s %-18s %-18s %-7d %-s' % (dst or '0.0.0.0',mask,gw,metric,iface))
def parseIP6(data): ip6Loc = data ip6 = {} ip6.update({'version':ip6Loc.v}) ip6.update({'destination_address':socket.inet_ntop(socket.AF_INET6, ip6Loc.dst)}) ip6.update({'source_address':socket.inet_ntop(socket.AF_INET6, ip6Loc.src)}) ip6.update({'hop_limit':ip6Loc.hlim}) ip6.update({'payload_length':ip6Loc.plen}) ip6.update({'next':ip6Loc.nxt}) ip6.update({'flow_label':ip6Loc.flow}) next = ip6['next'] extHeader = [] while next in [0, 43, 44, 51, 50, 60, 135, 59]: header = parseExtensionHeader(ip6Loc.data) extHeader.append(header) if type(ip6Loc.data) not in [dpkt.ip6.IP6OptsHeader,dpkt.ip6.IP6HopOptsHeader, dpkt.ip6.IP6DstOptsHeader, dpkt.ip6.IP6RoutingHeader, dpkt.ip6.IP6FragmentHeader, dpkt.ip6.IP6AHHeader, dpkt.ip6.IP6ESPHeader]: break ip6Loc = ip6Loc.data next = ip6Loc.nxt if len(extHeader) > 0: ip6.update({'extensionHeader':extHeader}) ip6.update({'data':ip6Loc.data}) return ip6
def unpack_host(host): #fp=open("host.txt",'w+b') #fp.write(host+"\n") if len(host) == 4: return socket.inet_ntop(socket.AF_INET, host) elif len(host) == 16: return socket.inet_ntop(socket.AF_INET6, host)
def extractRecord(resolver, name, answers, level = 10): if not level: return None if hasattr(socket, 'inet_ntop'): for r in answers: if r.name == name and r.type == dns.A6: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in answers: if r.name == name and r.type == dns.AAAA: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in answers: if r.name == name and r.type == dns.A: return socket.inet_ntop(socket.AF_INET, r.payload.address) for r in answers: if r.name == name and r.type == dns.CNAME: result = extractRecord(resolver, r.payload.name, answers, level - 1) if not result: return resolver.getHostByName(str(r.payload.name), effort=level-1) return result # No answers, but maybe there's a hint at who we should be asking about this for r in answers: if r.type == dns.NS: from twisted.names import client r = client.Resolver(servers=[(str(r.payload.name), dns.PORT)]) return r.lookupAddress(str(name) ).addCallback(lambda (ans, auth, add): extractRecord(r, name, ans + auth + add, level - 1) ).addBoth(lambda passthrough: (r.protocol.transport.stopListening(), passthrough)[1])
def get_random_cidr(mask=None, af='v4'): ''' Generate a random subnet based on netmask and address family ''' if not is_valid_af(af=af): raise ValueError("Address family not supported %s" % af) if mask is None: mask = SUBNET_MASK[af]['default'] if type(mask) is int: mask = str(mask) if not is_valid_subnet_mask(plen=mask, af=af): raise ValueError("Invalid subnet mask %s for af %s" % (mask, af)) while (True): if af == 'v6': min = 0x2001000000000000 max = 0x3fffffffffffffff address = socket.inet_ntop(socket.AF_INET6, struct.pack('>2Q', random.randint(min, max), random.randint(0, 2 ** 64))) elif af == 'v4': address = socket.inet_ntop(socket.AF_INET, struct.pack('>I', random.randint(2 ** 24, 2 ** 32))) if is_reserved_address(address): continue if is_valid_address(address): return '%s/%s' % (str(IPNetwork(address + '/' + mask).network), mask)
def bmpParse_peerUpHdr(fd, bmp_peer_hdr): """ Parse BMP peer UP header from file :param fd: Opened file descriptor to the BMP file :param bmp_peer_hdr: Reference to the parsed bmp peer header ..note: info TLV's should be checked after initial header parse. BGP OPEN messages should be checked after the initial header parse :return: dictionary defined as:: { local_address: <string; printed form of local IP>, local_port: <int; local port>, remote_port: <int; remote port>, } """ hdr = { 'local_addr': None, 'local_port': 0, 'remote_port': 0} if (bmp_peer_hdr['isIPv4']): fd.read(12) # skip to the ipv4 address hdr['local_address'] = socket.inet_ntop(socket.AF_INET, fd.read(4)) else: hdr['local_address'] = socket.inet_ntop(socket.AF_INET6, fd.read(16)) (hdr['local_port'], hdr['remote_port'],) = unpack('>HH', fd.read(4)) return hdr
def deserialize_network_address(self, data, has_timestamp=False): timestamp = None if has_timestamp: timestamp = struct.unpack("<I", data.read(4))[0] try: services = struct.unpack("<Q", data.read(8))[0] except struct.error as err: raise ReadError(err) _ipv6 = data.read(12) _ipv4 = data.read(4) port = struct.unpack(">H", data.read(2))[0] ipv6 = socket.inet_ntop(socket.AF_INET6, _ipv6 + _ipv4) ipv4 = socket.inet_ntop(socket.AF_INET, _ipv4) if ipv4 in ipv6: ipv6 = "" # use ipv4 else: ipv4 = "" # use ipv6 return { 'timestamp': timestamp, 'services': services, 'ipv6': ipv6, 'ipv4': ipv4, 'port': port, }
def __init__(self, address, packet): """ Initialize a usagepacket from a binary string containing the UDP packet contents. Arguments: self -- The new usagepacket.usagepacket object packet -- The binary packet contents Returns: New IPTimeMonitorPacket """ UsagePacket.__init__(self, address, packet) packdata = self.unpack("qB") time_sent_millis = packdata[0] time_sent = time_sent_millis / 1000 frac_secs = time_sent_millis - int(time_sent_millis) send_time = list(time.gmtime(time_sent))[0:6] send_time[5] += frac_secs self.send_time = tuple(send_time) address_form = packdata[1] if address_form == 4: address_data = self.unpack("4B") self.ip_address = socket.inet_ntop( socket.AF_INET, struct.pack('4B', *address_data)) elif address_form == 6: address_data = self.unpack("16B") self.ip_address = socket.inet_ntop( socket.AF_INET6, struct.pack('16B', *address_data))
def _unquote_host(self, host): # IPv6 / IPvFuture if host.startswith(b'[') and host.endswith(b']'): host = host[1:-1] try: return u'[%s]' % inet_ntop(AF_INET6, inet_pton(AF_INET6, host)).decode('ascii') except SocketError: # IPvFuture if host.startswith(b'v') and b'.' in host and host[1:].split('.', 1)[0].isdigit(): try: return u'[%s]' % host.decode('ascii') except UnicodeDecodeError: raise InvalidURI(_('Invalid IPvFuture address: must be ASCII.')) raise InvalidURI(_('Invalid IP address in URI.')) # IPv4 if all(x.isdigit() for x in host.split(b'.')): try: return inet_ntop(AF_INET, inet_pton(AF_INET, host)).decode('ascii') except SocketError: raise InvalidURI(_('Invalid IPv4 address in URI.')) if host.strip(Percent.UNRESERVED + Percent.SUB_DELIMS + b'%'): raise InvalidURI(_('Invalid URI host.')) # DNS hostname host = self.unquote(host) try: return host.encode('ascii').decode('idna').lower() except UnicodeError: raise InvalidURI(_('Invalid host.'))
def data_received(self, data): if self.state == self.INIT: assert data[0] == 0x05 # server -> client. VER | METHOD self.transport.write(pack('!BB', 0x05, 0x00)) # no auth self.state = self.HOST elif self.state == self.HOST: # socks request info. VER | CMD | RSV | ATYP | SDT.ADDR | DST.PORT ver, cmd, rsv, atype = data[:4] assert ver == 0x05 and cmd == 0x01 if atype == 3: # domain length = data[4] hostname, nxt = data[5:5 + length], 5 + length elif atype == 1: # ipv4 hostname, nxt = socket.inet_ntop(socket.AF_INET, data[4:8]), 8 elif atype == 4: # ipv6 hostname, nxt = socket.inet_ntop(socket.AF_INET6, data[4:20]), 20 else: logging.warn('addr_type not suport') return port = unpack('!H', data[nxt:nxt + 2])[0] logging.info('request connect to {}:{}'.format(hostname, port)) # 连接proxyserver asyncio.ensure_future(self.connect(hostname, port)) self.state = self.DATA elif self.state == self.DATA: self.client_transport.write(data)
def from_bytes(cls, b): services, host, port = struct.unpack('>Q16sH', b) if host.startswith(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF'): host = socket.inet_ntop(socket.AF_INET, host[-4:]) else: host = socket.inet_ntop(socket.AF_INET6, host) return cls(services, host, port)
def show_routes(self, family): if (family == socket.AF_INET): ip_cfg = self.get_ip4_config() else: ip_cfg = self.get_ip6_config() if ip_cfg is None: print("None") return nm_routes = ip_cfg.get_routes() if len(nm_routes) == 0: print("None") return for nm_route in nm_routes: dest = nm_route.get_dest() prefix = nm_route.get_prefix() next_hop = nm_route.get_next_hop() metric = nm_route.get_metric() if (family == socket.AF_INET): dest_struct = struct.pack("=I", dest) next_hop_struct = struct.pack("=I", next_hop) else: dest_struct = dest next_hop_struct = next_hop print("%s/%d %s %d") % (socket.inet_ntop(family, dest_struct), prefix, socket.inet_ntop(family, next_hop_struct), metric)
def ParseBmpPeerUp(message, peer_flags, verbose=False): """Parse a BMP V3 Peer Up message. Args: header: array containing BMP peer up message. peer_flags: from the per-peer header. verbose: be chatty, or not. Returns: A list of strings to print. Raises: ValueError: an unexpected value was found in the message """ indent_str = indent.IndentLevel(indent.BMP_CONTENT_INDENT) print_msg = [] offset = 0 if peer_flags & PEER_FLAG_IPV6: loc_addr = socket.inet_ntop(socket.AF_INET6, message[offset : offset + 16]) else: loc_addr = socket.inet_ntop(socket.AF_INET, message[offset + 12 : offset + 16]) offset += 16 loc_port, rem_port = struct.unpack_from(">HH", message, offset) print_msg.append("%sloc_addr %s, loc_port %d, rem_port %d\n" % (indent_str, loc_addr, loc_port, rem_port)) return print_msg
def _extractRecord(self, records, name, timeout, effort): twunnel.logger.log(3, "trace: ResolverBase._extractRecord") dnsName = dns.Name(name) if not effort: return None for r in records: if r.name == dnsName and r.type == dns.A: return socket.inet_ntop(socket.AF_INET, r.payload.address) for r in records: if r.name == dnsName and r.type == dns.A6: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in records: if r.name == dnsName and r.type == dns.AAAA: return socket.inet_ntop(socket.AF_INET6, r.payload.address) for r in records: if r.name == dnsName and r.type == dns.CNAME: result = self._extractRecord(records, str(r.payload.name), timeout, effort - 1) if not result: return self.getHostByName(str(r.payload.name), timeout, effort - 1) return result for r in records: if r.type == dns.NS: configuration = {} configuration["PROXY_SERVERS"] = self.configuration["PROXY_SERVERS"] configuration["DNS_RESOLVER"] = {} configuration["DNS_RESOLVER"]["SERVERS"] = [] configuration["DNS_RESOLVER"]["SERVERS"].append({}) configuration["DNS_RESOLVER"]["SERVERS"][0]["ADDRESS"] = str(r.payload.name) configuration["DNS_RESOLVER"]["SERVERS"][0]["PORT"] = dns.PORT resolver = ServerResolver(configuration) return resolver.getHostByName(name, timeout, effort - 1)
def _ParseProcIgmp(self): """Returns a list of current IGMP group memberships. /proc/net/igmp uses an unusual format: Idx Device : Count Querier Group Users Timer Reporter 1 lo : 1 V3 010000E0 1 0:00000000 0 2 eth0 : 1 V3 010000E0 1 0:00000000 0 010000E0 is the IP multicast address as a hex number, and always big endian. """ igmps = set() with open(PROCNETIGMP, 'r') as f: for line in f: result = IGMPREGEX.match(line) if result is not None: igmp = result.group(1).strip() igmps.add(socket.inet_ntop( socket.AF_INET, struct.pack('<L', int(igmp, 16)))) with open(PROCNETIGMP6, 'r') as f: for line in f: result = IGMP6REGEX.match(line) if result is not None: igmp = result.group(1).strip() ip6 = ':'.join([igmp[0:4], igmp[4:8], igmp[8:12], igmp[12:16], igmp[16:20], igmp[20:24], igmp[24:28], igmp[28:]]) igmps.add(socket.inet_ntop(socket.AF_INET6, socket.inet_pton(socket.AF_INET6, ip6))) return list(igmps)
def show_addresses(self, family): if (family == socket.AF_INET): ip_cfg = self.get_ip4_config() else: ip_cfg = self.get_ip6_config() if ip_cfg is None: print("None") return nm_addresses = ip_cfg.get_addresses() if len(nm_addresses) == 0: print("None") return for nm_address in nm_addresses: addr = nm_address.get_address() prefix = nm_address.get_prefix() gateway = nm_address.get_gateway() if (family == socket.AF_INET): addr_struct = struct.pack("=I", addr) gateway_struct = struct.pack("=I", gateway) else: addr_struct = addr gateway_struct = gateway print("%s/%d %s") % (socket.inet_ntop(family, addr_struct), prefix, socket.inet_ntop(family, gateway_struct))
def _decode_addr_key(self, obj_dict): """ Callback function to handle the decoding of the 'Addr' field. Serf msgpack 'Addr' as an IPv6 address, and the data needs to be unpack using socket.inet_ntop(). See: https://github.com/KushalP/serfclient-py/issues/20 :param obj_dict: A dictionary containing the msgpack map. :return: A dictionary with the correct 'Addr' format. """ key = b'Addr' if key in obj_dict: try: # Try to convert a packed IPv6 address. # Note: Call raises ValueError if address is actually IPv4. ip_addr = socket.inet_ntop(socket.AF_INET6, obj_dict[key]) # Check if the address is an IPv4 mapped IPv6 address: # ie. ::ffff:xxx.xxx.xxx.xxx if ip_addr.startswith('::ffff:'): ip_addr = ip_addr.lstrip('::ffff:') obj_dict[key] = ip_addr.encode('utf-8') except ValueError: # Try to convert a packed IPv4 address. ip_addr = socket.inet_ntop(socket.AF_INET, obj_dict[key]) obj_dict[key] = ip_addr.encode('utf-8') return obj_dict
def extract_streams(self): """ Extracts TCP streams with data from the pcap file. TCP segments in each stream are queued according to their sequence number. """ with open(self.filepath) as pcap_file: pcap_reader = dpkt.pcap.Reader(pcap_file) for timestamp, buf in pcap_reader: frame = dpkt.ethernet.Ethernet(buf) ip_pkt = frame.data if isinstance(ip_pkt.data, dpkt.tcp.TCP): ip_ver = socket.AF_INET if ip_pkt.v == 6: ip_ver = socket.AF_INET6 tcp_pkt = ip_pkt.data stream_id = ( socket.inet_ntop(ip_ver, ip_pkt.src), tcp_pkt.sport, socket.inet_ntop(ip_ver, ip_pkt.dst), tcp_pkt.dport ) if len(tcp_pkt.data) > 0: timestamp = int(timestamp * 1000) # in ms self.streams[stream_id].put( (tcp_pkt.seq, (timestamp, tcp_pkt))) logging.info("Streams: %d", len(self.streams))
def do_dad(self): """perform the duplicate address detection (DAD) proccess as described in RFC4861 and updated in RFC3971""" while self.__collcount < 3: # send MLD to receive packets destined to our tentative address # FIXIT: it seems that scapy6send does not handle MLD report message correctly for now # investigate on this # we need this value on the forked process too, so we compute it # before the fork nonce = "".join([ chr(random.randrange(255)) for i in range(6)]) # the father process sniff (potentials) DAD packets while the # children one send a NS pid = os.fork() # the filters of sniff() function works better when conf.iface is # not a tun (could be the case if the node uses an IPv6 tunnel old_if = conf.iface conf.iface = self.__interface if pid == 0: # send a NS toward the solicited node multicast address time.sleep(0.2) # to be sure the capture mode is already on cgapds = CGAParams(modifier = pkcs_i2osp(self.__modifier, 16), \ prefix = self.__prefix, \ ccount = self.__collcount, \ pubkey = self.__pubkey, \ ext = self.__ext) p = str( IPv6(src = "::",dst = inet_ntop(socket.AF_INET6, # dst is the solicited node multicast address in6_getnsma(inet_pton(socket.AF_INET6, self.__address))))/ ICMPv6ND_NS(tgt = self.__address) ) p = Ether(src=get_if_hwaddr(self.__interface)) / self.sign(p,dad=True,nonce=nonce) sendp(p,iface=self.__interface,verbose=NDprotector.verbose) os._exit(0) else: # listen (sniff) to packets destined to the solicited node multicast address and the tentative address itself hwaddr = get_if_hwaddr(self.__interface) packets = sniff(timeout=NDprotector.retrans_timer, \ iface=self.__interface, \ filter="icmp6 and not ether src %s" % hwaddr, \ lfilter= lambda x: x.haslayer(ICMPv6ND_NS) or x.haslayer(ICMPv6ND_NA)) collision = False for packet in packets: # we only threat NS and NA NS and NA if (packet.haslayer(ICMPv6ND_NS) and \ packet.getlayer(IPv6).src=="::" and \ packet.getlayer(ICMPv6ND_NS).tgt == self.__address) \ or \ (packet.haslayer(ICMPv6ND_NA) and packet.getlayer(ICMPv6ND_NA).tgt==self.__address): if self.__collcount==0: collision=True break # from RFC 3971: first time when perform DAD, we listen for unsecure NDP messages else: try: address = packet[IPv6].src # we can receive messages from other node performing the DAD if packet.haslayer(ICMPv6ND_NS) and address == "::": address = packet.tgt # CGA address check if not CGAverify(address,packet[CGAParams]): warn("one packet with an invalid CGA address was received during the DAD procedure\n") continue # signature check if not packet[ICMPv6NDOptUSSig].verify_rsa_sig(packet[CGAParams].pubkey): warn("one packet failed signature check during the DAD process\n") continue if packet.haslayer(ICMPv6ND_NS) and packet.getlayer(ICMPv6NDOptNonce).nonce == nonce: warn("one packet is a replayed packet (potentially under a DAD DOS replay attack\n") continue if packet.haslayer(ICMPv6ND_NA) and packet.dst != "ff02::1" and packet.getlayer(ICMPv6NDOptNonce).nonce != nonce : print "expect %s" % `nonce` print "received %s" % `packet.getlayer(ICMPv6NDOptNonce).nonce` warn("NA value does not match the nonce from the NS\n") continue # quick and dirty way to obtain the "current" time ts = ICMPv6NDOptTimestamp(str(ICMPv6NDOptTimestamp())).timestamp # nodes need to have a loosely synchronised clock if math.fabs(packet.getlayer(ICMPv6NDOptTimestamp).timestamp - ts) > NDprotector.ts_delta: warn("Timestamp value exceed the delta\n") continue except AttributeError: # where likely to go in there if one option is missing continue # in this case, we ignore the packet # weak TODO so far, the packet seems legit, # need create/update an entry in the Neighbor # Cache (so the Timestamp value is recorded) collision=True break os.wait() conf.iface = old_if if collision==True: self.__collcount += 1 warn("collision on %s detected\n" % self.__address) (self.__address,_) = CGAgen1(self.__prefix, \ self.__pubkey, \ self.__sec, \ self.__ext, \ pkcs_i2osp(self.__modifier,16), \ self.__collcount) warn("trying DAD on new address %s\n" % self.__address) # no collision, DAD has been performed correctly else: return raise DadException("Duplicate Address Detection for %s failed, likely due to an attack or a misconfiguration" % self.__address)
def ip_to_str(address): return socket.inet_ntop(socket.AF_INET, address)
def get_prefix(self): return socket.inet_ntop(socket.AF_INET6,socket.inet_pton(socket.AF_INET6,self.__address)[:8] + "\x00"*8)
def ipv6StrToAddress(ipv6_str): return socket.inet_ntop( socket.AF_INET6, struct.pack('>QQ', *divmod(int(ipv6_str, 16), 2**64)))
async def cb_ondnstap(dnstap_decoder, payload, cfg, queue, metrics): """on dnstap""" # decode binary payload dnstap_decoder.ParseFromString(payload) dm = dnstap_decoder.message # filtering by dnstap identity ? tap_ident = dnstap_decoder.identity.decode() if not len(tap_ident): tap_ident = "-" if cfg["filter"]["dnstap-identities"] is not None: if re.match(cfg["filter"]["dnstap-identities"], dnstap_decoder.identity.decode()) is None: del dm return tap = { "identity": tap_ident, "query-name": "-", "query-type": "-", "source-ip": "-" } # decode type message tap["message"] = DNSTAP_TYPE.get(dm.type, "-") tap["protocol"] = DNSTAP_FAMILY.get(dm.socket_family, "-") tap["transport"] = DNSTAP_PROTO.get(dm.socket_protocol, "-") # decode query address if len(dm.query_address) and dm.socket_family == 1: tap["source-ip"] = socket.inet_ntoa(dm.query_address) if len(dm.query_address) and dm.socket_family == 2: tap["source-ip"] = socket.inet_ntop(socket.AF_INET6, dm.query_address) tap["source-port"] = dm.query_port if tap["source-port"] == 0: tap["source-port"] = "-" # handle query message if (dm.type % 2) == 1: dnstap_parsed = from_wire(dm.query_message, question_only=True) tap["length"] = len(dm.query_message) d1 = dm.query_time_sec + (round(dm.query_time_nsec) / 1000000000) tap["timestamp"] = datetime.fromtimestamp(d1, tz=timezone.utc).isoformat() # handle response message if (dm.type % 2) == 0: dnstap_parsed = from_wire(dm.response_message, question_only=True) tap["length"] = len(dm.response_message) d2 = dm.response_time_sec + (round(dm.response_time_nsec) / 1000000000) tap["timestamp"] = datetime.fromtimestamp(d2, tz=timezone.utc).isoformat() # common params if len(dnstap_parsed.question): tap["query-name"] = dnstap_parsed.question[0].name tap["query-type"] = dns.rdatatype.to_text( dnstap_parsed.question[0].rdtype) tap["code"] = dns.rcode.to_text(dnstap_parsed.rcode()) # filtering by qname ? if cfg["filter"]["qname-regex"] is not None: if re.match(cfg["filter"]["qname-regex"], tap["query-name"]) is None: del dm del tap return # update metrics metrics.record_dnstap(dnstap=tap) # finally add decoded tap message in queue for outputs # except for metrics # if cfg["output"]["metrics"]["enable"]: # return queue.put_nowait(tap)
def __init__(self,interface=None,\ address=None,prefix=None,\ key=None,modifier=None,sec=None,\ collcount=0, ext=None, keypos=0,\ publickey=None,\ autoconf=False, dad=True,\ ** extrap): """if no interface name is given, we'll use scapy6send to determine a working one and use it""" self.__interface = None self.__address = None self.__prefix = None self.__key = None self.__pubkey = None self.__modifier = 0 self.__collcount = 0 self.__sec = 0 self.__ext = [] self.__keypos = keypos self.__autoconf = autoconf # we can't put ext=[] as a default argument because of its "mutable" nature if ext == None: ext = [] self.__ext = ext plugins = get_plugins_by_capability("Address") for plugin in plugins: plugin.init_address(self,extrap) # time at the beginning of the function beginning = time.time() if not address and not prefix: raise Exception("can not configure an address without at least a prefix") if address and (not key or (not modifier and modifier !=0 )): raise Exception("can not use an address without at least the key and the modifier") if interface == None: warn("no interface name given, using %s\n" % conf.iface) self.__interface = conf.iface else: if interface in get_if_list(): self.__interface = interface else: raise AddressException("No such interface for the address: %s", interface) if collcount >= 0 and collcount <= 3: self.__collcount = collcount else: raise AddressException("The collision counter must be between 0 and 3") if modifier == None: self.__modifier= random.randint(0,2**128 -1) else: self.__modifier= modifier if sec != None: self.__sec=sec else: self.__sec=NDprotector.default_sec_value if prefix: # prefix length is /64 if socket.inet_pton(socket.AF_INET6,prefix)[8:] == \ '\x00'*8 : self.__prefix == prefix else: raise AddressException("prefix %s is not valid" % prefix) # generate a key or use a default one when none is passed if key is None and NDprotector.default_publickey: self.__key = load_key(NDprotector.default_publickey, NDprotector.ECCsupport) self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport) elif key is None and not NDprotector.default_publickey: warn("Computing an RSA key pair\n") k = Popen( [ OpenSSL , "genrsa", str(NDprotector.rsa_key_size)], stdout=PIPE, stderr=PIPE) key = k.stdout.read() if not "BEGIN RSA PRIVATE KEY" in key: raise AddressException("unable to compute the RSA public Key") self.__key = Key(key) self.__pubkey = self.__key.toPubKey() # a key was passed else: self.__key = load_key(key, NDprotector.ECCsupport) self.__pubkey = load_pkey(key, NDprotector.ECCsupport) # set the Public Key that will be store in the CGA PDS # in the Public Key field if publickey: self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport) if address == None: self.__prefix = prefix warn("Generating CGA\n") if type(modifier) == int: modifier = pkcs_i2osp(modifier,16) res = CGAgen(prefix, self.__pubkey, self.__sec, modifier = modifier, ext=ext, do_dad=False) if type(res) is tuple: (self.__address,param) = res self.__modifier = pkcs_os2ip(param.modifier) else: raise AddressException("failed to create an address, perhaps you should investage on the public key files") else: # we use the address passed in parameter self.__address = address # weak TODO: find something cleaner to extract the prefix from the address self.__prefix = socket.inet_ntop(socket.AF_INET6, \ socket.inet_pton(socket.AF_INET6,address)[:8]+"\x00"*8) modifier = pkcs_i2osp(self.__modifier,16) self.__sec = ord(socket.inet_pton(\ socket.AF_INET6,self.__address)[8]) >> 5 if not CGAverify(self.__address, CGAParams(modifier=modifier, prefix=self.__prefix, \ ccount = self.__collcount, pubkey = self.__pubkey, \ ext = ext)): raise AddressException("Address %s is not a valid CGA" % self.__address) if NDprotector.assign_addresses: self.assign(dad=dad) end = time.time() warn("CGA address %s computed and assigned in %f seconds\n" %\ (self.__address, end - beginning))
def recaddr(self, data): #listOfAddressDetailsToBroadcastToPeers = [] numberOfAddressesIncluded = 0 numberOfAddressesIncluded, lengthOfNumberOfAddresses = decodeVarint( data[:10]) if shared.verbose >= 1: with shared.printLock: print 'addr message contains', numberOfAddressesIncluded, 'IP addresses.' if numberOfAddressesIncluded > 1000 or numberOfAddressesIncluded == 0: return if len(data) != lengthOfNumberOfAddresses + ( 38 * numberOfAddressesIncluded): print 'addr message does not contain the correct amount of data. Ignoring.' return for i in range(0, numberOfAddressesIncluded): try: fullHost = data[20 + lengthOfNumberOfAddresses + (38 * i):36 + lengthOfNumberOfAddresses + (38 * i)] except Exception as err: with shared.printLock: sys.stderr.write( 'ERROR TRYING TO UNPACK recaddr (recaddrHost). Message: %s\n' % str(err)) break # giving up on unpacking any more. We should still be connected however. try: recaddrStream, = unpack( '>I', data[8 + lengthOfNumberOfAddresses + (38 * i):12 + lengthOfNumberOfAddresses + (38 * i)]) except Exception as err: with shared.printLock: sys.stderr.write( 'ERROR TRYING TO UNPACK recaddr (recaddrStream). Message: %s\n' % str(err)) break # giving up on unpacking any more. We should still be connected however. if recaddrStream == 0: continue if recaddrStream != self.streamNumber and recaddrStream != ( self.streamNumber * 2 ) and recaddrStream != ( (self.streamNumber * 2) + 1 ): # if the embedded stream number is not in my stream or either of my child streams then ignore it. Someone might be trying funny business. continue try: recaddrServices, = unpack( '>Q', data[12 + lengthOfNumberOfAddresses + (38 * i):20 + lengthOfNumberOfAddresses + (38 * i)]) except Exception as err: with shared.printLock: sys.stderr.write( 'ERROR TRYING TO UNPACK recaddr (recaddrServices). Message: %s\n' % str(err)) break # giving up on unpacking any more. We should still be connected however. try: recaddrPort, = unpack( '>H', data[36 + lengthOfNumberOfAddresses + (38 * i):38 + lengthOfNumberOfAddresses + (38 * i)]) except Exception as err: with shared.printLock: sys.stderr.write( 'ERROR TRYING TO UNPACK recaddr (recaddrPort). Message: %s\n' % str(err)) break # giving up on unpacking any more. We should still be connected however. # print 'Within recaddr(): IP', recaddrIP, ', Port', # recaddrPort, ', i', i if fullHost[ 0: 12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': ipv4Host = fullHost[12:] hostFromAddrMessage = socket.inet_ntop(socket.AF_INET, ipv4Host) if not self._checkIPv4Address(ipv4Host, hostFromAddrMessage): continue else: hostFromAddrMessage = socket.inet_ntop(socket.AF_INET6, fullHost) if hostFromAddrMessage == "": # This can happen on Windows systems which are not 64-bit compatible # so let us drop the IPv6 address. continue if not self._checkIPv6Address(fullHost, hostFromAddrMessage): continue timeSomeoneElseReceivedMessageFromThisNode, = unpack( '>Q', data[lengthOfNumberOfAddresses + (38 * i):8 + lengthOfNumberOfAddresses + (38 * i)] ) # This is the 'time' value in the received addr message. 64-bit. if recaddrStream not in shared.knownNodes: # knownNodes is a dictionary of dictionaries with one outer dictionary for each stream. If the outer stream dictionary doesn't exist yet then we must make it. shared.knownNodesLock.acquire() shared.knownNodes[recaddrStream] = {} shared.knownNodesLock.release() peerFromAddrMessage = shared.Peer(hostFromAddrMessage, recaddrPort) if peerFromAddrMessage not in shared.knownNodes[recaddrStream]: if len( shared.knownNodes[recaddrStream] ) < 20000 and timeSomeoneElseReceivedMessageFromThisNode > ( int(time.time()) - 10800 ) and timeSomeoneElseReceivedMessageFromThisNode < ( int(time.time()) + 10800 ): # If we have more than 20000 nodes in our list already then just forget about adding more. Also, make sure that the time that someone else received a message from this node is within three hours from now. shared.knownNodesLock.acquire() shared.knownNodes[recaddrStream][peerFromAddrMessage] = ( timeSomeoneElseReceivedMessageFromThisNode) shared.knownNodesLock.release() with shared.printLock: print 'added new node', peerFromAddrMessage, 'to knownNodes in stream', recaddrStream shared.needToWriteKnownNodesToDisk = True hostDetails = (timeSomeoneElseReceivedMessageFromThisNode, recaddrStream, recaddrServices, hostFromAddrMessage, recaddrPort) #listOfAddressDetailsToBroadcastToPeers.append(hostDetails) shared.broadcastToSendDataQueues( (self.streamNumber, 'advertisepeer', hostDetails)) else: timeLastReceivedMessageFromThisNode = shared.knownNodes[ recaddrStream][ peerFromAddrMessage] # PORT in this case is either the port we used to connect to the remote node, or the port that was specified by someone else in a past addr message. if (timeLastReceivedMessageFromThisNode < timeSomeoneElseReceivedMessageFromThisNode) and ( timeSomeoneElseReceivedMessageFromThisNode < int( time.time())): shared.knownNodesLock.acquire() shared.knownNodes[recaddrStream][ peerFromAddrMessage] = timeSomeoneElseReceivedMessageFromThisNode shared.knownNodesLock.release() #if listOfAddressDetailsToBroadcastToPeers != []: # self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers) with shared.printLock: print 'knownNodes currently has', len( shared.knownNodes[self.streamNumber]), 'nodes for this stream.'
def unpack_ipvx_address(cls, pkt, of, ver): sz = 4 if ver == 4 else 16 af = socket.AF_INET if ver == 4 else socket.AF_INET6 raw = pkt[of:of + sz] return socket.inet_ntop(af, raw), of + sz
def update_record(self, zc, now, record): if record.type == _TYPE_A and len(record.address) == 4: self.addrs.append( socket.inet_ntop(socket.AF_INET, record.address))
def inet_to_str(inet: bytes) -> str: try: return socket.inet_ntop(socket.AF_INET, inet) except ValueError: return socket.inet_ntop(socket.AF_INET6, inet)
def decode_rr(pkt, offset, hexrdata): """ Decode a resource record, given DNS packet and offset""" orig_offset = offset domainname, offset = get_domainname(pkt, offset) rrtype, rrclass, ttl, rdlen = \ struct.unpack("!HHIH", pkt[offset:offset+10]) offset += 10 rdata = pkt[offset:offset + rdlen] if hexrdata: rdata = hexdump(rdata) elif rrtype == 1: # A rdata = socket.inet_ntop(socket.AF_INET, rdata) elif rrtype in [2, 5, 12, 39]: # NS, CNAME, PTR rdata, junk = get_domainname(pkt, offset) # DNAME rdata = pdomainname(rdata) elif rrtype == 6: # SOA rdata = decode_soa_rdata(pkt, offset, rdlen) elif rrtype == 15: # MX mx_pref, = struct.unpack('!H', pkt[offset:offset + 2]) rdata, junk = get_domainname(pkt, offset + 2) rdata = "%d %s" % (mx_pref, pdomainname(rdata)) elif rrtype in [16, 99]: # TXT, SPF rdata = decode_txt_rdata(rdata, rdlen) elif rrtype == 28: # AAAA rdata = socket.inet_ntop(socket.AF_INET6, rdata) elif rrtype == 33: # SRV rdata = decode_srv_rdata(pkt, offset) elif rrtype == 41: # OPT pass elif rrtype in [43, 59, 32769]: # [C]DS, DLV rdata = decode_ds_rdata(pkt, offset, rdlen) elif rrtype == 44: # SSHFP rdata = decode_sshfp_rdata(pkt, offset, rdlen) elif rrtype == 45: # IPSECKEY rdata = decode_ipseckey_rdata(pkt, offset, rdlen) elif rrtype in [46, 24]: # RRSIG, SIG rdata = decode_rrsig_rdata(pkt, offset, rdlen) elif rrtype == 47: # NSEC rdata = decode_nsec_rdata(pkt, offset, rdlen) elif rrtype in [48, 25, 60]: # [C]DNSKEY, KEY rdata = decode_dnskey_rdata(pkt, offset, rdlen) elif rrtype == 50: # NSEC3 rdata = decode_nsec3_rdata(pkt, offset, rdlen) elif rrtype == 51: # NSEC3PARAM rdata = decode_nsec3param_rdata(pkt, offset, rdlen) elif rrtype in [52, 53]: # TLSA, SMIMEA rdata = decode_tlsa_rdata(rdata) elif rrtype == 61: # OPENPGPKEY rdata = decode_openpgpkey_rdata(rdata) elif rrtype == 257: # CAA rdata = decode_caa_rdata(rdata) elif rrtype == 250: # TSIG tsig_name = pdomainname(domainname) tsig = options["tsig"] rdata = tsig.decode_tsig_rdata(pkt, offset, rdlen, tsig_name, orig_offset) else: # use RFC 3597 rdata = generic_rdata_encoding(rdata, rdlen) offset += rdlen return (domainname, rrtype, rrclass, ttl, rdata, offset)
def read_data(): global flow_stats global l2_header global packet_queue global stop_event packet_count = 0 while True: # Retrieve a packet, or break out if everything is finished try: data = packet_queue.get(timeout=1) except Empty: if stop_event.is_set(): break continue seconds, microseconds, captured_length, packet_length, pkt_data = data # Inspect the Ethernet header to determine where the layer 3 data # starts and what type it is.- # ether_type 0x8100 has a VLAN tag (802.1Q) # ether_type 0x88A8 and 0x9100 have two VLAN tags (Q-in-Q) ether_type = l2_header.unpack_from(pkt_data, 0)[-1] l3_offset = l2_header.size if ether_type == 0x8100: ether_type = ethernet_q_header.unpack_from(pkt_data, 0)[-1] l3_offset = ethernet_q_header.size print('Q tagging detected') elif (ether_type == 0x88A8) or (ether_type == 0x9100): ether_type = ethernet_qq_header.unpack_from(pkt_data, 0)[-1] l3_offset = ethernet_qq_header.size print('Q-in-Q tagging detected') # Inspect the IP header to determine where the layer 4 data starts and # what type it is. # ether_type 0x0800 is IPv4 # ether_type 0x86dd is IPv6 more_fragments = 0 frag_offset = 0 if ether_type == 0x0800: address_family = AF_INET ip_data = ipv4_header.unpack_from(pkt_data, l3_offset) version_ihl = ip_data[0][0] version = ip_data[0][0] >> 4 if version != 4: print('IP version did not match EtherType') protocol = ip_data[6] ihl = version_ihl & 0x0F l4_offset = l3_offset + (ihl * 4) frag_key = ip_data[3] frag_info = ip_data[4] more_fragments = (frag_info >> 13) & 0b001 frag_offset = frag_info & 0x1FFF elif ether_type == 0x86dd: address_family = AF_INET6 ip_data = ipv6_header.unpack_from(pkt_data, l3_offset) version = ip_data[0][0] >> 4 if version != 6: print('IP version did not match EtherType') protocol = ip_data[2] l4_offset = l3_offset + ipv6_header.size else: print('Unrecognized L3 type {}'.format(ether_type)) continue # Not part of a fragment, and nothing left if (not frag_offset) and (not more_fragments): pass # The first part of a fragment elif (not frag_offset) and more_fragments: frag_value = frag_offset, pkt_data[l4_offset:] fragment_holder[frag_key] = [frag_value] continue # The last part of a fragment elif frag_offset and (not more_fragments): frag_value = frag_offset, pkt_data[l4_offset:] fragment_holder[frag_key].append(frag_value) frag_parts = sorted(fragment_holder[frag_key]) assembled = b''.join(x[1] for x in frag_parts) del fragment_holder[frag_key] # The middle of a fragment elif frag_offset and more_fragments: frag_value = frag_offset, pkt_data[l4_offset:] fragment_holder[frag_key].append(frag_value) continue tcp_flags = 0 # TCP if protocol == 0x06: l4_data = tcp_header.unpack_from(pkt_data, l4_offset) flag_data = l4_data[4] tcp_flags = ((flag_data[0] & 0x01) << 8) ^ flag_data[1] # UDP elif protocol == 0x11: l4_data = udp_header.unpack_from(pkt_data, l4_offset) # ICMP or ICMPv6 elif (protocol == 0x01) or (protocol == 0x3a): l4_data = icmp_header.unpack_from(pkt_data, l4_offset) else: print('Unrecognized L4 header {}'.format(protocol)) continue src_ip = ip_data[-2] dst_ip = ip_data[-1] src_port = l4_data[0] dst_port = l4_data[1] time_key = (seconds // 10) * 10 flow_key = ( inet_ntop(address_family, src_ip), inet_ntop(address_family, dst_ip), src_port, dst_port, protocol, ) flow_stats[time_key][flow_key].update(seconds, packet_length, tcp_flags) # print(*flow_key, sep='\t') packet_count += 1 print('Reader loop completed. Read {} packets'.format(packet_count))
def rawHandler(self, pktlen, pkt, ts, **kwargs): '''takes ethernet data and determines if it contains IP or IP6. defragments IPv4 if 6to4, unencaps the IPv6 If IP/IP6, hands off to IPDecoder via IPHandler()''' try: # if this is an IPv4 packet, defragment, decode and hand it off if type(pkt.data) == dpkt.ip.IP: if self.defrag: # return packet if whole, None if more frags needed pkt = self.ipdefrag(pkt.data) else: pkt = pkt.data # get the layer 3 packet if pkt: # do we have a whole IP packet? if self.decode6to4 and pkt.p == dpkt.ip.IP_PROTO_IP6: pass # fall thru to ip6 decode elif not self.v6only: # if we are decoding ip4 sip, dip = socket.inet_ntoa(pkt.src), socket.inet_ntoa( pkt.dst) # try to decode ports try: sport, dport = pkt.data.sport, pkt.data.dport except: # no ports in this layer-4 protocol sport, dport = None, None # generate int forms of src/dest ips sipint, dipint = struct.unpack( '!L', pkt.src)[0], struct.unpack('!L', pkt.dst)[0] # call IPHandler with extra data self.IPHandler( ((sip, sport), (dip, dport)), pkt, ts, pkttype=dpkt.ethernet.ETH_TYPE_IP, proto=self.IP_PROTO_MAP.get(pkt.p, pkt.p), sipint=sipint, dipint=dipint, **kwargs) if pkt and type(pkt.data) == dpkt.ip6.IP6: pkt = pkt.data # no defrag of ipv6 # decode ipv6 addresses sip, dip = socket.inet_ntop(socket.AF_INET6, pkt.src), socket.inet_ntop( socket.AF_INET6, pkt.dst) # try to get layer-4 ports try: sport, dport = pkt.data.sport, pkt.data.dport except: sport, dport = None, None # generate int forms of src/dest ips h, l = struct.unpack("!QQ", pkt.src) sipint = ((h << 64) | l) h, l = struct.unpack("!QQ", pkt.dst) dipint = ((h << 64) | l) # call ipv6 handler self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, pkttype=dpkt.ethernet.ETH_TYPE_IP6, proto=self.IP_PROTO_MAP.get(pkt.nxt, pkt.nxt), sipint=sipint, dipint=dipint, **kwargs) except Exception, e: self._exc(e)
def sprint_addr(addr): ''' binary ip addr -> string ''' family = socket.AF_INET if len(addr) == 4 else socket.AF_INET6 return socket.inet_ntop(family, addr)
def run(self): """Process PCAP. @return: dict with network analysis data. """ try: file = open(self.filepath, "rb") except (IOError, OSError): log.error("Unable to open %s" % self.filepath) return self.results try: pcap = dpkt.pcap.Reader(file) except dpkt.dpkt.NeedData: log.error("Unable to read PCAP file at path \"%s\".", self.filepath) return self.results except ValueError: log.error("Unable to read PCAP file at path \"%s\". File is " "corrupted or wrong format." % self.filepath) return self.results offset = file.tell() first_ts = None for ts, buf in pcap: if not first_ts: first_ts = ts try: ip = iplayer_from_raw(buf, pcap.datalink()) connection = {} if isinstance(ip, dpkt.ip.IP): connection["src"] = socket.inet_ntoa(ip.src) connection["dst"] = socket.inet_ntoa(ip.dst) elif isinstance(ip, dpkt.ip6.IP6): connection["src"] = socket.inet_ntop(socket.AF_INET6, ip.src) connection["dst"] = socket.inet_ntop(socket.AF_INET6, ip.dst) else: offset = file.tell() continue self._add_hosts(connection) if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data if not isinstance(tcp, dpkt.tcp.TCP): tcp = dpkt.tcp.TCP(tcp) if tcp.data: connection["sport"] = tcp.sport connection["dport"] = tcp.dport self._tcp_dissect(connection, tcp.data) src, sport, dst, dport = (connection["src"], connection["sport"], connection["dst"], connection["dport"]) if not ((dst, dport, src, sport) in self.tcp_connections_seen or (src, sport, dst, dport) in self.tcp_connections_seen): self.tcp_connections.append((src, sport, dst, dport, offset, ts-first_ts)) self.tcp_connections_seen.add((src, sport, dst, dport)) self.alive_hosts[dst, dport] = True else: ipconn = ( connection["src"], tcp.sport, connection["dst"], tcp.dport, ) seqack = self.tcp_connections_dead.get(ipconn) if seqack == (tcp.seq, tcp.ack): host = connection["dst"], tcp.dport self.dead_hosts[host] = self.dead_hosts.get(host, 1) + 1 self.tcp_connections_dead[ipconn] = tcp.seq, tcp.ack elif ip.p == dpkt.ip.IP_PROTO_UDP: udp = ip.data if not isinstance(udp, dpkt.udp.UDP): udp = dpkt.udp.UDP(udp) if len(udp.data) > 0: connection["sport"] = udp.sport connection["dport"] = udp.dport self._udp_dissect(connection, udp.data) src, sport, dst, dport = (connection["src"], connection["sport"], connection["dst"], connection["dport"]) if "10.152.152" in src and "10.152.152" in dst: pass elif not ((dst, dport, src, sport) in self.udp_connections_seen or (src, sport, dst, dport) in self.udp_connections_seen): self.udp_connections.append((src, sport, dst, dport, offset, ts-first_ts)) self.udp_connections_seen.add((src, sport, dst, dport)) elif ip.p == dpkt.ip.IP_PROTO_ICMP: icmp = ip.data if not isinstance(icmp, dpkt.icmp.ICMP): icmp = dpkt.icmp.ICMP(icmp) self._icmp_dissect(connection, icmp) offset = file.tell() except AttributeError: continue except dpkt.dpkt.NeedData: continue except Exception as e: log.exception("Failed to process packet: %s", e) file.close() # Post processors for reconstructed flows. self._process_smtp() # Process countries based on final data self._get_country() # Build results dict. self.results["hosts"] = self.unique_hosts self.results["domains"] = self.unique_domains self.results["tcp"] = [conn_from_flowtuple(i) for i in self.tcp_connections] self.results["udp"] = [conn_from_flowtuple(i) for i in self.udp_connections] self.results["icmp"] = self.icmp_requests self.results["http"] = self.http_requests.values() self.results["tls"] = self.tls_keys self.results["dns"] = self.dns_requests.values() self.results["smtp"] = self.smtp_requests self.results["irc"] = self.irc_requests self.results["countries"] = self.country_list self.results["country_percents"] = self.country_percent self.results["dead_hosts"] = [] # Report each IP/port combination as a dead host if we've had to retry # at least 3 times to connect to it and if no successful connections # were detected throughout the analysis. for (ip, port), count in self.dead_hosts.items(): if count < 3 or (ip, port) in self.alive_hosts: continue # Report once. if (ip, port) not in self.results["dead_hosts"]: self.results["dead_hosts"].append((ip, port)) return self.results
def fmt_ipv6_addr(v): """Given a 128-bit integer representing an ipv6 address, return a string for that ipv6 address.""" return socket.inet_ntop(socket.AF_INET6, binascii.unhexlify("%032x" % v))
def __repr__(self): return socket.inet_ntop(socket.AF_INET6, self._vs_value)
def pretty(self, attr): if attr == "src" or attr == "dst": return inet_ntop(AF_INET, struct.pack('!L', getattr(self, attr)))
def reprIPv6Addr(addr): return socket.inet_ntop(socket.AF_INET6, addr)
def _add_dns(self, conn, udpdata): """Adds a DNS data flow. @param udpdata: UDP data flow. """ dns = dpkt.dns.DNS(udpdata) # DNS query parsing. query = {} # Temporary list for found A or AAAA responses. _ip = [] if dns.rcode == dpkt.dns.DNS_RCODE_NOERR or \ dns.qr == dpkt.dns.DNS_R or \ dns.opcode == dpkt.dns.DNS_QUERY or True: # DNS question. try: q_name = dns.qd[0].name q_type = dns.qd[0].type except IndexError: return False # DNS RR type mapping. # See: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 # See: https://github.com/kbandla/dpkt/blob/master/dpkt/dns.py#L42 query["request"] = q_name if q_type == dpkt.dns.DNS_A: query["type"] = "A" elif q_type == dpkt.dns.DNS_AAAA: query["type"] = "AAAA" elif q_type == dpkt.dns.DNS_CNAME: query["type"] = "CNAME" elif q_type == dpkt.dns.DNS_MX: query["type"] = "MX" elif q_type == dpkt.dns.DNS_PTR: query["type"] = "PTR" elif q_type == dpkt.dns.DNS_NS: query["type"] = "NS" elif q_type == dpkt.dns.DNS_SOA: query["type"] = "SOA" elif q_type == dpkt.dns.DNS_HINFO: query["type"] = "HINFO" elif q_type == dpkt.dns.DNS_TXT: query["type"] = "TXT" elif q_type == dpkt.dns.DNS_SRV: query["type"] = "SRV" elif q_type == dpkt.dns.DNS_ANY: # For example MDNS requests have q_type=255. query["type"] = "All" else: # Some requests are not parsed by dpkt. query["type"] = "None" # DNS answer. query["answers"] = [] for answer in dns.an: ans = {} if answer.type == dpkt.dns.DNS_A: ans["type"] = "A" try: ans["data"] = socket.inet_ntoa(answer.rdata) _ip.append(ans["data"]) except socket.error: continue elif answer.type == dpkt.dns.DNS_AAAA: ans["type"] = "AAAA" try: ans["data"] = socket.inet_ntop(socket.AF_INET6, answer.rdata) _ip.append(ans["data"]) except (socket.error, ValueError): continue elif answer.type == dpkt.dns.DNS_CNAME: ans["type"] = "CNAME" ans["data"] = answer.cname elif answer.type == dpkt.dns.DNS_MX: ans["type"] = "MX" ans["data"] = answer.mxname elif answer.type == dpkt.dns.DNS_PTR: ans["type"] = "PTR" ans["data"] = answer.ptrname elif answer.type == dpkt.dns.DNS_NS: ans["type"] = "NS" ans["data"] = answer.nsname elif answer.type == dpkt.dns.DNS_SOA: ans["type"] = "SOA" ans["data"] = ",".join([answer.mname, answer.rname, str(answer.serial), str(answer.refresh), str(answer.retry), str(answer.expire), str(answer.minimum)]) elif answer.type == dpkt.dns.DNS_HINFO: ans["type"] = "HINFO" ans["data"] = " ".join(answer.text) elif answer.type == dpkt.dns.DNS_TXT: ans["type"] = "TXT" ans["data"] = " ".join(answer.text) # TODO: add srv handling query["answers"].append(ans) if self._is_whitelisted(conn, q_name): log.debug("DNS target {0} whitelisted. Skipping ...".format(q_name)) self.whitelist_ips = self.whitelist_ips + _ip return True self._add_domain(query["request"]) reqtuple = query["type"], query["request"] if reqtuple not in self.dns_requests: self.dns_requests[reqtuple] = query else: new_answers = set((i["type"], i["data"]) for i in query["answers"]) - self.dns_answers self.dns_requests[reqtuple]["answers"] += [dict(type=i[0], data=i[1]) for i in new_answers] return True
def __str__(self): return '[%s]:%d' % (socket.inet_ntop(self.sin6_family, ''.join( map(chr, self.sin6_addr))), socket.ntohs(self.sin6_port))
def __repr__(self): bytes = struct.pack('>I', self._vs_value) return socket.inet_ntop(socket.AF_INET, bytes)