Cisco IP Phones: Spoofing CDP to use VOIP VLAN on an unmanaged network
I ran into an interesting issue recently where I was deploying Cisco IP Phones onto an unmanaged network. With any other phone vendor, this wouldn't be too much of a problem as they support storing their configuration, but Cisco phones are typically transient and require an accessible TFTP server in order to boot.
This TFTP server is found using DHCP Option 150
, provided when the phone requests a lease.
Unfortunately, the unmanaged network I was deploying into used an ISP-provided router for DHCP, and hence didn't have the capability to set DHCP options. A typical hacky approach to get around this which i've used before is to set up isc-dhcp-server
on a Raspberry Pi with a MAC Address whitelist for the phones, and rely on the fact that it's likely going to be faster at serving DHCP than a rubbish ISP router. Sadly this approach didn't work as it turns out as this ISP router was actually somewhat fast at DHCP replies, and beat the Pi to it about 50% of the time.
Normally in enterprise environments, Cisco switches use CDP
to advertise a VOIP VLAN to be used by phones, allowing large networks to separate normal internet and VOIP traffic, applying QOS and other measures to make sure that the VOIP traffic is treated preferentially. Sadly, the network here was unmanaged, and installing a beefy Cisco 3750 with lots of fans in place of their silent 8 port switch seemed a little overkill.
I then thought, if Cisco switches typically send out these packets from any port configured for end-user access, surely we could spoof this on an unmanaged network by simply sending out CDP, and due to its broadcast nature it would reach all devices on it's own. Provided we didn't send any weird options that would interfere with existing devices on the network (most of which aren't CDP-aware anyway), we should be fine.
After some googling, i found an old package called cdp-tools
, which seemed to be difficult to find as the website it was hosted on has been shut down. Thankfully, someone had mirrored it to GitHub: https://github.com/geocar/cdp-tools
I found a great site with tutorials on the tools included: https://openmaniak.com/cdp.php
Once I had the tools, I used cdp-send
to send out CDP packets with a voice vlan
parameter, hoping that the Cisco phone would see this and hop over to the other VLAN, where I had another device waiting to give it a DHCP lease with the crucial option 150
.
Sadly, at first it didn't seem to work. I first tried increasing the number of broadcasts by decreasing the wait time to once every 10 seconds (using -t 10
). This still didn't seem to have an effect so I kept trying.
My final command, which I put into cron on a linux box was:
cdp-send eth0 -n asterisk -L 1 -V 3 -t 10 -p "Port 10" -P full -c l2sw
This command broadcasts CDP at an interval of 10
seconds, advertising that devices are connected to Port 10
of a layer 2 switch
with name asterisk
, negotiated at full duplex
. The native (untagged) VLAN ID is 1
, and Voice VLAN ID is 3
.
When my Cisco 6901 saw a few of these packets, it immediately disconnected from the untagged network and hopped over onto VLAN 3
, ready to accept DHCP with option 150
and pull config over TFTP.