Parsing and enrichment
Vector receives syslog over TLS and runs a short program for each line. pf lines are taken apart with one regular expression; SSH logins are recognised and classified; addresses get names.
What gets added#
- The rule's name, from the label the firewall appends.
- Network names for each interface, so a dashboard says "Trusted Wi-Fi", not
vlan10. - Device names for internal addresses, from a CSV lookup table; an unknown internal address is named
unknown, which makes strangers easy to spot. - Country and network owner for traffic from the internet, from GeoIP databases inside OpenSearch.
- SSH logins on the firewall, as success or failure with user, source and the key's fingerprint.
- The web server's requests, which arrive as JSON: status, path, user agent and TLS version, and the country and network owner of every visitor. Its SSH logins and
sudocommands are recognised the same way.
In the configuration#
p, err = parse_regex(.message,
r'rule (?P<rule>\d+)/\((?P<reason>[^)]+)\) (?P<action>pass|block) (?P<dir>in|out) on (?P<iface>\S+): (?P<src_ip>[\d.]+)\.?(?P<src_port>\d+)? > (?P<dst_ip>[\d.]+)\.?(?P<dst_port>\d+)?:')
if err == null {
.event.action = p.action
.source.ip = p.src_ip
.destination.ip = p.dst_ip
host, e = get_enrichment_table_record("hosts", {"ip": .source.ip})
if e == null { .source.hostname = host.hostname }
}- Errors are values in VRL, so a line that does not match is kept and tagged instead of being dropped.