OPNsense Syslog Configuration

This role configures OPNsense firewall to forward system logs to a remote Graylog server via the REST API.

ARA Ansible Bash DHCP Graylog HTTPS JSON OPNsense

OPNsense Syslog Configuration Role

Overview

This role configures OPNsense firewall to forward system logs to a remote Graylog server via the REST API. It manages syslog destinations using an idempotent approach: searching for existing configurations, creating new destinations if needed, or updating existing ones. The role applies configuration changes to activate log forwarding immediately.

Purpose

  • Centralized Logging: Forward OPNsense logs to Graylog for aggregation
  • Security Monitoring: Enable SIEM capabilities for firewall logs
  • Troubleshooting: Centralize logs for easier debugging
  • Audit Trail: Maintain searchable log history
  • API-Based: Reliable automation via OPNsense REST API
  • Idempotent: Safe to run multiple times, updates existing config

Requirements

  • Ansible 2.9 or higher
  • OPNsense firewall with API access enabled
  • API key and secret stored in Ansible Vault
  • Network connectivity to OPNsense (VLAN10)
  • OPNsense user with syslog configuration permissions
  • Graylog server with syslog input configured
  • Network connectivity from OPNsense to Graylog

What is Syslog Forwarding?

Syslog forwarding sends log messages from OPNsense to a remote log server:

Without forwarding:

OPNsense → Local logs only
(Limited storage, difficult to search/analyze)

With forwarding:

OPNsense → Graylog server
(Centralized storage, powerful search, long retention)

Benefits:

  • Aggregate logs from multiple systems
  • Long-term storage
  • Advanced search and filtering
  • Alerting on log events
  • Compliance and auditing

Role Variables

Required Variables

VariableRequiredDescription
vault_opnsense_bjoffrey_user_api_keyYesOPNsense API key (in vault)
vault_opnsense_bjoffrey_user_api_secretYesOPNsense API secret (in vault)

Optional Variables

VariableDefaultDescription
opnsense_syslog_configuration_server_iphostvars['graylog']['ip_vlan12']Graylog server IP
opnsense_syslog_configuration_server_port514Syslog port (UDP/TCP)
opnsense_syslog_configuration_transportudp4Transport protocol
opnsense_syslog_configuration_levelsalert,crit,emerg,err,info,notice,warnLog severity levels
opnsense_syslog_configuration_validate_certstrueValidate SSL certificates

Variable Details

opnsense_syslog_configuration_server_ip

IP address of the Graylog server to receive logs.

Default: "{{ hostvars['graylog']['ip_vlan12'] }}"

Example: "192.168.x.x"

opnsense_syslog_configuration_server_port

UDP or TCP port for syslog.

Default: 514 (standard syslog port)

Common values:

  • 514: Standard syslog (UDP/TCP)
  • 1514: Alternative port
  • 6514: Syslog over TLS

opnsense_syslog_configuration_transport

Network transport protocol.

Default: udp4

Values:

  • udp4: UDP over IPv4 (most common)
  • tcp4: TCP over IPv4 (reliable delivery)
  • udp6: UDP over IPv6
  • tcp6: TCP over IPv6

UDP vs TCP:

  • UDP: Faster, lower overhead, may lose packets
  • TCP: Reliable, guaranteed delivery, slightly slower

opnsense_syslog_configuration_levels

Which log severity levels to forward.

Default: "alert,crit,emerg,err,info,notice,warn"

Severity levels (most to least severe):

  • emerg: Emergency (system unusable)
  • alert: Alert (immediate action required)
  • crit: Critical
  • err: Error
  • warn: Warning
  • notice: Notice
  • info: Informational
  • debug: Debug (very verbose)

Typical configurations:

# All except debug
levels: "alert,crit,emerg,err,info,notice,warn"

# Errors and above only
levels: "alert,crit,emerg,err"

# Everything including debug
levels: "alert,crit,debug,emerg,err,info,notice,warn"

Dependencies

This role has no dependencies on other Ansible roles, but requires:

  • OPNsense firewall with API enabled
  • Graylog server with syslog input configured
  • Network connectivity between OPNsense and Graylog
  • API key with syslog management permissions
  • Ansible Vault for storing API credentials

Example Playbook

Basic Usage

---
- name: Configure OPNsense Syslog Forwarding
  hosts: mint-vm
  gather_facts: false

  roles:
    - opnsense_syslog_configuration

Custom Graylog Server

---
- name: Configure Syslog to Custom Server
  hosts: mint-vm
  gather_facts: false

  vars:
    opnsense_syslog_configuration_server_ip: "192.168.x.x"
    opnsense_syslog_configuration_server_port: 1514

  roles:
    - opnsense_syslog_configuration

TCP Transport

---
- name: Configure Syslog with TCP
  hosts: mint-vm
  gather_facts: false

  vars:
    opnsense_syslog_configuration_transport: tcp4

  roles:
    - opnsense_syslog_configuration

Error-Level Logs Only

---
- name: Configure Syslog for Errors Only
  hosts: mint-vm
  gather_facts: false

  vars:
    opnsense_syslog_configuration_levels: "alert,crit,emerg,err"

  roles:
    - opnsense_syslog_configuration

What This Role Does

  1. Search for existing syslog destination:

    • Calls API: /api/syslog/settings/searchDestinations
    • Filters by: Server IP and port
    • Determines: Create new or update existing
  2. If no existing destination found:

    • Creates new destination via /api/syslog/settings/addDestination
    • Configures: IP, port, transport, log levels
  3. If existing destination found:

    • Updates destination via /api/syslog/settings/setDestination/{uuid}
    • Ensures: Configuration matches desired state
  4. Apply configuration:

    • Reconfigures service via /api/syslog/service/reconfigure
    • Activates changes immediately
    • Starts forwarding logs to Graylog

OPNsense API Endpoints

Search Syslog Destinations

POST /api/syslog/settings/searchDestinations
Authorization: Basic (API key:secret)
Content-Type: application/json

Request body:

{
  "current": 1,
  "rowCount": -1,
  "searchPhrase": ""
}

Response:

{
  "rows": [
    {
      "uuid": "12345678-1234-1234-1234-123456789abc",
      "enabled": "1",
      "transport": "udp4",
      "hostname": "192.168.x.x",
      "port": "514",
      "level": "alert,crit,emerg,err,info,notice,warn"
    }
  ],
  "rowCount": 1,
  "total": 1
}

Add Syslog Destination

POST /api/syslog/settings/addDestination
Authorization: Basic (API key:secret)
Content-Type: application/json

Request body:

{
  "destination": {
    "enabled": "1",
    "transport": "udp4",
    "hostname": "192.168.x.x",
    "port": "514",
    "level": "alert,crit,emerg,err,info,notice,warn",
    "description": "Graylog Server"
  }
}

Response:

{
  "result": "saved",
  "uuid": "12345678-1234-1234-1234-123456789abc"
}

Update Syslog Destination

POST /api/syslog/settings/setDestination/{uuid}
Authorization: Basic (API key:secret)
Content-Type: application/json

Request body: Same as addDestination

Apply Configuration

POST /api/syslog/service/reconfigure

Applies pending syslog configuration changes and restarts service.

Syslog Message Format

Standard syslog message:

<priority>timestamp hostname process[pid]: message

Example:

<30>Jan 08 10:30:45 opnsense filterlog[1234]: BLOCK eth0 IN TCP 192.168.x.x:50123 -> 192.168.x.x:22

Priority calculation:

priority = (facility * 8) + severity

OPNsense facilities:

  • local0-local7: Custom applications
  • auth: Authentication
  • daemon: System daemons
  • kern: Kernel messages

Firewall Log Format

OPNsense filterlog format:

action,interface,direction,protocol,src_ip:src_port,dst_ip:dst_port,rule_num

Example:

BLOCK,vlan18,in,TCP,192.168.x.x:50123,192.168.x.x:22,rule:5

Graylog parsing: Use extractors to parse filterlog messages.

Idempotency

Role is fully idempotent:

  1. First run: Creates syslog destination, reports changed
  2. Subsequent runs:
    • Finds existing destination (search by IP:port)
    • Compares configuration
    • Updates only if different
    • Reports ok if no changes needed

Safe to run repeatedly without creating duplicate destinations.

How Idempotency Works

# Step 1: Search for existing destination
POST /api/syslog/settings/searchDestinations

# Step 2a: If not found, create new
POST /api/syslog/settings/addDestination

# Step 2b: If found, update existing
POST /api/syslog/settings/setDestination/{uuid}

# Step 3: Apply changes (only if changed)
POST /api/syslog/service/reconfigure

Key logic:

{% if destination_exists %}
  Update existing (setDestination)
{% else %}
  Create new (addDestination)
{% endif %}

Security Considerations

  • API Credentials: Stored in Ansible Vault
  • HTTPS: Uses SSL/TLS for API calls
  • Basic Auth: API key/secret authentication
  • Certificate Validation: Enabled by default
  • Unencrypted Logs: Standard syslog (UDP/TCP) is unencrypted
    • Consider syslog over TLS (port 6514) for sensitive environments
  • Network Security: Ensure firewall rules allow OPNsense → Graylog
  • Log Privacy: Logs may contain sensitive information

Network Requirements

Firewall rules needed:

# Allow OPNsense to reach Graylog on syslog port
- action: pass
  interface: vlan12
  source_net: opnsense_vlan12_ip
  destination_net: graylog_server_ip
  destination_port: "514"
  protocol: udp
  description: "Allow OPNsense syslog to Graylog"

Test connectivity:

# From OPNsense (Diagnostics → Ping)
ping 192.168.x.x

# Test UDP port (via nc)
nc -u 192.168.x.x 514

Graylog Configuration

Graylog must have syslog input configured:

  1. Create syslog input:

    • System → Inputs
    • Select “Syslog UDP” or “Syslog TCP”
    • Bind address: 0.0.0.0 or specific IP
    • Port: 514
    • Save
  2. Configure extractors (optional):

    • Parse filterlog messages
    • Extract fields: action, interface, src_ip, dst_ip, etc.
    • Enables better searching/dashboards
  3. Test:

    • Search → Last 5 minutes
    • Filter: source:opnsense

Tags

This role does not define any tags. Use playbook-level tags if needed:

- hosts: mint-vm
  roles:
    - opnsense_syslog_configuration
  tags:
    - opnsense
    - syslog
    - logging
    - monitoring

Notes

  • become: false recommended (no root needed)
  • Idempotent: Safe to run multiple times
  • Searches for existing destination by IP:port combination
  • Creates or updates as needed
  • Only applies configuration if changes were made
  • Logs start flowing immediately after reconfigure

Troubleshooting

”Authentication failed” errors

Cause: Invalid API key/secret

Solution: Verify credentials in vault.

ansible-vault view group_vars/all/vault.yml

Logs not appearing in Graylog

Check OPNsense syslog config:

  1. OPNsense UI → System → Settings → Logging / Targets
  2. Verify destination exists and is enabled
  3. Check IP, port, transport match Graylog

Check Graylog input:

  1. System → Inputs
  2. Verify input is running (green)
  3. Check “Show received messages”

Test connectivity:

# From OPNsense: Diagnostics → Ping
ping <graylog-ip>

# Check firewall rules allow traffic
# Firewall → Rules → VLAN12 (or OPNsense interface)

Check Graylog logs:

# On Graylog server
tail -f /var/log/graylog-server/server.log

“Connection refused” errors

Cause: Graylog not listening on syslog port

Solution:

# Check Graylog listening
netstat -uln | grep 514

# Restart Graylog input
# System → Inputs → [Restart input]

Duplicate log entries

Cause: Multiple syslog destinations configured

Solution:

  1. OPNsense → System → Settings → Logging / Targets
  2. Remove duplicate destinations
  3. Run role again to ensure single destination

Wrong log levels

Cause: Log level filter too restrictive

Solution: Update levels variable:

opnsense_syslog_configuration_levels: "alert,crit,debug,emerg,err,info,notice,warn"

Testing the Role

Verify Destination Created

Via OPNsense UI:

  1. Log into OPNsense
  2. System → Settings → Logging / Targets
  3. Should see Graylog destination

Via API:

curl -u "key:secret" -X POST \
  https://opnsense-ip/api/syslog/settings/searchDestinations \
  -H "Content-Type: application/json" \
  -d '{"current":1,"rowCount":-1}' | jq

Test Log Forwarding

Generate test log:

# Via OPNsense SSH
logger -t test "Test message from OPNsense"

Check in Graylog:

  1. Search → Last 5 minutes
  2. Query: source:opnsense AND test
  3. Should see test message

Monitor Firewall Logs

Trigger firewall log event:

# From blocked network, try to connect to allowed network
# Should generate block log

Check Graylog:

# Search for filterlog messages
source:opnsense AND filterlog

Best Practices

  1. Use UDP for high-volume: TCP overhead can impact performance
  2. Filter log levels: Don’t forward debug unless needed
  3. Monitor Graylog disk: Firewall logs can be high volume
  4. Configure retention: Set appropriate retention policy in Graylog
  5. Create extractors: Parse filterlog messages for better analysis
  6. Set up alerts: Alert on critical firewall events
  7. Regular testing: Verify logs flowing after OPNsense updates
  8. Backup Graylog: Include Graylog in backup strategy
  9. Network isolation: Ensure Graylog on trusted network
  10. Document parsers: Document custom extractors/parsing rules

Log Volume Considerations

OPNsense can generate significant logs:

  • Firewall blocks (especially from internet)
  • DHCP events
  • VPN connections
  • System events

High-traffic networks: 1GB+ logs per day

Graylog sizing:

  • Plan disk space for retention period
  • Example: 1GB/day × 30 days = 30GB minimum
  • Add 50% buffer for growth

Retention policy:

# Graylog index retention
System → Indices → [Default index set]
- Rotation strategy: Size-based (5GB)
- Retention strategy: Delete (30 indices)

Log Message Examples

Firewall block:

filterlog: 5,,,0,vlan18,match,block,in,4,0x0,,64,0,0,DF,6,tcp,60,192.168.x.x,192.168.x.x,50123,22,0,S,1234567890,,64240,,mss

VPN connection:

openvpn: peer connection initiated with [AF_INET]1.2.3.4:12345

DHCP lease:

dhcpd: DHCPACK on 192.168.x.x to aa:bb:cc:dd:ee:ff via vlan14

This role is often used with:

  • opnsense_firewall: Configure firewall rules
  • opnsense_aliases: Create firewall aliases
  • opnsense_source_nat: Configure SNAT rules
  • opnsense_destination_nat: Configure DNAT rules

License

MIT

Author

Created for homelab infrastructure management.