def fw_events(file, filter_ip, filter_type, clients_dir, limit): """Format firewall drop events with dedup and counts""" import glob proto_map = {1: 'icmp', 6: 'tcp', 17: 'udp'} ip_to_name = {} for conf in glob.glob(f"{clients_dir}/*.conf"): name = os.path.basename(conf).replace('.conf', '') try: with open(conf) as f: for line in f: if line.startswith('Address'): ip = line.split('=')[1].strip().split('/')[0] ip_to_name[ip] = name except: pass events = [] last_seen = {} try: with open(file) as f: for line in f: try: e = json.loads(line.strip()) src = e.get('src_ip', '') if not src: continue if filter_ip and src != filter_ip: continue dst = e.get('dest_ip', '') port = e.get('dest_port', '') proto = e.get('ip.protocol', 0) key = (src, dst, port, proto) ts_str = e.get('timestamp', '') try: from datetime import datetime ts = datetime.fromisoformat(ts_str).timestamp() except: ts = 0 windows = {1: 5, 6: 30, 17: 10} window = windows.get(proto, 10) if key in last_seen and (ts - last_seen[key]) < window: continue last_seen[key] = ts events.append(e) except: pass except: pass # Dedup consecutive same src+dst+port within 60s with count deduped = [] counts = [] for e in events: ts_str = e.get('timestamp', '') try: from datetime import datetime ts = datetime.fromisoformat(ts_str).timestamp() except: ts = 0 src = e.get('src_ip', '') dst = e.get('dest_ip', '') port = e.get('dest_port', '') proto = e.get('ip.protocol', 0) key = (src, dst, port, proto) if deduped and counts: prev = deduped[-1] try: prev_ts = datetime.fromisoformat(prev.get('timestamp','')).timestamp() except: prev_ts = 0 prev_key = (prev.get('src_ip',''), prev.get('dest_ip',''), prev.get('dest_port',''), prev.get('ip.protocol',0)) if key == prev_key and (ts - prev_ts) < 60: counts[-1] += 1 continue deduped.append(e) counts.append(1) grouped = [] group_counts = [] for e in deduped: ts_str = e.get('timestamp', '') try: from datetime import datetime dt = datetime.fromisoformat(ts_str) # Truncate to minute for grouping minute_key = dt.strftime('%Y-%m-%d %H:%M') except: minute_key = ts_str[:16] src = e.get('src_ip', '') dst = e.get('dest_ip', '') port = e.get('dest_port', '') proto = e.get('ip.protocol', 0) key = (minute_key, src, dst, proto) # group within same minute if grouped and group_counts: prev = grouped[-1] try: prev_dt = datetime.fromisoformat(prev.get('timestamp','')) prev_minute = prev_dt.strftime('%Y-%m-%d %H:%M') except: prev_minute = '' prev_key = (prev_minute, prev.get('src_ip',''), prev.get('dest_ip',''), prev.get('ip.protocol',0)) if key == prev_key: group_counts[-1] += 1 continue grouped.append(e) group_counts.append(1) for e, count in zip(deduped[-int(limit):], counts[-int(limit):]): ts = e.get('timestamp', '') try: from datetime import datetime dt = datetime.fromisoformat(ts) ts = dt.strftime(DATETIME_FMT) except: pass src = e.get('src_ip', '—') dst = e.get('dest_ip', '—') port = e.get('dest_port', '') proto_num = e.get('ip.protocol', 0) proto = proto_map.get(proto_num, str(proto_num)) dst_str = f"{dst}:{port}" if port else dst client = ip_to_name.get(src, src) if filter_type and not client.startswith(filter_type + '-'): continue count_str = f" (x{count})" if count > 1 else "" print(f"{ts}|{client}|{dst_str}|{proto}{count_str}")