Skip to content

Instantly share code, notes, and snippets.

@dstreefkerk
Last active September 12, 2025 00:10
Show Gist options
  • Save dstreefkerk/24d120459df9029e3c82fb40dbf9ac6c to your computer and use it in GitHub Desktop.
Save dstreefkerk/24d120459df9029e3c82fb40dbf9ac6c to your computer and use it in GitHub Desktop.
#####################################################################
# FortiAnalyzer CEF Integration - Syslog-ng Configuration
#####################################################################
# Equivalent to the rsyslog configuration for FortiAnalyzer CEF forwarding
# to Microsoft Sentinel via Azure Monitor Agent
#
# PROBLEM:
# --------
# FortiAnalyzer sends CEF messages in partial syslog format:
# SENDS: "MMM dd HH:mm:ss hostname CEF:0|..."
# EXPECTED: "<164>MMM dd HH:mm:ss hostname CEF:0|..."
#
# Azure Monitor Agent (AMA) strictly requires RFC3164/RFC5424 compliant
# syslog messages with PRI headers and will reject headerless messages entirely.
#
# SOLUTION:
# ---------
# - Receives CEF messages from FortiAnalyzer on TCP port 1514
# - Adds mandatory syslog PRI header <164> (local4.warning) for AMA compliance
# - Forwards ALL UTM logs to ensure complete security visibility
# - No severity-based filtering to prevent missing critical security events
#
# DEPLOYMENT:
# -----------
# 1. Save this file as /etc/syslog-ng/conf.d/40-fortianalyzer-cef.conf
# 2. Test configuration: sudo syslog-ng -s
# 3. Reload syslog-ng: sudo systemctl reload syslog-ng
# 4. Verify port listening: sudo netstat -tlnp | grep 1514
# 5. Configure FortiAnalyzer to forward CEF logs to this server:1514
# - Enable "Reliable Connection" for TCP mode (recommended)
# 6. Ensure Azure Monitor Agent is configured with appropriate DCR
# 7. DCR should be configured for LOG_LOCAL4:LOG_WARNING
#####################################################################
# Source: TCP input on port 1514 (Recommended - reliable delivery)
source s_forti_tcp {
network(
port(1514)
transport("tcp")
flags(no-parse) # Keep raw message intact
);
};
# Source: UDP input on port 1514 (Optional - uncomment if needed)
# Note: UDP is best-effort delivery and may lose logs under heavy load
# source s_forti_udp {
# network(
# port(1514)
# transport("udp")
# flags(no-parse) # Keep raw message intact
# );
# };
# Template: Force PRI header addition for AMA compliance
# Adds <164> which is local4.warning (20*8 + 4 = 164)
template t_forti_cef_forcepri {
template("<164>$ISODATE $HOST $MSG\n");
};
# Destination: Forward to Azure Monitor Agent
# AMA listens on localhost:28330 for syslog forwarding
destination d_ama_forwarder {
network(
"127.0.0.1"
port(28330)
transport("tcp")
template(t_forti_cef_forcepri)
persist-name("ama_forwarder")
disk-buffer(
mem-buf-size(10485760) # 10MB memory buffer
disk-buf-size(1073741824) # 1GB disk buffer
reliable(yes)
)
log-fifo-size(25000)
throttle(0)
);
};
# Destination: Debug logging
# Uncomment to troubleshoot - logs ALL received messages
# destination d_forti_debug {
# file("/var/log/forti-force-pri.log"
# create-dirs(yes)
# dir-perm(0755)
# perm(0644)
# );
# };
# Filter: CEF messages only
# Ensures we only process Common Event Format messages
filter f_cef {
message("CEF:");
};
# Filter: UTM logs only (all severity levels)
# Forward ALL Unified Threat Management logs regardless of severity
# This ensures complete security visibility in Sentinel
filter f_utm {
message('cat="utm"');
};
# Log path: Process FortiAnalyzer CEF messages
log {
source(s_forti_tcp);
# source(s_forti_udp); # Uncomment if using UDP
# Debug logging - uncomment the following line to troubleshoot
# destination(d_forti_debug);
# Only process CEF messages
filter(f_cef);
# Only forward UTM logs
filter(f_utm);
# Forward to AMA with forced PRI header
destination(d_ama_forwarder);
# Stop processing after forwarding
flags(final);
};
# Alternative debug log path for ALL messages (not just UTM)
# Uncomment this entire block to see everything received on port 1514
# log {
# source(s_forti_tcp);
# # source(s_forti_udp);
# destination(d_forti_debug);
# flags(final);
# };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment