Skip to main content

Command Palette

Search for a command to run...

Discovering Your Network | A Bash Script to Map IP & LLDP Neighbors

Explore Your Local Network with Ease Using a Bash Script to Identify Connected Devices

Updated
Discovering Your Network | A Bash Script to Map IP & LLDP Neighbors
R

Driving SD-WAN Adoption in South Africa

Ever wondered who's hanging out on your local network? Whether you're a network admin, a curious techie, or just want to keep tabs on your devices, this Bash script is your go-to tool for uncovering the devices connected to your network. It leverages Linux commands like ip, nmap, and lldpcli, along with an external API, to provide a detailed snapshot of your network neighbors. In this blog post, we'll dive into what this script does, how it works, and how you can use it to explore your network like a pro.

What Does the Script Do?

This script is a powerful network discovery tool that generates two detailed tables:

  1. IP Neighbors Table:

    • Lists all IPv4 devices in your local network's ARP table (using ip neigh show).

    • Excludes IPv6 addresses for a clean focus on IPv4.

    • Retrieves the vendor of each device's MAC address using the macvendors.com API.

    • Performs a quick nmap scan to identify open TCP ports on each device.

    • Outputs a formatted table with columns for IP Address, MAC Address, Vendor (30 characters wide), and Open Ports.

  2. LLDP Neighbors Summary Table:

    • Uses lldpcli show neighbors summary to list devices connected via the Link Layer Discovery Protocol (LLDP), typically used in enterprise networks.

    • Displays details like Interface, Chassis ID (MAC address), System Name, and Port Description.

The script ensures all dependencies (curl, ip, nmap, lldpcli) are installed, runs with root privileges (required for nmap and lldpcli), and handles errors gracefully. It's perfect for network troubleshooting, security audits, or just satisfying your curiosity about what's on your network.

Example Output

Here's a sample output from running the script on a network with a mix of devices:

IP Neighbors Table:
IP Address      MAC Address       Vendor                         Open Ports
--------------- ----------------- ------------------------------ --------------------
192.168.88.89   00:0b:82:7f:c0:5d Grandstream Networks, Inc.     22/tcp,80/tcp
192.168.88.66   86:34:16:3b:49:02 Unknown                        None
192.168.88.112  80:af:ca:24:1a:84 Shenzhen Cudy Technology Co., Ltd. 53/tcp,80/tcp,443/tcp
192.168.88.6    52:54:00:38:0b:45 Unknown                        22/tcp
192.168.88.250  10:5a:17:16:03:35 Tuya Smart Inc.                None
192.168.88.86   f4:30:b9:c2:11:59 Hewlett Packard                80/tcp,443/tcp,631/tcp,8080/tcp
192.168.88.55   d8:1f:12:30:94:fa Tuya Smart Inc.                None
192.168.88.73   e8:94:f6:ba:c3:46 TP-LINK TECHNOLOGIES CO.,LTD.  None
192.168.88.31   80:af:ca:a8:e4:7f Shenzhen Cudy Technology Co., Ltd. 22/tcp,53/tcp,80/tcp
105.233.232.1   10:8f:fe:a9:74:c6 HUAWEI TECHNOLOGIES CO.,LTD    None
192.168.88.211  5e:af:57:e5:30:f4 Unknown                        None
192.168.88.130  b4:2e:99:ec:ca:43 GIGA-BYTE TECHNOLOGY CO.,LTD.  135/tcp,139/tcp,445/tcp
192.168.88.237  02:88:89:a7:7b:99 Unknown                        None
192.168.88.39   74:83:c2:33:ab:98 Ubiquiti Inc                   22/tcp
192.168.88.58   80:af:ca:22:27:f0 Shenzhen Cudy Technology Co., Ltd. 53/tcp,80/tcp,443/tcp
192.168.88.179  dc:a6:32:14:fe:4e Raspberry Pi Trading Ltd       139/tcp,445/tcp
192.168.88.38   0c:60:76:38:5e:ba Hon Hai Precision Ind. Co.,Ltd. None
192.168.88.178  10:5a:17:a8:d6:10 Tuya Smart Inc.                None
192.168.88.136  00:45:e2:f6:f8:9d CyberTAN Technology Inc.       None
192.168.88.76   80:af:ca:a8:e4:7f Shenzhen Cudy Technology Co., Ltd. 22/tcp,53/tcp,80/tcp
192.168.88.242  74:83:c2:33:b2:68 Ubiquiti Inc                   22/tcp
192.168.88.49   9e:79:c2:20:49:b7 Unknown                        49152/tcp
192.168.88.23   dc:a6:32:14:fe:4e Raspberry Pi Trading Ltd       139/tcp,445/tcp
192.168.88.51   c8:cd:55:e0:71:8a Ruijie Networks Co.,LTD        53/tcp,80/tcp
192.168.88.85   00:0b:82:7f:c0:59 Grandstream Networks, Inc.     22/tcp,80/tcp
192.168.88.226  d8:1f:12:2e:2f:bd Tuya Smart Inc.                None
192.168.88.171  d0:39:57:12:74:6d Liteon Technology Corporation  None
10.44.77.254    c8:cd:55:e0:71:8a Ruijie Networks Co.,LTD        None
192.168.88.32   7c:f6:66:75:8d:b0 Tuya Smart Inc.                None

LLDP Neighbors Summary Table:
Interface       Chassis ID        System Name                    Port Description
--------------- ----------------- ------------------------------ --------------------
eth2            74:83:c2:33:ab:98 Dias340ne                      eth0
eth2            b4:2e:99:ec:ca:43 Unknown                        Unknown

This output reveals a vibrant network with devices like Grandstream phones, Ubiquiti gear, Raspberry Pis, and more. The IP Neighbors Table shows which devices are active (e.g., open ports like 80/tcp for web servers or 22/tcp for SSH), while the LLDP table provides insight into directly connected devices, such as a system named Dias340ne on eth0.

How the Script Works

The script is a Bash masterpiece that combines several Linux tools to paint a complete picture of your network:

  1. Dependency Checks:

    • Ensures curl, ip, nmap, and lldpcli are installed.

    • If lldpcli is missing, it exits with instructions to install lldpd (e.g., sudo apt install lldpd).

    • Requires root privileges (use sudo) for nmap and lldpcli.

  2. IP Neighbors Table:

    • Uses ip neigh show | grep -v "::" to list IPv4 neighbors from the ARP table, excluding IPv6 addresses (identified by ::).

    • Queries https://api.macvendors.com/<MAC_ADDRESS> to get the vendor for each MAC address.

    • Runs nmap -F --open -T4 <IP> to scan ~100 common TCP ports and list open ones (e.g., 80/tcp,443/tcp).

    • Formats the output into a table with columns: IP Address, MAC Address, Vendor (30 characters wide), and Open Ports.

  3. LLDP Neighbors Table:

    • Runs lldpcli show neighbors summary to get LLDP neighbor details.

    • Parses the output to extract Interface, Chassis ID (full MAC address), System Name, and Port Description.

    • Handles missing fields (e.g., Unknown for missing System Name or Port Description).

    • Displays a formatted table, ensuring all neighbors are included.

The Script

Here's the full script you can save and run:

#!/bin/bash

# Check if curl is installed
if ! command -v curl &> /dev/null; then
    echo "Error: curl is not installed. Please install it using 'sudo apt install curl' or equivalent."
    exit 1
fi

# Check if ip command is available
if ! command -v ip &> /dev/null; then
    echo "Error: ip command is not installed. Please install iproute2 using 'sudo apt install iproute2' or equivalent."
    exit 1
fi

# Check if nmap is installed
if ! command -v nmap &> /dev/null; then
    echo "Error: nmap is not installed. Please install it using 'sudo apt install nmap' or equivalent."
    exit 1
fi

# Check if lldpcli is installed
if ! command -v lldpcli &> /dev/null; then
    echo "Error: lldpcli is not installed. Please install it using 'sudo apt install lldpd' or equivalent."
    exit 1
fi

# Check if script is run as root (required for nmap and lldpcli)
if [[ $EUID -ne 0 ]]; then
    echo "Error: This script must be run as root for nmap and lldpcli to function."
    exit 1
fi

# Function to query MAC vendor
get_vendor() {
    local mac=$1
    # Query macvendors.com API and extract vendor name
    vendor=$(curl -s "https://api.macvendors.com/$mac")
    # Check if the response is empty or contains an error
    if [[ -z "$vendor" || "$vendor" == *"error"* ]]; then
        echo "Unknown"
    else
        # Crop vendor name to 30 characters
        echo "${vendor:0:30}"
    fi
}

# Function to get open ports using nmap
get_open_ports() {
    local ip=$1
    # Perform a quick TCP SYN scan on common ports (-F for fast scan)
    ports=$(nmap -F --open -T4 "$ip" | grep ^[0-9] | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')
    if [[ -z "$ports" ]]; then
        echo "None"
    else
        echo "$ports"
    fi
}

# Print IP neighbors table header
echo "IP Neighbors Table:"
printf "%-15s %-17s %-30s %s\n" "IP Address" "MAC Address" "Vendor" "Open Ports"
printf "%-15s %-17s %-30s %s\n" "---------------" "-----------------" "------------------------------" "--------------------"

# Get IP neighbors, filter out IPv6 (lines containing ::), and process each entry
ip neigh show | grep -v "::" | while read -r line; do
    # Extract IP and MAC address using awk
    ip=$(echo "$line" | awk '{print $1}')
    mac=$(echo "$line" | awk '{print $5}')

    # Only process lines with valid IP and MAC addresses
    if [[ -n "$ip" && -n "$mac" ]]; then
        # Get vendor for the MAC address
        vendor=$(get_vendor "$mac")
        # Get open ports for the IP
        ports=$(get_open_ports "$ip")
        # Print formatted output
        printf "%-15s %-17s %-30s %s\n" "$ip" "$mac" "$vendor" "$ports"
    fi
done

# Print LLDP neighbors table
echo -e "\nLLDP Neighbors Summary Table:"
# Check if lldpcli command returns any neighbors
lldp_output=$(lldpcli show neighbors summary 2>/dev/null)
if [[ -z "$lldp_output" || $(echo "$lldp_output" | grep -c "Interface:") -eq 0 ]]; then
    echo "No LLDP neighbors found."
else
    # Print LLDP table header
    printf "%-15s %-17s %-30s %s\n" "Interface" "Chassis ID" "System Name" "Port Description"
    printf "%-15s %-17s %-30s %s\n" "---------------" "-----------------" "------------------------------" "--------------------"

    # Process lldpcli output
    echo "$lldp_output" | awk '
    BEGIN { interface=""; chassis=""; sysname="Unknown"; portdesc="Unknown"; }
    /Interface:/ { 
        if (interface != "") {
            printf "%-15s %-17s %-30s %s\n", interface, chassis, sysname, portdesc;
        }
        interface=$2; sub(/,$/, "", interface);
        chassis=""; sysname="Unknown"; portdesc="Unknown";
    }
    /ChassisID:/ { if ($3 == "mac") { chassis=$4 } else { chassis=$3 } }
    /SysName:/ { sysname=$2 }
    /PortDescr:/ { portdesc=$2 }
    END { if (interface != "") {
            printf "%-15s %-17s %-30s %s\n", interface, chassis, sysname, portdesc;
        }
    }'
fi

exit 0

How to Use It

  1. Save the Script:

    • Copy the script into a file, e.g., network_discovery.sh.

    • Make it executable:

        chmod +x network_discovery.sh
      
  2. Install Dependencies:

    • Ensure curl, iproute2, nmap, and lldpd are installed. On Debian-based systems:

        sudo apt update
        sudo apt install curl iproute2 nmap lldpd
      
    • Start the lldpd daemon if not already running:

        sudo systemctl start lldpd
      
  3. Run the Script:

    • Execute with root privileges:

        sudo ./network_discovery.sh
      
    • If the ARP table is empty, ping devices to populate it:

        ping 192.168.88.1
      

Tips and Considerations

  • Root Privileges: The script requires sudo for nmap (SYN scanning) and lldpcli (LLDP data access).

  • API Rate Limits: The macvendors.com API may have rate limits. If you get "Too many requests" errors, add a sleep 1 in the get_vendor function or switch to an alternative API like https://api.maclookup.app/v2/macs/<MAC_ADDRESS>.

  • Nmap Speed: The -F flag scans ~100 common ports for speed. For a full scan, replace with -p- (all 65,535 ports, slower) or specify ports (e.g., -p 1-1000).

  • LLDP Requirements: LLDP must be enabled on your network devices (e.g., switches, routers). If no LLDP neighbors appear, check if your devices support LLDP or if lldpd is running.

  • Firewalls: Devices with firewalls may show "None" for open ports. Use nmap --reason for debugging.

  • Network Population: If the IP Neighbors Table is empty, ping devices on your network to populate the ARP table.

Why This Script Rocks

This script is a lekker way to get a quick, comprehensive view of your network. Whether you're troubleshooting connectivity, auditing for unauthorized devices, or just geeking out over your network setup, it provides:

  • Device Identification: IP, MAC, and vendor details help you recognize devices (e.g., spotting that Raspberry Pi or Ubiquiti gear).

  • Service Discovery: Open ports reveal what services devices are running (e.g., SSH on 22/tcp, web servers on 80/tcp).

  • Network Topology: LLDP data shows direct connections, useful in enterprise environments with managed switches.

So, fire up your terminal, run the script, and get to know your network neighbors like never before! Got ideas for tweaks or want to add more features? Let me know in the comments!


Ronald Bartels | LinkedIn | Instagram


Nepean Networks

The Hub & Spoke | SD-WAN Blog

The Morning Patrol with Ron Mastelek 💪