7b8456b24f56b667ae10cbddfce6b75c6410cc5d
   1#
   2#   ufw_journald.py
   3#   
   4#   Get details about packets blocked by ufw (uses journald)
   5#
   6
   7import datetime
   8import re
   9from systemd import journal
  10
  11from logparse import config
  12from logparse.formatting import *
  13from logparse.load_parsers import Parser
  14from logparse.util import resolve
  15
  16PROTOCOLS = ["TCP", "UDP", "UDP-Lite", "ICMP", "ICMPv6", "AH", "SCTP", "MH"]
  17
  18class Packet():
  19
  20    def __init__(self, msg):
  21        try:
  22            self.inif, self.outif, self.mac, self.src, self.dst, self.len, self.proto, self.spt, self.dpt = re.search(r"IN=(?P<inif>\w*).*OUT=(?P<outif>\w*).*MAC=(?P<mac>\S*).*SRC=(?P<src>\S*).*DST=(?P<dst>\S*).*LEN=(?P<length>\d*).*PROTO=(?P<proto>\S*)(?:\sSPT=(?P<spt>\d*))?(?:\sDPT=(?P<dpt>\d*))?", msg).groupdict().values()
  23            if self.proto and self.proto.isdigit():
  24                self.proto = PROTOCOLS[int(self.proto)-1]
  25        except Exception as e:
  26            logger.warning("Malformed packet log: {0}. Error message: {1}".format(msg, str(e)))
  27            return None
  28
  29class UfwJournald(Parser):
  30
  31    def __init__(self):
  32        super().__init__()
  33        self.name = "ufw_journald"
  34        self.info = "Get details about packets blocked by ufw"
  35
  36    def parse_log(self):
  37
  38        logger.debug("Starting ufw section")
  39        section = Section("ufw")
  40
  41        j = journal.Reader()
  42        j.this_machine()
  43        j.add_match(_TRANSPORT='kernel')
  44        j.add_match(PRIORITY=4)
  45        j.seek_realtime(section.period.startdate)
  46        
  47        logger.debug("Searching for messages")
  48
  49        blocked_packets = [Packet(entry["MESSAGE"]) for entry in j if "MESSAGE" in entry and "UFW BLOCK" in entry["MESSAGE"]]
  50
  51        logger.debug("Parsing messages")
  52
  53        inbound_interfaces = []
  54        outbound_interfaces = []
  55        n_inbound = n_outbond = 0
  56        src_ips = []
  57        dst_ips = []
  58        src_ports = []
  59        dst_ports = []
  60        protocols = {'UDP': 0, 'TCP': 0}
  61        src_macs = []
  62
  63        for pkt in blocked_packets:
  64            if pkt.inif:
  65                inbound_interfaces.append(pkt.inif)
  66            elif pkt.outif:
  67                outbound_interfaces.append(pkt.outif)
  68            if pkt.src: src_ips.append(resolve(pkt.src, config.prefs.get("ufw", "ufw-resolve-domains")))
  69            if pkt.dst: dst_ips.append(resolve(pkt.dst, config.prefs.get("ufw", "ufw-resolve-domains")))
  70            if pkt.spt: src_ports.append(pkt.spt)
  71            if pkt.dpt: dst_ports.append(pkt.dpt)
  72            if pkt.proto: protocols[pkt.proto] += 1
  73                
  74        section.append_data(Data(subtitle="{} blocked ({} UDP, {} TCP)".format(plural("packet", len(blocked_packets)), protocols['UDP'], protocols['TCP'])))
  75
  76        src_port_data = Data(items=src_ports)
  77        src_port_data.orderbyfreq()
  78        src_port_data.subtitle = plural("source port", len(src_port_data.items))
  79        src_port_data.truncl(config.prefs.getint("logparse", "maxlist"))
  80        section.append_data(src_port_data)
  81
  82        dst_port_data= Data(items=dst_ports)
  83        dst_port_data.orderbyfreq()
  84        dst_port_data.subtitle = plural("destination port", len(dst_port_data.items))
  85        dst_port_data.truncl(config.prefs.getint("logparse", "maxlist"))
  86        section.append_data(dst_port_data)
  87
  88        src_ips_data= Data(items=src_ips)
  89        src_ips_data.orderbyfreq()
  90        src_ips_data.subtitle = plural("source IP", len(src_ips_data.items))
  91        src_ips_data.truncl(config.prefs.getint("logparse", "maxlist"))
  92        section.append_data(src_ips_data)
  93
  94        dst_ips_data= Data(items=dst_ips)
  95        dst_ips_data.orderbyfreq()
  96        dst_ips_data.subtitle = plural("destination IP", len(dst_ips_data.items))
  97        dst_ips_data.truncl(config.prefs.getint("logparse", "maxlist"))
  98        section.append_data(dst_ips_data)
  99
 100        logger.info("Finished ufw section")
 101        return section