Skip to content

Instantly share code, notes, and snippets.

@cmsj
Last active April 10, 2022 21:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmsj/e03b6d28325ce5c3d5b255256278a330 to your computer and use it in GitHub Desktop.
Save cmsj/e03b6d28325ce5c3d5b255256278a330 to your computer and use it in GitHub Desktop.
#!/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