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