Installing addrwatch on FreeBSD/OPNsense
addrwatch is a tool for monitoring the ARP traffic on a subnet. From its GitHub page:
This is a tool similar to arpwatch. It main purpose is to monitor network and log discovered ethernet/ip pairings.
Main features of addrwatch:
- IPv4 and IPv6 address monitoring
- Monitoring multiple network interfaces with one daemon
- Monitoring of VLAN tagged (802.1Q) packets.
- Output to stdout, plain text file, syslog, sqlite3 db, MySQL db
- IP address usage history preserving output/logging
- Addrwatch is extremely useful in networks with IPv6 autoconfiguration (RFC4862) enabled. It allows to track IPv6 addresses of hosts using IPv6 privacy extensions (RFC4941).
The main difference between arpwatch and addrwatch is the format of output files.
Arpwatch stores only current state of the network ethernet/ip pairings and allows to send email notification when a pairing change occurs. This is fine for small and rather static networks. In arpwatch case all the history of pairings is saved only in administrators mailbox. When arpwatch is used for monitoring dozen or more networks it becomes hard to keep track of the historic address usage information.
I chose to install addrwatch on ISP routers to monitor for:
- ARP spoofing - clients may change their MAC to evade access control mechanisms, accounting, request new leases or otherwise obscure their identity. It is noteworthy that it is the default behaviour of modern Android and iOS devices to randomize their MAC address upon connecting to a new WiFi network; however it is the default behaviour that they will retain this association and present the same address upon reconnection.
- ARP poisoning - the quintessential layer 2 MitM attack, allowing an adversary to fully intercept (optionally forwarding) all traffic to and from a different, legitimate host (i.e. the victim's gateway) for inspection, injection and/or exfiltration.
- Malfunctioning devices - on occasion I have seen embedded devices go haywire, spewing broadcast storms of ARP responses with randomized source MAC addresses. This can overwhelm a router/bridge/switch's ARP table with bogus entries resulting in a DoS at worst and cache starvation at best.
- CPE equipment changes - detecting a change in hardware at the customer's premises (i.e. a new router's installation)
- Unauthorized IP address changes - where a client may have accidentally or intentionally forced a new layer 3 address that was not assigned to them. This could indicate a router's loss of configuration (reversion to DHCP) or the subversion of access controls, bandwidth allocation or accounting.
On OPNsense one can install addrwatch from the community repo via
...or compile it from source via ports:
As covered in the previous article, Create an Unprivileged User Account on FreeBSD/OPNsense, it is best practice to run daemons under their own user account. To create an unprivileged user account for addrwatch run:
Although the man page that ships with the latest version of addrwatch indicates that it is possible to pipe logs into a standard syslog interface with the
Next it's necessary to create a syshook script to ensure the daemon isEdit started at bootup. Per the syshook documentation, we will prepend the script's file name with 50-: /usr/local/etc/rc.syshook.d/start/50-addrwatch and populate it thus:
#!/bin/sh
ADDRWATCH_EXEC="/usr/local/bin/addrwatch"
ADDRWATCH_USER="addrwatch" # See https://foxpa.ws/unprivileged-user-on-freebsd
ADDRWATCH_LOGFILE="/var/log/addrwatch/addrwatch.log"
ADDRWATCH_PIDFILE="/var/run/addrwatch.pid"
ADDRWATCH_RATELIMIT="-r 0" # [-r (num)] | >0 = seconds within which duplicate events shall be discarded | 0/[empty] = record all events | -1 = suppress duplicates indefinitely
ADDRWATCH_LISTEN_INTERFACES="
Note that you will want to populate the
Let's make a stop script to mirror this configuration at /usr/local/etc/rc.syshook.d/stop/50-addrwatch
#!/bin/sh
/bin/pkill -KILL addrwatch
exit 0
Do not forget to set the execute bits on these scripts:
Optionally, we can add configd actions which can later be called up by the
[start]
command:/usr/local/etc/rc.syshook.d/start/50-addrwatch
type:script
message:starting addrwatch
description:Start addrwatch
[stop]
command:/usr/local/etc/rc.syshook.d/stop/50-addrwatch
type:script
message:stopping addrwatch
description:Stop addrwatch
[restart]
command:/usr/local/etc/rc.syshook.d/stop/50-addrwatch; /usr/local/etc/rc.syshook.d/start/50-addrwatch
type:script
message:restarting addrwatch
description:Restart addrwatch service
[reset]
command:kill -9 `cat /var/run/addrwatch.pid`; rm /var/run/addrwatch.pid
type:script
message:resetting addrwatch
description:Kills addrwatch by PID (if still running) and removes PID file
[status]
command:tail /var/log/addrwatch/addrwatch.log
type:script_output
message:displaying tail of addrwatch logfile
description:Shows the last lines of addrwatch's logfile
Now it's necessary to create a newsyslog configuration to ensure that the log file is rotated, as on a busy network with ratelimiting set low or disabled we will quickly run out of storage. Create /usr/local/etc/newsyslog.conf.d/addrwatch.conf:
# configuration file for newsyslog for addrwatch
#
# see newsyslog.conf(5) for details
#
# logfilename [owner:group] mode count size when flags [/pid_file] [sig_num]
/var/log/addrwatch/addrwatch.log addrwatch:addrwatch 644 7 1024 * JX /var/run/addrwatch.pid
In my situation I quickly realized that the meat-and-potatoes I was looking for would easily be drowned out with ratelimiting set too low. At the same time, with ratelimiting set too high I would be missing important details like flip-flopping. I chose to run two instances side-by-side, logging to separate locations so I can rapidly identify unusual behaviour then optionally refer to the detailed record. This was accomplished by simply duplicating the syshook script and newsyslog configuration, setting the
/usr/local/etc/rc.syshook.d/start/50-addrchange:
#!/bin/sh
ADDRWATCH_EXEC="/usr/local/bin/addrwatch"
ADDRWATCH_USER="addrwatch" # See https://foxpa.ws/unprivileged-user-on-freebsd
ADDRWATCH_LOGFILE="
It's important to ensure that the
/usr/local/etc/newsyslog.conf.d/addrchange.conf:
# configuration file for newsyslog for addrwatch
#
# see newsyslog.conf(5) for details
#It's important to ensure that the
Comments
There are no comments for this item.