4

I connect through Ethernet. But almost all other devices use WiFi. Is it possible to get a list of devices connected to my router in Ubuntu 22.04? It would be great if there is some method to get an alert as well when a new device is connected to the WiFi network.

Edit 1: Interestingly arp -a is giving more details, but no device information. A few internal IPs and MAC IDs.

Edit 2: I think more details are available through arp -a because I ran the nmap command shared by @Raffa.

Edit 3: There is already a tool called Nutty that can do this, but last release was 2019.

screenshot

Pablo Bianchi
  • 17,371
user227495
  • 4,309

4 Answers4

5

I hope this helps or at least educates :-) ... It should be run as a bash script ... It uses notify-send for notifications:

#!/bin/bash

Start the main loop

while true; do

Change "10.0.0.0/24" to your network address and your netmask e.g. "192.168.1.0/24"

Use "nmap" to get discoverable devices on the network and parse the output to get only those with resolvable hostnames into an arry "a"

readarray -t a < <(nmap -sn 10.0.0.0/24 | awk '/Nmap scan report for/ && NF == 6 {print $((NF-1)), $NF}')

To get even devices with un-resolvable/empty/unset hostnames, comment the above line and uncomment the below line

readarray -t a < <(nmap -sn 10.0.0.0/24 | awk '/Nmap scan report for/ {print $5, $6}')

Loop over items in array "a"

for item in "${a[@]}"; do # Get device's MAC address from the already updated arp table ip=${item#(}; ip=${ip%)}; mac=$(arp -n "$ip" | awk '/.:.:.:.:.:./{printf "%s", $3}') # Compare items to array "b" and send notification for recently connected devices. [[ ! "${b[*]}" =~ "${item}" ]] && notify-send -i network-wired "Connected device:" "Hostname (IP) MAC:\n ${item} ${mac}" done

Loop over items in array "b" ... Notice this array is not initially declared for simplicity and shortness.

for item in "${b[@]}"; do # Compare items to array "a" and send notification for recently disconnected devices. [[ ! "${a[*]}" =~ "${item}" ]] && notify-send -i network-error "Disconnected device:" "Hostname (IP):\n ${item}" done # Copy array "a" to array "b" b=("${a[@]}") # Wait N seconds before continuing the main loop sleep 60 done

A terminal display version(with extra features) of the above script would be like so:

#!/bin/bash

This script depends on these commands/utilities (mktemp, nmap, awk, arp, column, sort, nl and notify-send)

nts="1" # Set this to "1" to enable sending desktop (notify-send) notifications on new or disconnected devices or to "0" to disable it. network="10.0.0.0/24" # Change "10.0.0.0/24" to your network address and your netmask e.g. "192.168.1.0/24" si="60" # Scan interval in seconds. Lower is NOT always better (between "30" and "300" is recommended for "/24" subnet). Devices are discovered at this interval and considered disconnected 3X this interval. logfile="$HOME/NetworkDevicesMonitor.log" # Pathe to the log file. It will be created if it dosen't exist.

Path to Nmap MAC prefixes file on your system (It comes with nmap when installed). This is the default path and should work fine:

pdb="/usr/share/nmap/nmap-mac-prefixes"

Don't edit below this line unless you know what you're doing

Create a temporary file with "mktemp"

tmpfile=$(mktemp)

Start the main loop

while true; do

Clear the temporary file

> "$tmpfile"

Use "nmap" to get discoverable devices on the network and parse the output into an arry "a"

readarray -t a < <(nmap -sn "$network" |
awk '/Nmap scan report for/ && (NF == 6) {print $5, $6} /Nmap scan report for/ && (NF == 5) {print "Unavailable", "("$5")"}')

Loop over items in array "a"

for item in "${a[@]}"; do # Get device's MAC address from the already updated arp table ip=${item#(}; ip=${ip%)}; mac=$(arp -n "$ip" 2> /dev/null | awk '/.:.:.:.:.:./{printf "%s", $3}'); [[ -z "$mac" ]] && mac="Unknown" # Lookup vendor if [[ "$mac" == "Unknown" ]]; then vendor="$mac" else awmac="${mac//:}" awmac="${awmac:0:6}" vendor=$(awk -v mac="${awmac}" 'BEGIN{IGNORECASE=1} $1 == mac {for(i=2;i<NF;++i) printf "%s_", $i; printf "%s", $NF }' "$pdb") fi [[ -z "$vendor" ]] && vendor="Unavailable" # Compare items to array "b" and write new and connected devices to file (and send notifications if enabled). if [[ ! "${b[*]}" =~ "${item}" ]] && [[ ! "${c[*]}" =~ "${item}" ]] && [[ ! "${d[*]}" =~ "${item}" ]]; then echo -e "1 \U2191 New ${item} ${mac} ${vendor}" >> "$tmpfile" echo -e "[$(date)] \U2191 Connected: ${item} ${mac} ${vendor}" >> "$logfile" [[ "$nts" == 1 ]] && notify-send -u critical -i network-wired "New device:" "${item}\n${mac}\n${vendor}\n$(date)" else echo -e "3 \U2194 Connected ${item} ${mac} ${vendor}" >> "$tmpfile" fi done

Loop over items in array "d" ...

for item in "${d[@]}"; do # Get device's MAC address from the already updated arp table ip=${item#(}; ip=${ip%)}; mac=$(arp -n "$ip" 2> /dev/null | awk '/.:.:.:.:.:./{printf "%s", $3}'); [[ -z "$mac" ]] && mac="Unknown" # Lookup vendor if [[ "$mac" == "Unknown" ]]; then vendor="$mac" else awmac="${mac//:}" awmac="${awmac:0:6}" vendor=$(awk -v mac="${awmac}" 'BEGIN{IGNORECASE=1} $1 == mac {for(i=2;i<NF;++i) printf "%s_", $i; printf "%s", $NF }' "$pdb") fi [[ -z "$vendor" ]] && vendor="Unavailable" # Compare items to array "a" and write disconnected devices to file (and send notifications if enabled). if [[ ! "${a[*]}" =~ "${item}" ]] && [[ ! "${b[*]}" =~ "${item}" ]] && [[ ! "${c[*]}" =~ "${item}" ]]; then echo -e "2 \U2193 Disconnected ${item} ${mac} ${vendor}" >> "$tmpfile" echo -e "[$(date)] \U2193 Disconnected: ${item} ${mac} ${vendor}" >> "$logfile" [[ "$nts" == 1 ]] && notify-send -u critical -i network-error "Disconnected device:" "${item}\n${mac}\n${vendor}\n$(date)" fi done # Copy to redundant arrays "c" and "d" used for more reliable status and notification d=("${c[@]}") c=("${b[@]}") # Copy array "a" to array "b" b=("${a[@]}") # Clear the terminal clear # Format and write output sort -k1 "$tmpfile" | nl | column -t -N '#,s,*,Status:,Hostname:,(IP):,MAC:,Vendor:' -H 's' # Wait N seconds before continuing the main loop sleep "$si" done

Notices:

  • There are alternative scripting methods some of which require the use of sudo for higher privileges e.g. nmap itself will print MAC addresses if it is run as root … I however avoided those methods at all costs and used safe workarounds that don’t require being run as root … It’s also worth noting that the example application linked in your question and others depend on and use nmap in the background … So, when all roads lead to Rome as such, I usually advocate the shortest, safest and straightest one :-).

  • Arp(Address Resolution Protocol) tables are implemented and available on most network enabled OSes including Ubuntu(cat /proc/net/arp will give you an idea) and you can query them easily and quickly … But, the important thing to know in your use case is that newly connected devices to the network are not necessarily readily/instantly added to these arp tables … Your host needs to communicate with these devices and exchange arp packets (e.g. by sending arp requests or echo requests to them) for its arp table to be updated accordingly ... Helpful information here as well.

  • Nowadays and by default, devices change their MAC addresses to random ones and/or hide their host/device names when they connect to different networks ... It's considered a security/privacy feature and it can usually be disabled/enabled under network connections settings.

Raffa
  • 34,963
1

This question is not directly Ubuntu related and may be a better fit elsewhere. It's quite broad and more focus would help get a better answer.

If you're running an OpenWrt router, you should be able to put together a script to do this. It could be run on the router to regularly query connected WiFi devices as a cron job: Listing devices connected in hotspot through terminal

I suspect, as you haven't mentioned your router OS, that you're running off the shelf firmware. In that case, you could scrape your router's web interface regularly to obtain a list of connected devices (if this information is available somewhere on the router's web interface). You could use requests or selenium, depending on how your router's webif is designed. This is likely to be quite brittle.

Another approach might be to regularly run nmap to scan your network and set up an alert for when a new address is detected on the network. This isn't limited to WiFi connections and would also flag if a new wired device connected.

All have pros and cons. It depends on what router you have. I personally would get an OpenWrt router then write a script to monitor new WiFI devices.

moo
  • 966
0

Install NetDiscover with:

sudo apt-get install netdiscover

Then assuming You router's IP is 192.168.0.1,
You can scan for devices connected to it by running:

netdiscover -r 192.168.0.1/24 # where -r is a flag for RANGE
or
netdiscover -r 192.168.0.1-192.168.0.254 # same as 192.168.0.1-254
or
netdiscover # with no argument, so as to auto discover.

ByronTaaka
  • 171
  • 6
-1

If your router doesn't have it's own Linux based router software,(and you don't have Wine installed(a windows emulation software,)) then here is the latest from Google search. https://openwrt.org/ WRTproject is for developers--- EHH!! nope it does:Users can replace the router firmware that comes with their stock routers and customize their devices.(and it is completely opensource) https://vyos.io/ https://mikrotik.com/software (top two other Linux based router software(may need make(hint your repository files ending end in DEV for supporting libraries and OTM dependencies.)))