1. Overview

In this tutorial, we’ll talk about ways to detect devices connected to the network we’re connected to. We’ll look at methods using different tools, and choosing one over the other will depend on our specific needs and the tools in our system. We’ll focus on tools we can use from the command line. However, there are other tools, such as Angry IP or zenmap, that allow us to follow similar procedures from a Graphical User Interface.

Firstly, we’ll start with a brief discussion of some preliminary information that will help us better understand the results that we’ll get.

2. Preliminary Background

For most of the tools, we’ll need to know the network IP address. We’ll employ the wlp3s0 network interface in the examples, but other network interfaces might apply in each case. We’ll call ifconfig to get its IP address:

$ ifconfig wlp3s0
wlp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
        inet 192.168.1.4 netmask 255.255.255.0 broadcast 192.168.1.255
        ...

We can see next to inet that the device has the local address 192.168.1.4. This means that the private IP addresses of our router start with 192.168.1. followed by another digit between 1 and 254While this is the most common scenario, we might have our network configured to have another local address.

For the remainder of the article, we’ll consider that there are three devices connected to the network. The 192.168.1.1 one corresponds to the router or modem that’s the source of the network. The 192.168.1.2 one is a smartphone, 192.168.1.3 is a single-board computer (such as a Raspberry Pi) and 192.168.1.4 corresponds to the device from which we’re enquiring, as we just saw.

There will be commands that won’t output the modem and others won’t output the device from which we’re enquiring.

3. Using ping

3.1. Take Advantage of the Network Broadcasting

If our network has broadcasting enabled, we can ping the broadcast address (reserved to the 255 in our local addresses):

$ ping -b 192.168.1.255

However, it’s usually recommended to have broadcasting off in our network. Attackers can exploit a network with attacks such as a Smurf distributed denial of service (DDoS). This attack exploits the vulnerability of networks where broadcasting is enabled.

3.2. Check Hosts That Respond to ping

If our network doesn’t support broadcasting, we can still use ping to detect devices. We just need to loop over all the local IP addresses and use ping to send a packet. Within a for loop, we can use ping and then parse the output with grep:

$ for ip in 192.168.1.{1..254}; do ping -c 1 -W 1 $ip & done | grep "^64 bytes"
64 bytes from 192.168.1.4: icmp_seq=1 ttl=64 time=0.021 ms
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=2.64 ms
64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=11.0 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=325 ms

We’ve used the syntax {1..254} to append the last block to the IP addresses that start with 192.168.1. The -c 1 flag in ping is used to limit the number (count) of packets to one. The -W 1 flag specifies a timeout of one second regardless of the outcome of ping. Finally, we grep the lines starting (specified with the ^) with 64 bytes, which indicates a successful packet send.

In the output, we can see that we get all the devices that are on the network. However, this method only works with the devices that respond to ping. The network might have devices connected that don’t reply to the ICMP (Internet Control Message Protocol) requests and we won’t have them listed in the output.

4. Using arp-based Tools

Linux has several tools used to analyze the Address Resolution Protocol (ARP). The arp tool is responsible for managing the cache of recently-connected devices. We can call arp and it will display all the hosts in the default Linux style:

$ arp
Address        HWtype   HWaddress            Flags   Mask   Iface
192.168.1.2    ether    aa:13:bc:00:1f:f1    C              wlp3s0
_gateway       ether    bb:14:de:01:ed:de    C              wlp3s0
raspberry      ether    cc:15:f1:10:cb:bc    C              wlp3s0

We can also request the output in the alternative BSD style with the -a flag:

$ arp -a
? (192.168.1.2) at aa:13:bc:00:1f:f1 [ether] on wlp3s0
_gateway (192.168.1.1) at bb:14:de:01:ed:de [ether] on wlp3s0
raspberry (192.168.1.3) at cc:15:f1:10:cb:bc [ether] on wlp3s0

The main advantage of arp is that it’s available in (almost) all Linux systems. However, we’ll only retrieve the machines that our system has already talked to.

Let’s expand on this as it will be a recurring topic. arp only shows the IP addresses of those devices to which we’ve attempted a connection recently and that arp has registered in the cache. Thus, if we clear the cache and try again, we’ll probably find nothing.

Therefore, in order to have a more realistic list, we just need to be sure that the cache is up to date. We can ping all the devices with a similar loop as before, directing the output to /dev/null and using & to only show the process ID. Then we can call arp to get the most updated list:

$ for ip in 192.168.1.{1..254}; do ping -c 1 -W 1 $ip & done &> /dev/null &
[1] 201775
$ arp -a
? (192.168.1.2) at aa:13:bc:00:1f:f1 [ether] on wlp3s0
_gateway (192.168.1.1) at bb:14:de:01:ed:de [ether] on wlp3s0
raspberry (192.168.1.3) at cc:15:f1:10:cb:bc [ether] on wlp3s0

The ARP cache is not persistent. This means that if we restart our device – or the networking – the system wipes and empties the ARP cache. We’ll need to ping again before considering using this method.

Finally, there’s another tool that falls under the arp category: arp-scan. With this command we need to specify the interface to get the results:

$ arp-scan --localnet --interface=wlp3s0
Interface: wlp3s0, type: EN10MB, MAC: e0:bf:34:43:fb:0e, IPv4: 192.168.1.4
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.1.1 aa:13:bc:00:1f:f1 Sagemcom Broadband SAS
192.168.1.2 bb:14:de:01:ed:de Samsung Electronics Co Ltd
192.168.1.3 cc:15:f1:10:cb:bc Raspberry Pi Foundation
3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.057 seconds (124.45 hosts/sec). 3 responded

*We can see that with arp-scan, we get more detailed information about the devices connected to the network.*

5. Checking the ARP Cache With ip

The ip package comes equipped with tools to inspect the devices in our network. Let’s use the ip-neighbour tool to get information about our network:

$ ip n
192.168.1.1 dev wlp3s0 lladdr aa:13:bc:00:1f:f1 REACHABLE 
192.168.1.2 dev wlp3s0 lladdr bb:14:de:01:ed:de STALE 
192.168.1.3 dev wlp3s0 lladdr cc:15:f1:10:cb:bc STALE

We can also use any of the following equivalent commands since all of them return the same output (which doesn’t include the device from which we’re emitting the query 192.168.1.4):

$ ip neighbour
$ ip neighbor
$ ip neigh

Finally, we can request that ip attempt to resolve the IP addresses with the -r flag:

$ ip -r n
_gateway  dev wlp3s0 lladdr aa:13:bc:00:1f:f1 REACHABLE  
192.168.1.2 dev wlp3s0 lladdr bb:14:de:01:ed:de STALE 
raspberry dev wlp3s0 lladdr cc:15:f1:10:cb:bc STALE

We can see that the output doesn’t contain IP addresses only and it contains a resolved name that might provide information about the device. The IP address resolution might fail, so we’ll still see the IP address.

The advantages and disadvantages of this method are the same as those of the previous one. It doesn’t require any special package to be installed*,* just the ip command which should be readily available on our device. However, we still need to ping the devices in the network to have a reliable ARP cache.

6. Scanning With nmap

There’s yet another method that doesn’t rely on the ARP cache to detect the devices of the network. nmap is a tool for scanning ports and exploring networks and their security. There are two methods that nmap uses to scan devices: list scan (-sL) and ping scan (-sn).

The list scan method simply lists the targets to scan, producing a very verbose output:

$ nmap -sL 192.168.1.*
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-15 21:52 CET
Nmap scan report for 192.168.1.0
Nmap scan report for mymodem (192.168.1.1)
Nmap scan report for 192.168.1.2
Nmap scan report for osmc (192.168.1.3)
Nmap scan report for 192.168.1.4
Nmap scan report for 192.168.1.5
Nmap scan report for 192.168.1.6
...

We can see that it loops over all the IP addresses. However, the output might be difficult to read since it outputs all IP addresses. We can use grep to filter it:

$ nmap -sL 192.168.1.* | grep \(1
Nmap scan report for mymodem (192.168.1.1)
Nmap scan report for osmc (192.168.1.3)

We’ve used grep to filter only those starting with (1, which we’ve escaped with the backslash. With the nmap list scan method combined with the grep search, we’ll only detect those devices where their names can be resolved.

The ping scan method might sound similar to what we did with ping, but it goes beyond the simple ICMP echo request. We can retrieve all the devices of the network, including those for which the list scan method cannot resolve the name:

$ nmap -sn 192.168.1.*
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-15 21:53 CET
Nmap scan report for mymodem (192.168.1.1)
Host is up (0.0084s latency).
Nmap scan report for 192.168.1.2
Host is up (0.0088s latency).
Nmap scan report for osmc (192.168.1.3)
Host is up (0.00014s latency).
Nmap scan report for 192.168.1.4
Host is up (0.0088s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.53 seconds

There are more options for the nmap tool to scan our network as we can differentiate by protocol or customize other scan flags.

7. Conclusion

In this article, we’ve talked about different methods to detect the devices inside our network. The most simple method, ping, is useful in many scenarios but only works with devices that reply to ICMP echo requests.

Even if the arp and ip methods rely on the ARP cache, which only keeps track of the devices we’ve talked to, we can use ping to include all devices in the cache.

Finally, the nmap method performs a scan outwards to discover all devices in the network.