Until now I hadn’t used the options and features rsyslog comes with. Let me show a simple example I have done today. This is an example log line rsyslog has received from iptables (I have configured iptables to log certain connections attempts to identify and save devices with malware):

Sep 29 15:30:39 myserver kernel: [malware3] IN=ens192 OUT=ens192 MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX SRC=10.15.13.17 DST=194.25.72.92 LEN=60 TOS=0x10 PREC=0x00 TTL=62 ID=6620 DF PROTO=TCP SPT=55082 DPT=9085 WINDOW=64240 RES=0x00 SYN URGP=0

The string [malware3] is the prefix I have configured iptables to add. There is a lenght limitation so I couldn’t set the real full malware name. But I delegated that work to rsyslog. I wanted to replace that string by using the replace function:

https://www.rsyslog.com/doc/v8-stable/rainerscript/functions/rs-replace.html

But no way to make it work. Thanks I found a better function for my purposes.
This is result, the finally parsed and logged syslog message that replaces the one sent by iptables (I only needed those fields among all of them):

2020-09-29 15:30:39 malware=(PotentiallyDangerous)VirusXYZ source=10.225.223.137 destination=199.21.76.91 dstport=TCP/9085

And this the rsyslog configuration I added in /etc/rsyslog.d/iptables.conf:

if ($msg contains "[malware3]") then
{
  set $!malware = "(PotentiallyDangerous)VirusXYZ";
  set $!clientip = field($msg,32,4);
  set $!clientip = field($!clientip,61,2);
  set $!dstip = field($msg,32,5);
  set $!dstip = field($!dstip,61,2);
  set $!protocol = field($msg,32,12);
  set $!protocol = field($!protocol,61,2);
  set $!dstport = field($msg,32,14);
  set $!dstport = field($!dstport,61,2);
  $template iptables_log, "%$year%-%$month%-%$day% %timegenerated:12:19:date-rfc3339% malware=%$!malware% source=%$!clientip% destination=%$!dstip% dstport=%$!protocol%/%$!dstport%\n"
  /var/log/iptables_malware.log;iptables_log
  @anothersyslogserver:514;iptables_log
  stop
}

First of all, the condition that makes this parsing and logging be executed in case [malware3] is found in the received message.

if ($msg contains "[malware3]") then

Set the malware name variable name

set $!malware = "(PotentiallyDangerous)VirusXYZ";

Split fields.
2nd parameter = ascii code of the separator character.
3rd paramter = value position

set $!clientip = field($msg,32,4);
set $!clientip = field($!clientip,61,2);

Customized format of the syslog message (also changed the date format)

$template iptables_log, "%$year%-%$month%-%$day% %timegenerated:12:19:date-rfc3339% malware=%$!malware% source=%$!clientip% destination=%$!dstip% dstport=%$!protocol%/%$!dstport%\n"

Log to file using the template

/var/log/iptables_malware.log;iptables_log

Log to remote syslog server using the template

@anothersyslogserver:514;iptables_log