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:
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.
#!/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.*
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)
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.