====== SNMP network scanner ======
This may be a re-invention of someone else's wheel, but I enjoyed doing it.
It's a bash script which uses nmap and snmpwalk to scan all your locally-connected networks (this should ideally be run on your router / firewall) and (a) finds SNMP-managed switches, and then (b) interrogates them to find out what's plugged in to which port.
It reports:
- Which switch ports are directly connected to the router's interfaces
- Which switch ports are inter-connected to another switch, if you've cascaded them
- Which devices (listed by MAC address, IP address if known, and hostname if available) are connected to the remaining ports
Some ports will show a single device connected, other may show multiple devices; these are connected in between to an unmanaged switch which cannot be interrogated.
===== The script =====
#!/bin/bash
# 1. Scan known networks for SNMP listeners (assumed to be switches)
#
# 2. Run snmpwalk on each switch to find out MAC addresses on each port
#
# 3. Convert MAC addresses to IPs and if possible hostnames
#
# 4. If a MAC address appears more than once in the list, there's a link between switches
# - try to work out what's connected to what
#
# 5. Final outcome - list of MACs, IPs and hostnames plugged in to each switch port
debug=0
tempfile=/tmp/switchscan.$$
required="nmap snmpwalk"
for req in $required
do
if ! which $req &>/dev/null
then
echo "Sorry, but I need $req to be installed first."
exit 1
fi
done
# Get a list of my local network connections, scan each in turn
ip route list | grep -v default | cut -d' ' -f1,3 | while read network iface
do
[ "$debug" -ge "1" ] && echo "Scanning network $network on interface $iface for SNMP devices" >&2
# Find any SMNP managed switches (they'll be listening on UDP port 161)
nmap -Pn -sU -p 161 $network 2>/dev/null | grep -B4 "161/udp open" | grep ^Nmap | rev | cut -d' ' -f1 | rev | tr -d '()' | while read IP
do
# Ask each switch what MAC addresses it has on each port
snmpwalk -v2c -c public $IP .1.3.6.1.2.1.17.4.3.1.2 2>/dev/null | grep ^iso | cut -d'.' -f12- | grep -v ^1.128.194 | grep -v " = INTEGER: 0" | while read SNMPout
# iso.3.6.1.2.1.17.4.3.1.2.56.234.167.167.63.123 = INTEGER: 5
do
[ "$debug" -ge "2" ] && echo "SNMP response from $IP was $SNMPout" >&2
# Note the port number and convert each MAC address to hex
MACdec=${SNMPout% = *}
port=${SNMPout##* }
MACh=
for byte in `echo $MACdec | tr '.' ' '`
do
MACh=$MACh:`printf "%02x" $byte`
done
MAChex=${MACh#:}
# Look up the MAC address in the arp table to see if we know its IP (and possibly hostname)
rarp=`arp -a | grep $MAChex | tr -d '()' | cut -d' ' -f1,2,7 | tr -d '?'`
subnet=${rarp##* }
nameIP=${rarp% *}
hostname=${rarp%% *}
hostIP=${nameIP##* }
echo "$IP port $port = ${subnet:--} $MAChex $hostIP $hostname"
[ "$debug" -ge "2" ] && echo "$IP port $port = ${subnet:--} $MAChex $hostIP $hostname" >&2
done
done
# Send everything to a temp file so we can process later
done >$tempfile.pass1
# What are our own interfaces' MAC addresses?
ip route list | grep -v default | cut -d' ' -f3 | while read net
do
mac=`ifconfig $net | grep ether | tr -s ' ' | cut -d' ' -f3`
if [ -n "$mac" ]
then
# If we find our own MAC address on a switch port, we're obviously connected (somehow)
grep $mac $tempfile.pass1 | cut -d ' ' -f1-3 | while read swport
do
# Make sure we are the only thing on that port, otherwise it's an indirect connection
[ `grep -c "^$swport " $tempfile.pass1` -eq 1 ] && echo "$swport is connected to my $net interface"
done
fi
done
echo
# Get each switch's IP and see if other switches are plugged in to it
cut -d' ' -f1 $tempfile.pass1 | sort -u | while read swIP
do
grep " $swIP " $tempfile.pass1 | cut -d' ' -f1-3 | while read conSW2
do
if [ `grep -c " ${conSW2%% *} " $tempfile.pass1` -eq 1 ]
then
conSW1=`grep " ${conSW2%% *} " $tempfile.pass1 | cut -d ' ' -f1-3`
# Output to another temporary file because we want the details later as well
echo "$conSW1~$conSW2"
fi
done
done >$tempfile.pass2
# Print the inter-switch connections to console
cat $tempfile.pass2 | tr '~' ' ' | while read IP1 x1 port1 IP2 x2 port2
do
echo "$IP1 port $port1 is connected to $IP2 port $port2"
done | sort -nk3
echo
# Look at the original results again but without the interconnected ports
# This should just be the remaining client machines (sometimes more than one per port, due to unmanaged switches in between)
cut -d' ' -f1 $tempfile.pass1 | sort -u | while read swIP
do
( cat $tempfile.pass2 | tr '~' '\n'; ifconfig | grep HWaddr | tr -s ' ' | cut -d' ' -f5 ) | grep -vf - $tempfile.pass1 | grep "^$swIP " | while read s x1 port x2 net mac cIP cname
do
echo "$swIP port $port is connected to $mac $cIP ${cname:+($cname)}"
done | sort -nk3
echo
done
# Tidy up temp files
rm -f $tempfile.*
===== Sample output =====
192.168.32.1 port 1 is connected to my clients interface
192.168.36.1 port 1 is connected to my servers interface
192.168.36.2 port 1 is connected to 192.168.36.1 port 24
192.168.32.1 port 23 is connected to 192.168.32.3 port 1
192.168.32.1 port 24 is connected to 192.168.32.2 port 8
192.168.36.1 port 24 is connected to 192.168.36.2 port 1
192.168.32.1 port 3 is connected to 00:25:9c:38:e7:94 192.168.32.16 (WRT54.clients)
192.168.32.1 port 3 is connected to 2c:3a:e8:3b:ac:ca 192.168.32.233 (Sonoff-Two.clients)
192.168.32.1 port 3 is connected to 2c:3a:e8:4e:9c:7e 192.168.32.230 (Sonoff-One.clients)
192.168.32.1 port 3 is connected to 5c:51:81:7c:b7:01 192.168.32.102 (Galaxy-J3.clients)
192.168.32.1 port 3 is connected to b4:e6:2d:14:27:64 192.168.32.220 (Wemos-Three.clients)
192.168.32.2 port 1 is connected to 50:46:5d:b5:9c:58 192.168.32.35 (Pikantus.clients)
192.168.32.3 port 3 is connected to 00:19:99:7f:c4:6a 192.168.32.164 (Fujitsu.clients)
192.168.32.3 port 5 is connected to 52:54:00:1e:dd:f8 192.168.32.58
192.168.32.3 port 5 is connected to 52:54:00:5b:05:d8 192.168.32.59 (FreeSwitch.clients)
192.168.32.3 port 5 is connected to c8:3a:35:d8:00:10
192.168.32.3 port 7 is connected to bc:5f:f4:89:a0:94 192.168.32.151 (Stella.clients)
192.168.36.1 port 4 is connected to 00:13:d3:b3:4b:1f 192.168.36.12
192.168.36.1 port 5 is connected to e8:39:35:2d:f0:cc 192.168.36.22 (Masham.servers)
192.168.36.1 port 23 is connected to 00:c0:02:4a:62:b6 192.168.36.20 (PrintUSB.servers)
192.168.36.2 port 4 is connected to 00:b0:c2:01:91:ed
192.168.36.2 port 4 is connected to 52:54:00:75:33:45
192.168.36.2 port 4 is connected to 52:54:00:be:a4:55 192.168.36.27 (Collector.servers)
192.168.36.2 port 4 is connected to 52:54:00:c5:5d:69 192.168.36.24 (ZoneMinder.servers)
192.168.36.2 port 5 is connected to 38:ea:a7:a7:3f:7b 192.168.36.15 (SesteriLO.servers)
192.168.36.2 port 6 is connected to 28:92:4a:32:02:33 192.168.36.11 (Sester.servers)
192.168.36.2 port 7 is connected to 78:ac:c0:f7:88:ae 192.168.36.9 (Sester2.servers)
===== Further development =====
I'm sure there's plenty of other interesting information which can be got out of these switches, such as their names, locations, size, speed, etc.
VLANs are another step too.
----
[[.:|Go up]]\\
Return to [[:|main index]].