#!/usr/bin/env python3 | |
"""syslogreceiver.py - receive remote syslog events and pass them into | |
systemd's journal""" | |
import re | |
import socketserver | |
from systemd import journal | |
HOST, PORT = "0.0.0.0", 514 | |
LOG_FACILITY = { | |
0: 'kernel messages', | |
1: 'user-level messages', | |
2: 'mail system', | |
3: 'system daemons', | |
4: 'security/authorization messages', | |
5: 'messages generated internally by syslogd', | |
6: 'line printer subsystem', | |
7: 'network news subsystem', | |
8: 'UUCP subsystem', | |
9: 'clock daemon', | |
10: 'security/authorization messages', | |
11: 'FTP daemon', | |
12: 'NTP subsystem', | |
13: 'log audit', | |
14: 'log alert', | |
15: 'clock daemon', | |
16: 'local use 0 (local0)', | |
17: 'local use 1 (local1)', | |
18: 'local use 2 (local2)', | |
19: 'local use 3 (local3)', | |
20: 'local use 4 (local4)', | |
21: 'local use 5 (local5)', | |
22: 'local use 6 (local6)', | |
23: 'local use 7 (local7)' | |
} | |
LOG_LEVEL = { | |
0: 'Emergency', | |
1: 'Alert', | |
2: 'Critical', | |
3: 'Error', | |
4: 'Warning', | |
5: 'Notice', | |
6: 'Informational', | |
7: 'Debug' | |
} | |
def split_message(msg): | |
''' | |
https://www.fir3net.com/UNIX/Linux/how-to-determine-the-syslog-facility- | |
using-tcpdump.html | |
Each Syslog message contains a priority value. The priority value is | |
enclosed within the characters < >. The priority value can be | |
between 0 and 191 and consists of a Facility value and a Level value. | |
Facility being the type of message, such as a kernel or mail message. | |
And level being a severity level of the message. | |
To calculate the priority value the following formula is used : | |
Priority = Facility * 8 + Level | |
So to determine the facility value of a syslog message we divide the | |
priority value by 8. The remainder is the level value. | |
''' | |
match = re.search( | |
r"\b(\d*)>(\w*\s+\d+\s+\d\d:\d\d:\d\d)\s+([^ ]*?) (.*)", | |
msg, re.MULTILINE) | |
if match: | |
result = match.group(1) | |
return int(result), \ | |
str(match.group(2)), \ | |
str(match.group(3)), \ | |
str(match.group(4)) | |
else: | |
print("Failed to match against: %s" % msg) | |
raise | |
def get_facility_from_priority(priority): | |
"""Convert the priority to a facility""" | |
return priority//8 | |
def get_level_from_priority(priority): | |
"""Convert the priority to a level""" | |
return priority % 8 | |
class SyslogUDPHandler(socketserver.BaseRequestHandler): | |
"""Handler for the Syslog UDP packets""" | |
def handle(self): | |
data = bytes.decode(self.request[0].strip()) | |
syslog_message = str(data) | |
priority, _, host, text = split_message(syslog_message) | |
facility = get_facility_from_priority(priority) | |
lvl = get_level_from_priority(priority) | |
data = dict() | |
data['SYSLOG_FACILITY'] = str(facility) | |
data['SYSLOG_IDENTIFIER'] = str(host) | |
data['PRIORITY'] = str(lvl) | |
journal.send(text, **data) | |
if __name__ == "__main__": | |
try: | |
SERVER = socketserver.UDPServer((HOST, PORT), SyslogUDPHandler) | |
SERVER.serve_forever(poll_interval=0.1) | |
except (IOError, SystemExit): | |
raise | |
except KeyboardInterrupt: | |
print("Crtl+C Pressed. Shutting down.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment