Monitoring DHCP Leases with MikroTik and Slack
At home I have a fairly extensive network setup that includes numerous switches, wired connections in most rooms, Wi-Fi and over 100 connected devices. Amongst those 100+ devices are numerous Alexas, Raspberry Pis and smart devices in addition to the computers, laptops, tablets, phones, watches and all the usual things.
There are times where it is useful to know of a new DHCP lease being allocated, either for convenience or security.
Motivation
Messing around with tech on a regular basis often involves connecting various devices to the network from time to time, and often its useful to know the IP.
While it is possible to proactively check up on DHCP leases it is very convenient to be notified as and when unexpected leases are granted.
Expected vs Unexpected
Due to the number of devices connected, those that are known and constant are granted DHCP reservations meaning they get the same IP address every time.
I don't want to be notified about known devices with "fixed" (reserved/static lease) IPs.
Acting on Lease Assignment
Mikrotik's DHCP server supports running a lease-script
that will be executed after lease is assigned or de-assigned. Internal "global" variables that can be used in the script:
- leaseBound - set to "1" if bound, otherwise set to "0"
- leaseServerName - dhcp server name
- leaseActMAC - active mac address
- leaseActIP - active IP address
- lease-hostname - client hostname
- lease-options - array of received options
Notifying Slack
The easiest way to send something to slack is via a webhook.
By creating a custom app you can create hooks that go directly to channels without any coding required.
Unsurprisingly the one I use for this is the MikroTikBot:
Webhooks can be created and managed in the Incoming Webhooks section. Webhooks can be directed at specific channels. Each one has a unique URL.
The curl
example allows them to be easily tested and provides an example payload.
Notifying from the Router
The following script checks the lease is bound (rather than unbound) and the second part of the if clause checks it is a dynamic lease (i.e. not a reservation).
If it is the fetch
tool is used to POST
to the Slack endpoint created before with a message that includes the hostname, mac and IP.
/ip dhcp-server lease
:if (($leaseBound=1) && ([/ip dhcp-server lease find where dynamic mac-address=$leaseActMAC]!="")) do={
:do {
:tool fetch mode=https url="https://hooks.slack.com/services/XXX/YYY/ZZZ" http-method=post http-data="payload={\"text\": \"DHCP Assignment: client $"lease-hostname" [$leaseActMAC] received an IP address [$leaseActIP] from the DHCP Server [$leaseServerName]\"}"
:log info "Sent DHCP slack alert for MAC $leaseActMAC"
} on-error={:log error "Failed to send alert email to $recipient"}}
When creating/changing script and be sure to click Apply.
Existing dynamic leases can be deleted which will cause a the script to run again when the client renews (which can be forced for testing).
The Result
As the screenshot below shows, the leases feed into Slack as expected - the screenshot below is particularly noisy as I was developing on an ESP32 which grabs a lease on each boot (after uploading code).
Conclusion
This is quite a straightforward project and works as expected.
The webhook call could easily be swapped to call another service.
Generally speaking, Slack is a great way of delivering internal/personal notifications as it has a free tier, the mobile apps support push and you can organise them into channels as needed. I use it in a number of other projects both at work and home to provide quick any easy notifications of events.