Overview

[Client devices]
     |  SNMP Trap (UDP 162)
     v
[OPNsense]
  ├── snmptrapd  →  /var/log/snmptrap/snmptrap.log
  └── Zabbix Proxy 7.4  (reads trap log, forwards to Zabbix Server)

Important: OPNsense is based on FreeBSD, not Linux. Commands and tools differ from a standard Linux system:

Linux FreeBSD/OPNsense
apt/yum pkg
logrotate newsyslog
systemctl service / rc.d

Step 1: Verify the Zabbix Proxy plugin installation

Check whether the Zabbix Proxy plugin is correctly installed:

pkg info | grep zabbix

Find the configuration file location:

find /usr/local/etc -name "zabbix_proxy.conf"

Typical location for the OPNsense Zabbix Proxy 7.4 plugin:

/usr/local/etc/zabbix74/zabbix_proxy.conf

Also check where the Zabbix binaries are located:

ls /usr/local/sbin/zabbix_proxy
ls /usr/local/share/zabbix*/

Step 2: Verify net-snmp (snmptrapd)

net-snmp is automatically installed as a dependency of os-zabbix74-proxy. A separate installation is not required.

Verify it is present:

pkg info net-snmp
snmptrapd --version

Note: The users snmpd (uid 344) and zabbix (uid 122) are also created automatically during plugin installation. No manual user creation needed.


Step 3: Create the trap log directory

mkdir -p /var/log/snmptrap
chown snmpd:zabbix /var/log/snmptrap
chmod 750 /var/log/snmptrap
touch /var/log/snmptrap/snmptrap.log
chown snmpd:zabbix /var/log/snmptrap/snmptrap.log
chmod 640 /var/log/snmptrap/snmptrap.log

Note: snmptrapd runs as user snmpd (writer) and Zabbix Proxy runs as zabbix (reader). Ownership snmpd:zabbix with mode 640 gives both the correct access.

Check whether the zabbix user exists:

id zabbix

If the user does not exist:

pw useradd zabbix -d /var/db/zabbix -s /usr/sbin/nologin -c "Zabbix Daemon"

Step 4: Zabbix Trap Receiver script

The script zabbix_trap_receiver.pl processes incoming traps and writes them in the format Zabbix expects.

Check whether Perl is available and note its path:

which perl

Important: On FreeBSD/OPNsense, Perl is located at /usr/local/bin/perl, not /usr/bin/perl. Use this path in both the script shebang and the traphandle directive.

If the script is not present after installation, copy it to OPNsense via SCP. The script zabbix_trap_receiver.pl is located in the same folder as this guide.

Copy the script via SCP (run this from your own machine, not OPNsense):

scp zabbix_trap_receiver.pl root@<opnsense-ip>:/usr/local/bin/zabbix_trap_receiver.pl

Or via the OPNsense shell if transferred by another method (e.g. WinSCP):

# Verify the file is present
ls -la /usr/local/bin/zabbix_trap_receiver.pl

Make the script executable:

chmod +x /usr/local/bin/zabbix_trap_receiver.pl

Test the script syntax:

perl -c /usr/local/bin/zabbix_trap_receiver.pl

Expected output: zabbix_trap_receiver.pl syntax OK


Step 5: Configure snmptrapd

Create the configuration directory if it does not exist:

mkdir -p /usr/local/etc/snmp

Edit or create the configuration file:

vi /usr/local/etc/snmp/snmptrapd.conf

Contents:

# Accept traps from all hosts (restrict as needed)
authCommunity log,execute,net public
authCommunity log,execute,net private

# Forward traps to Zabbix log via the receiver script
traphandle default /usr/local/bin/perl /usr/local/bin/zabbix_trap_receiver.pl

Note: Replace public and private with the community strings used by your devices.

For SNMPv3 (recommended for production), add:

createUser myuser SHA "my_auth_password" AES "my_priv_password"
authUser log,execute,net myuser

Step 6: Configure Zabbix Proxy for SNMP Trapping

Important: OPNsense regenerates zabbix_proxy.conf from a Jinja2 template on every reboot. Editing the file directly will be overwritten. The correct approach is a drop-in config via an Include= directive added to the template.

Step 6a: Add Include to the OPNsense template

cd /usr/local/opnsense/service/templates/OPNsense/Zabbixproxy

python3 -c "
content = open('zabbix_proxy.conf').read()
insert = 'Include=/usr/local/etc/zabbix74/zabbix_proxy.d/*.conf\n'
idx = content.rfind('{% endif %}')
open('zabbix_proxy.conf', 'w').write(content[:idx] + insert + content[idx:])
"

Verify:

tail -5 zabbix_proxy.conf

Expected output:

Include=/usr/local/etc/zabbix74/zabbix_proxy.d/*.conf
{% endif %}
{% endif %}

Step 6b: Create the drop-in config

This file is never touched by OPNsense:

mkdir -p /usr/local/etc/zabbix74/zabbix_proxy.d
cat > /usr/local/etc/zabbix74/zabbix_proxy.d/snmp_trapper.conf << EOF
StartSNMPTrapper=1
SNMPTrapperFile=/var/log/snmptrap/snmptrap.log
EOF

Step 6c: Regenerate the config and verify

configctl template reload OPNsense/Zabbixproxy

grep -E "Include|StartSNMPTrapper|SNMPTrapperFile" /usr/local/etc/zabbix74/zabbix_proxy.conf

Step 7: Enable snmptrapd at boot

Add snmptrapd to /etc/rc.conf.local (OPNsense-safe method — this file is not overwritten by OPNsense upgrades):

echo 'snmptrapd_enable="YES"' >> /etc/rc.conf.local
echo 'snmptrapd_flags="-Lf /var/log/snmptrap/snmptrapd_daemon.log -On -p /var/run/snmptrapd.pid"' >> /etc/rc.conf.local

Do not use -f in the flags — that runs snmptrapd in the foreground and the terminal will hang.

Start snmptrapd:

service snmptrapd start

Check the status:

service snmptrapd status
sockstat -l | grep 162

If snmptrapd was already running (e.g. started at boot), kill the old process first:

ps aux | grep snmptrapd
kill <PID>
service snmptrapd start

Restart Zabbix Proxy to load the new configuration:

service zabbix_proxy restart
# or depending on the OPNsense plugin name:
# /usr/local/etc/rc.d/zabbix_proxy restart

Step 8: OPNsense Firewall rule for SNMP Traps

Add a firewall rule via the OPNsense GUI:

Firewall → Rules → [Interface where clients reside, e.g. LAN or VLAN]

Field Value
Action Pass
Interface LAN / VLAN (your clients)
Protocol UDP
Source Your client network
Destination This Firewall
Dest. Port 162 (SNMPTRAP)
Description Allow SNMP Traps to Zabbix

Verify the port is open:

sockstat -l | grep 162

Step 9: Log rotation with newsyslog

Important: /etc/newsyslog.conf is auto-generated by OPNsense and must not be edited manually — changes will be overwritten. Always use /usr/local/etc/newsyslog.conf.d/.

First check whether net-snmp already created entries:

cat /usr/local/etc/newsyslog.conf.d/net-snmp.conf

If the entries are already present with owner snmpd:zabbix, nothing needs to be done. Otherwise, create a file in the persistent directory:

cat > /usr/local/etc/newsyslog.conf.d/snmp-zabbix.conf << EOF
/var/log/snmptrap/snmptrap.log          snmpd:zabbix  640  7  10240  *  JC
/var/log/snmptrap/snmptrapd_daemon.log  snmpd:zabbix  640  7  10240  *  JC
EOF

Column explanation:

Column Value Meaning
1 log file path Full path
2 owner:group File ownership after rotation
3 mode File permissions
4 7 Keep 7 rotated files
5 10240 Rotate at 10 MB (value in KB)
6 * No time-based rotation
7 J Use bzip2 compression
C Create new file if it does not exist

Test the newsyslog configuration:

# Dry run (test without actually rotating)
newsyslog -nv

# Force rotation now
newsyslog -v /var/log/snmptrap/snmptrap.log

newsyslog runs automatically via cron — no manual cron configuration needed.

Note: The net-snmp package may already add entries for the snmptrap logs in /usr/local/etc/newsyslog.conf.d/net-snmp.conf. Check for duplicates:

cat /usr/local/etc/newsyslog.conf.d/net-snmp.conf
grep snmptrap /etc/newsyslog.conf

Step 10: Testing

Test 1: Send a test trap to the local machine

Send a test SNMPv2c trap to localhost:

snmptrap -v 2c -c public localhost '' .1.3.6.1.6.3.1.1.5.1

Send a test from a client machine (replace <opnsense-ip> with the OPNsense IP address):

snmptrap -v 2c -c public <opnsense-ip> '' .1.3.6.1.6.3.1.1.5.1

Test 2: Verify the trap appears in the log

tail -f /var/log/snmptrap/snmptrap.log

Test 3: Check Zabbix Proxy logs

tail -f /var/log/zabbix/zabbix_proxy.log
# or
find /var/log -name "zabbix_proxy*"

Test 4: Monitor network traffic on port 162

tcpdump -i igb1 -nn -A udp port 162
# Replace igb1 with your actual interface name

List available interfaces:

ifconfig | grep "^[a-z]"

Troubleshooting

snmptrapd fails to start

# Check the daemon log
cat /var/log/snmptrap/snmptrapd_daemon.log

# Run in debug/foreground mode (Ctrl+C to stop)
snmptrapd -f -Lo -C -c /usr/local/etc/snmp/snmptrapd.conf

Common causes:

  • "Address already in use" — another snmptrapd is already running. Find and kill it:
    sockstat -l | grep 162
    ps aux | grep snmptrapd
    kill <PID>
  • "-f flag" in snmptrapd_flags — remove it, it runs snmptrapd in the foreground.

Traps arrive (visible in tcpdump) but do not appear in the log

# Check the Perl path — on FreeBSD it must be /usr/local/bin/perl
grep traphandle /usr/local/etc/snmp/snmptrapd.conf

# Check file permissions (snmpd must write, zabbix must read)
ls -la /var/log/snmptrap/

# Test the Perl script manually
echo -e "172.19.30.10\nUDP: [172.19.30.10]:162->[172.19.30.157]:162\n.1.3.6.1.6.3.1.1.4.1.0 .1.3.6.1.6.3.1.1.5.1\n" | /usr/local/bin/perl /usr/local/bin/zabbix_trap_receiver.pl
cat /var/log/snmptrap/snmptrap.log

Traps appear in the log but not in Zabbix

# Verify Include and SNMP settings are present
grep -E "Include|StartSNMPTrapper|SNMPTrapperFile" /usr/local/etc/zabbix74/zabbix_proxy.conf

# Check the drop-in config file
cat /usr/local/etc/zabbix74/zabbix_proxy.d/snmp_trapper.conf

# Check whether the snmp trapper process is running
ps aux | grep "snmp trapper"

# Verify Zabbix Proxy can read the log file
sudo -u zabbix cat /var/log/snmptrap/snmptrap.log

After reboot, StartSNMPTrapper disappears from zabbix_proxy.conf

OPNsense regenerates the config from its template on every reboot. Check whether the Include directive is still in the template:

grep "Include" /usr/local/opnsense/service/templates/OPNsense/Zabbixproxy/zabbix_proxy.conf

If it is missing (e.g. after a plugin update), re-run Step 6a.

Port 162 is not reachable from clients

# Check if snmptrapd is listening
sockstat -l | grep 162

# Check OPNsense firewall rules
pfctl -sr | grep 162

File and location summary

File / Directory Purpose
/usr/local/etc/snmp/snmptrapd.conf snmptrapd configuration
/usr/local/bin/zabbix_trap_receiver.pl Zabbix trap receiver script
/usr/local/etc/zabbix74/zabbix_proxy.conf Zabbix Proxy config (generated by OPNsense)
/usr/local/etc/zabbix74/zabbix_proxy.d/snmp_trapper.conf Drop-in config: StartSNMPTrapper (persistent)
/usr/local/opnsense/service/templates/OPNsense/Zabbixproxy/zabbix_proxy.conf OPNsense template (contains Include directive)
/var/log/snmptrap/snmptrap.log SNMP trap log (read by Zabbix, owner snmpd:zabbix)
/var/log/snmptrap/snmptrapd_daemon.log snmptrapd daemon log
/etc/newsyslog.conf Log rotation configuration
/etc/rc.conf.local Startup services (OPNsense-safe)

Zabbix GUI configuration

After installation, configure the hosts in the Zabbix Server GUI to receive SNMP traps:

  1. Configuration → Hosts → select the host
  2. Add an SNMP trap item:
    • Type: SNMP trap
    • Key: snmptrap.fallback (for all traps) or snmptrap[<OID>] for specific traps
    • Log time format: yyyyMMdd HHmmss
  3. Make sure the host is linked to the correct Proxy (your OPNsense Zabbix Proxy)