145 lines
5.4 KiB
Plaintext
145 lines
5.4 KiB
Plaintext
# ARP Table Monitor Script for MikroTik RouterOS
|
|
# This script monitors ARP table and sends REST API notifications for new MAC+IP combinations
|
|
|
|
# Configuration variables
|
|
:local apiEndpoint "http://10.10.10.6:8500/mikrotik-389210-instant"
|
|
:local monitorInterfaces {"vlan-guest"; "vlan-iot"; "vlan-home"}
|
|
|
|
# Create global variable to store known MAC+IP combinations if it doesn't exist
|
|
:global arpKnownDevices
|
|
:if ([:typeof $arpKnownDevices] = "nothing") do={
|
|
:set arpKnownDevices [:toarray ""]
|
|
}
|
|
# Uncomment while testing, comment for production
|
|
# :set arpKnownDevices [:toarray ""]
|
|
|
|
# Get current ARP entries
|
|
:local currentArpEntries [:toarray ""]
|
|
:local arpEntries
|
|
|
|
# Get ARP entries - filter by interface if specified
|
|
:if ([:len $monitorInterfaces] > 0) do={
|
|
:set arpEntries [:toarray ""]
|
|
:foreach iface in=$monitorInterfaces do={
|
|
:do {
|
|
:local ifaceEntries [/ip arp find interface=$iface]
|
|
:foreach entry in=$ifaceEntries do={
|
|
:if ([:len $arpEntries] = 0) do={
|
|
:set arpEntries $entry
|
|
} else={
|
|
:set arpEntries ($arpEntries, $entry)
|
|
}
|
|
}
|
|
} on-error={
|
|
:log warning "Could not access interface: $iface"
|
|
}
|
|
}
|
|
:if ([:len $arpEntries] > 0) do={
|
|
:set arpEntries [:toarray $arpEntries]
|
|
}
|
|
} else={
|
|
# Monitor all interfaces
|
|
:set arpEntries [/ip arp find]
|
|
}
|
|
|
|
# Check for new MAC+IP combinations
|
|
:local newDevicesFound false
|
|
:local requestBody ""
|
|
|
|
:if ([:len $arpEntries] > 0) do={
|
|
:foreach arpEntry in=$arpEntries do={
|
|
:local arpInfo [/ip arp get $arpEntry]
|
|
|
|
# Skip incomplete, invalid, or dynamic entries if desired
|
|
:local arpStatus ($arpInfo->"status")
|
|
:if ($arpStatus = "reachable" || $arpStatus = "stale" || $arpStatus = "delay") do={
|
|
|
|
:local macAddress ($arpInfo->"mac-address")
|
|
:local ipAddress ($arpInfo->"address")
|
|
:local interface ($arpInfo->"interface")
|
|
|
|
# Create unique identifier for MAC+IP combination
|
|
:local deviceId ($macAddress . "-" . $ipAddress)
|
|
|
|
# Check if this MAC+IP combination is already known
|
|
:local isKnown false
|
|
:if ([:len $arpKnownDevices] > 0) do={
|
|
:if ([:find $arpKnownDevices $deviceId] >= 0) do={
|
|
:set isKnown true
|
|
}
|
|
}
|
|
|
|
# If not known, process as new device
|
|
:if (!$isKnown) do={
|
|
:set newDevicesFound true
|
|
|
|
# Get additional info
|
|
:local arpComment ""
|
|
:if ([:typeof ($arpInfo->"comment")] != "nothing") do={
|
|
:set arpComment ($arpInfo->"comment")
|
|
} else={
|
|
:set arpComment "N/A"
|
|
}
|
|
|
|
# Try to get hostname from DHCP lease table (if available)
|
|
:local hostname "Unknown"
|
|
:do {
|
|
:local dhcpLease [/ip dhcp-server lease find address=$ipAddress]
|
|
:if ([:len $dhcpLease] > 0) do={
|
|
:local leaseInfo [/ip dhcp-server lease get [:pick $dhcpLease 0]]
|
|
:if ([:typeof ($leaseInfo->"host-name")] != "nothing") do={
|
|
:set hostname ($leaseInfo->"host-name")
|
|
}
|
|
}
|
|
} on-error={
|
|
# DHCP lookup failed, keep hostname as "Unknown"
|
|
}
|
|
|
|
# Build notification body
|
|
:set requestBody ($requestBody . "MAC+IP Address: " . $deviceId . "\n")
|
|
:set requestBody ($requestBody . "Interface: " . $interface . "\n")
|
|
:set requestBody ($requestBody . "ARP Status: " . $arpStatus . "\n")
|
|
:set requestBody ($requestBody . "Hostname: " . $hostname . "\n")
|
|
:set requestBody ($requestBody . "----------------------------------------\n")
|
|
|
|
# Add to known devices
|
|
:if ([:len $arpKnownDevices] = 0) do={
|
|
:set arpKnownDevices $deviceId
|
|
} else={
|
|
:set arpKnownDevices ($arpKnownDevices . "," . $deviceId)
|
|
}
|
|
|
|
:log info "New ARP entry detected: $macAddress at $ipAddress on $interface"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Send REST API notification for new devices
|
|
:if ($newDevicesFound) do={
|
|
:do {
|
|
/tool fetch \
|
|
url=$apiEndpoint \
|
|
http-method=post \
|
|
http-header-field="Priority: 3,Title: New device detected in network,Tags: warning" \
|
|
http-data=$requestBody \
|
|
keep-result=no
|
|
|
|
:log info "ARP monitoring notification API request sent"
|
|
} on-error={
|
|
:log error "Failed to send ARP monitoring notification API request"
|
|
}
|
|
} else={
|
|
:log info "No new mac/ip combinations in ARP"
|
|
}
|
|
|
|
# Clean up known devices list if it gets too large
|
|
:local knownCount 0
|
|
:if ([:len $arpKnownDevices] > 0) do={
|
|
:set knownCount [:len [:toarray $arpKnownDevices]]
|
|
}
|
|
:if ($knownCount > 2000) do={
|
|
:log warning "Known ARP devices list is getting large ($knownCount entries), consider resetting it"
|
|
# Uncomment the next line to auto-reset when list gets too large
|
|
# :global arpKnownDevices ""
|
|
} |