How do I use Linux to find unused IP addresses on my network?

Solution 1:

Any well-behaved device on an Ethernet LAN is free to ignore nearly any traffic, so PINGs, port scans, and the like are all unreliable. Devices are not, however, free to ignore ARP requests, afaik. Given that you specify you're scanning a local network, I find the least-fragile method of doing what you want is to try to connect to a remote address, then look in my ARP cache.

Here's a simple, non-filtering device (ie, one which isn't configured to ignore some classes of IP traffic):

[me@risby tmp]$ ping -c 1 -W 1 192.168.3.1
PING 192.168.3.1 (192.168.3.1) 56(84) bytes of data.
64 bytes from 192.168.3.1: icmp_seq=1 ttl=64 time=0.351 ms
[...]
[me@risby tmp]$ arp -a -n|grep -w 192.168.3.1
? (192.168.3.1) at b8:27:eb:05:f5:71 [ether] on p1p1

Here's a filtering device (one configured with a single line of iptables to ignore all traffic):

[me@risby tmp]$ ping -c 1 -W 1 192.168.3.31
[...]
1 packets transmitted, 0 received, 100% packet loss, time 0ms
[me@risby tmp]$ arp -a -n|grep -w 192.168.3.31
? (192.168.3.31) at b8:27:eb:02:e4:46 [ether] on p1p1

Here's a device that's just down; note the lack of a MAC address:

[me@risby tmp]$ ping -c 1 -W 1 192.168.3.241
[...]
1 packets transmitted, 0 received, 100% packet loss, time 0ms
[me@risby tmp]$ arp -a -n|grep -w 192.168.3.241
? (192.168.3.241) at <incomplete> on p1p1

This method's not infallible - it misses devices that are turned off, for one thing - but it's the least-dreadful method I've yet tried.

Edit: Eric Duminil, yes, it only works on a local network; see paragraph one.

Vishal, the methods are functionally identical. Note the text quoted in Leo's answer about nmap:

When a privileged user tries to scan targets on a local ethernet network, ARP requests are used unless --send-ip was specified.

His method involves less typing. Mine can be done without privilege, and may give you a better understanding of what's actually happening. But the same thing is done on the wire in both cases.

Solution 2:

Since a device cannot ignore ARP requests, I like to use a tool named arp-scan. It is available in most repositories.

When you run the command with the --localnet switch it will give you an overview of your entire internal network.

sudo arp-scan --localnet

Gives me a list of all IP -and MAC addresses on my network. It is also possible to specify a network range to scan.

sudo arp-scan 172.16.128.0/25

If you have multiple network interfaces configured you can specify the one you want to use with the switch -I.

sudo arp-scan -I eth0 172.16.128.0/25

More information about possible switches can be found at https://linux.die.net/man/1/arp-scan or by running man arp-scan.


Solution 3:

I don't know which version of nmap you are running in your Red Hat 6.5, but for recent releases, the correct (and faster) way I think it would be:

nmap -sn -n 172.16.128.0/25

This will list every host in your network (so, you could use any other IP from that subnet as it should be available).

Edit and note: The subnet you mention is 255.255.255.128, but then you show the output as scanning 254 hosts. Unless I'm missing something, that should be a /25 mask and 126 hosts available. If you want to scan a /24, change the command above to query all 254 hosts.

From the nmap book, -sP is discontinued and replaced by -sn:

-sn (No port scan)

This option tells Nmap not to do a port scan after host discovery, and only print out the available hosts that responded to the host discovery probes. This is often known as a “ping scan”, but you can also request that traceroute and NSE host scripts be run. This is by default one step more intrusive than the list scan, and can often be used for the same purposes. It allows light reconnaissance of a target network without attracting much attention. Knowing how many hosts are up is more valuable to attackers than the list provided by list scan of every single IP and host name.

Systems administrators often find this option valuable as well. It can easily be used to count available machines on a network or monitor server availability. This is often called a ping sweep, and is more reliable than pinging the broadcast address because many hosts do not reply to broadcast queries.

The default host discovery done with -sn consists of an ICMP echo request, TCP SYN to port 443, TCP ACK to port 80, and an ICMP timestamp request by default. When executed by an unprivileged user, only SYN packets are sent (using a connect call) to ports 80 and 443 on the target. When a privileged user tries to scan targets on a local ethernet network, ARP requests are used unless --send-ip was specified. The -sn option can be combined with any of the discovery probe types (the -P* options, excluding -Pn) for greater flexibility. If any of those probe type and port number options are used, the default probes are overridden. When strict firewalls are in place between the source host running Nmap and the target network, using those advanced techniques is recommended. Otherwise hosts could be missed when the firewall drops probes or their responses.

In previous releases of Nmap, -sn was known as -sP.

The -n is to avoid DNS resolution of the clients (makes the scan faster):

-n (No DNS resolution)

Tells Nmap to never do reverse DNS resolution on the active IP addresses it finds. Since DNS can be slow even with Nmap's built-in parallel stub resolver, this option can slash scanning times.

You can use other combinations to deepen the scan or services, but that should suffice for what you are looking for, unless the hosts are masking themselves or dropping everything.

Source: https://nmap.org/book/man-host-discovery.html


Solution 4:

Part 1 -- fping

This tool pings everything in the network range specified, and shows those that answer via ICMP.

root@thionite:~# fping -a -g 10.28.1.0/24
10.28.1.1
10.28.1.2
10.28.1.3
10.28.1.4
10.28.1.5
10.28.1.12.....

Part 2 -- arp

Since fping talked with everything on the LAN, that will have caused an entry to be added to the system's ARP table. Read it out within a couple of minutes, because the arp table flushes old entries.

root@thionite:~# arp -a | grep -v incomplete
? (10.28.1.1) at 00:0d:b9:35:29:c4 [ether] on eth0
? (10.28.1.2) at 68:05:ca:10:53:5f [ether] on eth0
? (10.28.1.3) at d2:f1:6e:54:05:22 [ether] on eth0
? (10.28.1.4) at 00:1a:4d:26:85:ee [ether] on eth0
? (10.28.1.5) at 6e:a6:e5:78:da:ca [ether] on eth0
? (10.28.1.12) at 3c:4a:92:76:85:d8 [ether] on eth0

Also note that the ARP table has a maximum size and the kernel will evict old and low usage entries.

Put it all together with

 fping -a -g 10.28.1.0/24 && arp -a | grep -v incomplete > arp.txt

then browse arp.txt at your leisure.


Solution 5:

IPv6

Don't assume that IPv4 is your only option. Many modern operating systems handle IPv6 just fine, even if your ISP doesn't provide V6 connectivity.

There may even be devices which are only reachable by IPv6, or even other protocols.

There's a bunch of handy multicast addresses documented in https://en.wikipedia.org/wiki/Multicast_address#IPv6 But the interesting one for you is ff02::1

root@thionite:~# ping6 -I eth0 ff02::1
PING ff02::1(ff02::1) from fe80::4261:86ff:fec4:cbaa%eth0 eth0: 56 data bytes
64 bytes from fe80::4261:86ff:fec4:cbaa%eth0: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from fe80::21a:4dff:fe26:85ee%eth0: icmp_seq=1 ttl=64 time=0.215 ms (DUP!)
64 bytes from fe80::6a05:caff:fe10:535f%eth0: icmp_seq=1 ttl=64 time=0.233 ms (DUP!)
64 bytes from fe80::226:55ff:feda:299c%eth0: icmp_seq=1 ttl=64 time=0.334 ms (DUP!)
64 bytes from fe80::20d:b9ff:fe35:29c4%eth0: icmp_seq=1 ttl=64 time=0.501 ms (DUP!)
64 bytes from fe80::21e:c2ff:fe13:36bf%eth0: icmp_seq=1 ttl=64 time=0.512 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:85d8%eth0: icmp_seq=1 ttl=1 time=0.518 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:8506%eth0: icmp_seq=1 ttl=1 time=0.757 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:e550%eth0: icmp_seq=1 ttl=1 time=0.772 ms (DUP!)
64 bytes from fe80::60cc:69ff:fe4f:7db0%eth0: icmp_seq=1 ttl=64 time=0.992 ms (DUP!)
64 bytes from fe80::90e4:77ff:fe32:3232%eth0: icmp_seq=1 ttl=64 time=1.00 ms (DUP!)
64 bytes from fe80::90e4:77ff:fe30:3030%eth0: icmp_seq=1 ttl=64 time=1.24 ms (DUP!)
64 bytes from fe80::90e4:77ff:fe31:3131%eth0: icmp_seq=1 ttl=64 time=1.34 ms (DUP!)
64 bytes from fe80::6ca6:e5ff:fe78:daca%eth0: icmp_seq=1 ttl=64 time=2.35 ms (DUP!)
64 bytes from fe80::b639:d6ff:feab:1000%eth0: icmp_seq=1 ttl=64 time=7.04 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:85d8%eth0: icmp_seq=1 ttl=1 time=8.02 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:8506%eth0: icmp_seq=1 ttl=1 time=8.03 ms (DUP!)
64 bytes from fe80::3e4a:92ff:fe76:e550%eth0: icmp_seq=1 ttl=1 time=8.06 ms (DUP!)
64 bytes from fe80::212:12ff:fef7:8044%eth0: icmp_seq=1 ttl=64 time=8.24 ms (DUP!)
64 bytes from fe80::8edc:d4ff:fef2:67e0%eth0: icmp_seq=1 ttl=64 time=18.3 ms (DUP!)
64 bytes from fe80::21e:c2ff:fea9:6d71%eth0: icmp_seq=1 ttl=64 time=295 ms (DUP!)
...repeats