Cisco IOS Discovery
The Infracast Cisco IOS plugin discovers network devices by SSHing into seed devices and walking the network using CDP (Cisco Discovery Protocol) and LLDP (Link Layer Discovery Protocol) neighbor tables. Starting from one or more known devices, Infracast recursively discovers adjacent devices until the full network topology is mapped.
How Neighbor Walking Works
Seed Device (10.0.0.1)
│
├─ CDP neighbor: switch-core-01 (10.0.1.1) ──► connect & enumerate
│ │
│ ├─ CDP neighbor: switch-access-01 (10.0.2.1) ──► connect & enumerate
│ ├─ CDP neighbor: switch-access-02 (10.0.2.2) ──► connect & enumerate
│ └─ LLDP neighbor: ap-floor3 (10.0.3.1) ──► connect & enumerate
│
└─ CDP neighbor: router-wan-01 (10.1.0.1) ──► connect & enumerate
Infracast tracks which devices it has already visited to avoid loops. The walk terminates when:
- No new neighbors are discovered
- The configured
max_depthis reached - A device matches an
exclude_pattern(e.g., skip WAN devices by prefix)
CDP and LLDP must be enabled on devices for neighbor walking to work. Most Cisco IOS devices have CDP enabled by default. LLDP is often disabled by default on IOS but enabled on IOS-XE and NX-OS.
SSH Credential Setup
Infracast connects to devices using SSH with username/password or username/SSH key authentication.
Option 1: Username + Password
infracast creds add \
--plugin cisco-ios \
--name "network-ssh-creds" \
--type ssh-password \
--username "infracast" \
--password-file /run/secrets/cisco-ssh-password
Option 2: SSH Key
# Generate a dedicated SSH key for Infracast
ssh-keygen -t ed25519 -f /run/secrets/infracast-cisco-key -C "infracast-discovery" -N ""
infracast creds add \
--plugin cisco-ios \
--name "network-ssh-key" \
--type ssh-key \
--username "infracast" \
--private-key-file /run/secrets/infracast-cisco-key
Configuring the Read-Only User on Cisco IOS
Create a dedicated read-only user for Infracast. Connect to the device and run:
! Create local user with privilege level 1 (read-only)
username infracast privilege 1 secret 0 YourSecurePassword
! Allow SSH access (if not already enabled)
ip ssh version 2
ip ssh time-out 60
ip ssh authentication-retries 3
! Restrict to VTY lines
line vty 0 4
login local
transport input ssh
exec-timeout 5 0
! Optional: restrict by source IP (highly recommended)
ip access-list standard INFRACAST-MGMT
permit 10.0.100.50 ! Infracast collector IP
deny any log
!
line vty 0 4
access-class INFRACAST-MGMT in
Use privilege level 1 (unprivileged) for Infracast. All show commands used for discovery work at privilege level 1. Infracast never needs enable or configuration mode access.
Enabling CDP and LLDP
! Enable CDP globally (usually on by default)
cdp run
! Enable LLDP globally (IOS-XE, recommended)
lldp run
! Verify
show cdp neighbors detail
show lldp neighbors detail
Configuring the Discovery Job
discovery:
jobs:
- name: cisco-network
plugin: cisco-ios
credential: network-ssh-key
schedule: "0 2 * * *" # nightly at 2 AM UTC
config:
# Seed devices — discovery starts here
seed_ips:
- "10.0.0.1" # core router
- "10.0.1.1" # core switch (backup seed)
# SSH connection settings
ssh_port: 22
ssh_timeout_seconds: 30
ssh_known_hosts_check: false # set true in production with a known_hosts file
# Neighbor walk settings
walk_cdp: true
walk_lldp: true
max_depth: 10 # maximum hops from seed
# Scope control
include_subnets:
- "10.0.0.0/8" # only walk devices in these subnets
exclude_patterns:
- "^.*-WAN-.*" # skip WAN-facing devices by hostname
- "^ISP-.*"
exclude_ips:
- "192.168.1.1" # skip specific IPs
# What to collect from each device
collect:
interfaces: true
vlans: true
routes: true
acls: true
arp_table: true
mac_table: true
spanning_tree: true
ospf: true
bgp: false # set true if BGP is in use
What Gets Discovered
For each discovered device, Infracast collects:
| Category | Data Collected |
|---|---|
| Device Identity | Hostname, model, serial number, IOS version, uptime |
| Interfaces | Name, IP/mask, state (up/down), duplex, speed, input/output errors, description |
| VLANs | VLAN ID, name, state, associated interfaces, trunk/access mode |
| Routes | Destination, next-hop, protocol (static/OSPF/BGP/connected), metric, interface |
| ACLs | ACL name, type (standard/extended), rules (source/dest/port/action), interface bindings |
| ARP Table | IP-to-MAC mappings with interface and VLAN |
| MAC Table | MAC-to-port mappings (CAM table) |
| CDP Neighbors | Connected device hostname, IP, port, platform |
| LLDP Neighbors | Connected device hostname, IP, port, system description |
| Spanning Tree | Root bridge, port states (forwarding/blocking), bridge priority |
| OSPF | Router ID, areas, neighbor adjacencies, LSA summary |
| BGP | AS number, neighbor sessions, prefixes advertised/received (if enabled) |
| NTP | Configured NTP servers, sync status |
| SNMP | Community strings existence (not values), contact, location |
Troubleshooting
SSH connection refused
Symptom: Error: dial tcp 10.0.0.1:22: connect: connection refused
Checks:
- Verify SSH is enabled:
show ip ssh - Verify VTY lines accept SSH:
show run | section line vty - Check access-class restrictions — ensure the Infracast collector IP is permitted
- Verify no firewall is blocking TCP/22 between the collector and the device
# Test SSH manually from the collector host
ssh -o StrictHostKeyChecking=no infracast@10.0.0.1 "show version"
Authentication failure
Symptom: Error: ssh: handshake failed: ssh: unable to authenticate
Checks:
- Verify username and password/key are correct
- Check AAA configuration — if TACACS+/RADIUS is in use, verify the Infracast user exists there
- Try password authentication if key auth fails:
! On device: check local auth is allowed as fallback
aaa authentication login default group tacacs+ local
% Invalid input detected on show commands
Symptom: Some data is missing; logs show command parse errors
Cause: IOS version differences. Some show commands have different syntax across IOS versions.
Fix: Specify the IOS version in the job config to use compatible command syntax:
config:
ios_version_hint: "15.2" # or "16.x", "17.x", "xe-16.x"
Discovery stops too early (max_depth hit)
Symptom: Only part of the network is discovered; logs show max depth reached
Fix: Increase max_depth (default is 10):
config:
max_depth: 20
Or add additional seed IPs in different network segments to reduce traversal depth:
config:
seed_ips:
- "10.0.0.1" # DC core
- "10.1.0.1" # Branch core
- "10.2.0.1" # Campus core
Devices behind NAT not reachable
Symptom: CDP shows a neighbor but Infracast can't connect to it
Cause: CDP advertises the device's management IP, which may be a private address unreachable from the collector.
Fix: Use ip_override_map to map CDP-reported IPs to reachable addresses:
config:
ip_override_map:
"192.168.1.1": "10.100.0.1" # CDP reports 192.168.1.1, actually reach at 10.100.0.1
CDP/LLDP neighbor walking loops
Symptom: Discovery runs longer than expected; logs show the same device being visited repeatedly
Cause: This should not happen as Infracast tracks visited devices, but can occur if a device reports multiple IPs and is reached via different addresses.
Fix: Check the duplicate_detection setting:
config:
duplicate_detection: by-hostname # or 'by-ip' (default)