feat: SSH log relay emits proper DECNET syslog for sshd events

New log_relay.py replaces raw 'cat' on the rsyslog pipe. Intercepts
sshd and bash lines and re-emits them as structured RFC 5424 events:
login_success, session_opened, disconnect, connection_closed, command.
Parsers updated to accept non-nil PROCID (sshd uses PID).
This commit is contained in:
2026-04-14 02:07:35 -04:00
parent a6c7cfdf66
commit 7ff5703250
8 changed files with 240 additions and 79 deletions

View File

@@ -24,7 +24,7 @@ _RFC5424_RE = re.compile(
r"(\S+) " # 1: TIMESTAMP
r"(\S+) " # 2: HOSTNAME (decky name)
r"(\S+) " # 3: APP-NAME (service)
r"- " # PROCID always NILVALUE
r"\S+ " # PROCID (NILVALUE or PID)
r"(\S+) " # 4: MSGID (event_type)
r"(.+)$", # 5: SD element + optional MSG
)
@@ -32,8 +32,6 @@ _SD_BLOCK_RE = re.compile(r'\[decnet@55555\s+(.*?)\]', re.DOTALL)
_PARAM_RE = re.compile(r'(\w+)="((?:[^"\\]|\\.)*)"')
_IP_FIELDS = ("src_ip", "src", "client_ip", "remote_ip", "ip")
# bash PROMPT_COMMAND logger output: "CMD uid=0 pwd=/root cmd=ls -lah"
_BASH_CMD_RE = re.compile(r"CMD\s+uid=(\S+)\s+pwd=(\S+)\s+cmd=(.*)")
@@ -74,16 +72,6 @@ def parse_rfc5424(line: str) -> Optional[dict[str, Any]]:
except ValueError:
ts_formatted = ts_raw
# Normalize bash CMD lines from SSH honeypot PROMPT_COMMAND logger
if service == "bash" and msg:
cmd_match = _BASH_CMD_RE.match(msg)
if cmd_match:
service = "ssh"
event_type = "command"
fields["uid"] = cmd_match.group(1)
fields["pwd"] = cmd_match.group(2)
fields["command"] = cmd_match.group(3)
return {
"timestamp": ts_formatted,
"decky": decky,

View File

@@ -26,7 +26,7 @@ _RFC5424_RE = re.compile(
r"(\S+) " # 1: TIMESTAMP
r"(\S+) " # 2: HOSTNAME (decky name)
r"(\S+) " # 3: APP-NAME (service)
r"- " # PROCID always NILVALUE
r"\S+ " # PROCID (NILVALUE or PID)
r"(\S+) " # 4: MSGID (event_type)
r"(.+)$", # 5: SD element + optional MSG
)
@@ -40,8 +40,6 @@ _PARAM_RE = re.compile(r'(\w+)="((?:[^"\\]|\\.)*)"')
# Field names to probe for attacker IP, in priority order
_IP_FIELDS = ("src_ip", "src", "client_ip", "remote_ip", "ip")
# bash PROMPT_COMMAND logger output: "CMD uid=0 pwd=/root cmd=ls -lah"
_BASH_CMD_RE = re.compile(r"CMD\s+uid=(\S+)\s+pwd=(\S+)\s+cmd=(.*)")
@dataclass
@@ -103,18 +101,6 @@ def parse_line(line: str) -> LogEvent | None:
fields = _parse_sd_params(sd_rest)
# Normalize bash CMD lines from SSH honeypot PROMPT_COMMAND logger
if service == "bash":
# Free-text MSG follows the SD element (which is "-" for these lines)
msg = sd_rest.lstrip("- ").strip()
cmd_match = _BASH_CMD_RE.match(msg)
if cmd_match:
service = "ssh"
event_type = "command"
fields["uid"] = cmd_match.group(1)
fields["pwd"] = cmd_match.group(2)
fields["command"] = cmd_match.group(3)
attacker_ip = _extract_attacker_ip(fields)
return LogEvent(