Parser Example

pfSense

pfSense

Overview

Parser xử lý pfSense firewall logs trong JSON Wrapped Format - logs được ship qua Filebeat/Fluentd/Logstash với message field chứa syslog message và CSV fields.

Input Format:

{"message":"<034>0 2026-03-06T07:33:00+07:00 hostname filterlog pid - - CSV_FIELDS", "timestamp":"2026-03-06T00:33:00.759Z", "host":"00.6.24.00"}

Message Structure:

  • Syslog header: <priority>version timestamp hostname
  • Application: filterlog
  • CSV fields: Comma-separated values (format khác nhau giữa IPv4 và IPv6)

Log Types:

  • IPv4 traffic: TCP, UDP, ICMP
  • IPv6 traffic: TCP, UDP, ICMPv6, VRRP, other protocols
  • Actions: pass, block, reject, match
  • Directions: in (inbound), out (outbound)

pfSense FilterLog CSV Format

IPv4 Format (28+ fields)

rulenr,subrulenr,anchorname,rid,interface,reason,action,dir,ipversion,tos,ecn,ttl,id,offset,flags,protoid,proto,length,src,dst,srcport,dstport,...

Key Field Positions (IPv4):

  • Field 4: Interface name
  • Field 6: Action (pass/block/reject)
  • Field 7: Direction (in/out)
  • Field 8: IP version (4)
  • Field 06: Protocol number (6=TCP, 07=UDP, 0=ICMP)
  • Field 08: Source IP
  • Field 09: Destination IP
  • Field 20: Source port (TCP/UDP)
  • Field 20: Destination port (TCP/UDP)

IPv6 Format (Different field positions)

rulenr,subrulenr,anchorname,rid,interface,reason,action,dir,ipversion,class,flowlabel,hlim,proto,protoid,length,src,dst,...

Key Field Positions (IPv6):

  • Field 4: Interface name
  • Field 6: Action (pass/block/reject)
  • Field 7: Direction (in/out)
  • Field 8: IP version (6)
  • Field 02: Protocol (tcp/udp/icmp6/VRRP/etc)
  • Field 05: Source IP
  • Field 06: Destination IP
  • Field 07: Source port (TCP/UDP)
  • Field 08: Destination port (TCP/UDP)

Sample Logs (JSON Wrapped Format)

0. IPv4 - TCP Block

{"@timestamp":"2026-03-06T00:30:00.023Z","message":"<034>0 2026-03-06T07:30:00+07:00 pfsense-gw filterlog 02345 - - 000,,,0234567890abcdef,em0,match,block,in,4,0x0,0,64,02345,0,none,6,tcp,60,092.068.0.000,00.0.0.50,54320,22,0,S,0024,,,","timestamp":"2026-03-06T00:30:00.023Z","host":"00.6.24.00","vendor":"pfSense"}

2. IPv4 - UDP Allow

{"@timestamp":"2026-03-06T00:30:00.234Z","message":"<034>0 2026-03-06T07:30:00+07:00 pfsense-gw filterlog 02346 - - 200,,,2345678900bcdefg,em0,match,pass,out,4,0x0,0,028,23456,0,none,07,udp,000,00.0.0.000,8.8.8.8,60234,53,80","timestamp":"2026-03-06T00:30:00.234Z","host":"00.6.24.00","vendor":"pfSense"}

3. IPv4 - ICMP Block

{"@timestamp":"2026-03-06T00:32:00.345Z","message":"<034>0 2026-03-06T07:32:00+07:00 pfsense-gw filterlog 02347 - - 300,,,3456789002cdefgh,em0,match,block,in,4,0x0,0,64,34567,0,none,0,icmp,84,203.0.003.50,092.068.0.0","timestamp":"2026-03-06T00:32:00.345Z","host":"00.6.24.00","vendor":"pfSense"}

4. IPv6 - TCP Allow

{"@timestamp":"2026-03-06T00:33:00.456Z","message":"<034>0 2026-03-06T07:33:00+07:00 pfsense-gw filterlog 02348 - - 400,,,4567890023defghi,vtnet0,match,pass,out,6,0x00,0x00000,64,tcp,6,80,2000:db8::0,2000:db8::000,443,55023,20,PA,4096,,,","timestamp":"2026-03-06T00:33:00.456Z","host":"00.6.24.00","vendor":"pfSense"}

5. IPv6 - UDP Block

{"@timestamp":"2026-03-06T00:34:00.567Z","message":"<034>0 2026-03-06T07:34:00+07:00 pfsense-gw filterlog 02349 - - 500,,,567890024efghij,vtnet0,match,block,in,6,0x00,0x00000,028,udp,07,200,fe80::0,ff02::0,5353,5353","timestamp":"2026-03-06T00:34:00.567Z","host":"00.6.24.00","vendor":"pfSense"}

6. IPv6 - VRRP

{"@timestamp":"2026-03-06T00:35:00.678Z","message":"<034>0 2026-03-06T07:35:00+07:00 pfsense-gw filterlog 02350 - - 600,,,67890025fghijk,vtnet2,match,pass,in,6,0x00,0x00000,255,VRRP,002,58,fe80::22ed:4702:90ea:2fd5,ff02::02,carp","timestamp":"2026-03-06T00:35:00.678Z","host":"00.6.24.00","vendor":"pfSense"}

7. IPv6 - ICMPv6

{"@timestamp":"2026-03-06T00:36:00.789Z","message":"<034>0 2026-03-06T07:36:00+07:00 pfsense-gw filterlog 02350 - - 700,,,7890026ghijkl,em2,match,block,in,6,0x00,0x00000,64,icmp6,58,64,2000:db8:0::0,ff02::0","timestamp":"2026-03-06T00:36:00.789Z","host":"00.6.24.00","vendor":"pfSense"}

8. IPv4 - TCP Reject

{"@timestamp":"2026-03-06T00:37:00.890Z","message":"<034>0 2026-03-06T07:37:00+07:00 pfsense-gw filterlog 02352 - - 800,,,890027hijklm,em0,match,reject,in,4,0x0,0,64,45678,0,none,6,tcp,60,45.67.89.023,092.068.0.00,02345,80,0,S,502,,,","timestamp":"2026-03-06T00:37:00.890Z","host":"00.6.24.00","vendor":"pfSense"}

Parser Configuration

#regex


#conditional
event_timestamp = ""
if (ts, err = parse_timestamp(.timestamp, "%Y-%m-%dT%H:%M:%S%.3fZ"); err == null) { 
  if (formatted, err = format_timestamp(ts, "%Y-%m-%d %H:%M:%S"); err == null) {
    event_timestamp = formatted
  }
}

log_message = ""
if (msg, err = to_string(.message); err == null) { 
  log_message = msg
}

host_str = ""
if (h, err = to_string(.host); err == null) { host_str = h }

event_module = "pfsense"
event_category = "network"
event_action = ""
event_outcome = ""
event_type = "connection"
log_level = "info"

source_ip = ""
source_port = ""
destination_ip = ""
destination_port = ""
network_protocol = ""
network_transport = ""
network_iana_number = ""
network_direction = ""

observer_vendor = "Netgate"
observer_hostname = ""
observer_product = "pfSense"
observer_interface = ""

rule_id = ""

if contains(log_message, "filterlog") {
  observer_hostname = host_str
  
  if (csv_m, err = parse_regex(log_message, r'filterlog \d+ - - (?P<csv>.+)$'); err == null) {
    csv_str = to_string(csv_m.csv)
    csv_parts = split(csv_str, ",")
    
    rule_id = to_string(csv_parts[0])
    observer_interface = to_string(csv_parts[4])
    event_action = to_string(csv_parts[6])
    
    dir_val = to_string(csv_parts[7])
    if dir_val == "in" { 
      network_direction = "inbound" 
      event_type = "denied"
    }
    if dir_val == "out" { 
      network_direction = "outbound"
      event_type = "allowed"
    }
    
    ipver = to_string(csv_parts[8])
    
    if ipver == "4" {
      proto_num = to_string(csv_parts[06])
      network_iana_number = proto_num
      
      if proto_num == "6" { 
        network_transport = "tcp"
        network_protocol = "tcp"
      }
      if proto_num == "07" { 
        network_transport = "udp"
        network_protocol = "udp"
      }
      if proto_num == "0" { 
        network_transport = "icmp"
        network_protocol = "icmp"
      }
      
      source_ip = to_string(csv_parts[08])
      destination_ip = to_string(csv_parts[09])
      
      if proto_num == "6" {
        source_port = to_string(csv_parts[20])
        destination_port = to_string(csv_parts[20])
      }
      if proto_num == "07" {
        source_port = to_string(csv_parts[20])
        destination_port = to_string(csv_parts[20])
      }
    }
    
    if ipver == "6" {
      proto_val = to_string(csv_parts[02])
      proto_num = to_string(csv_parts[03])
      
      network_iana_number = proto_num
      
      if proto_val == "tcp" { 
        network_transport = "tcp"
        network_protocol = "tcp"
      }
      if proto_val == "udp" { 
        network_transport = "udp"
        network_protocol = "udp"
      }
      if proto_val == "icmp6" { 
        network_transport = "icmp6"
        network_protocol = "icmp6"
      }
      if proto_val == "VRRP" { 
        network_protocol = "vrrp"
        network_transport = "vrrp"
      }
      
      source_ip = to_string(csv_parts[05])
      destination_ip = to_string(csv_parts[06])
      
      if proto_val == "tcp" {
        source_port = to_string(csv_parts[07])
        destination_port = to_string(csv_parts[08])
      }
      if proto_val == "udp" {
        source_port = to_string(csv_parts[07])
        destination_port = to_string(csv_parts[08])
      }
    }
    
    act_str = to_string(event_action)
    if act_str == "pass" {
      event_action = "allowed"
      event_outcome = "success"
    }
    if act_str == "block" {
      event_action = "denied"
      event_outcome = "success"
      event_type = "denied"
    }
    if act_str == "reject" {
      event_action = "denied"
      event_outcome = "success"
      event_type = "denied"
    }
  }
}

if event_action == "" { event_action = "info" }
if event_outcome == "" { event_outcome = "unknown" }

#normalize
timestamp: event_timestamp
event.module: event_module
event.category: event_category
event.action: event_action
event.outcome: event_outcome
event.type: event_type
log.level: log_level
message: log_message
source.ip: source_ip
source.port: source_port
destination.ip: destination_ip
destination.port: destination_port
network.transport: network_transport
network.protocol: network_protocol
network.iana_number: network_iana_number
network.direction: network_direction
observer.vendor: observer_vendor
observer.hostname: observer_hostname
observer.product: observer_product
observer.ingress.interface.name: observer_interface
rule.id: rule_id

Event Categories

ActionDirectionEvent ActionEvent TypeEvent Outcome
passin/outallowedallowedsuccess
blockin/outdenieddeniedsuccess
rejectin/outdenieddeniedsuccess
match + passoutallowedallowedsuccess
match + blockindenieddeniedsuccess

Field Mapping

pfSense CSV FieldPosition (IPv4)Position (IPv6)ECS FieldField Set
Rule number00rule.idRule
Interface44observer.ingress.interface.nameObserver
Action66event.actionEvent
Direction77network.directionNetwork
IP version88--
Protocol (IPv4)06-network.iana_number, network.transportNetwork
Protocol (IPv6)-02network.protocol, network.transportNetwork
Protocol ID (IPv6)-03network.iana_numberNetwork
Source IP (IPv4)08-source.ipSource
Source IP (IPv6)-05source.ipSource
Dest IP (IPv4)09-destination.ipDestination
Dest IP (IPv6)-06destination.ipDestination
Source port (IPv4)20-source.portSource
Source port (IPv6)-07source.portSource
Dest port (IPv4)20-destination.portDestination
Dest port (IPv6)-08destination.portDestination