====== 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]].