Last active
April 10, 2022 21:00
-
-
Save cmsj/e03b6d28325ce5c3d5b255256278a330 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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