ARP spoofing/poisoning
If you expect a story about dead seals (“Arp! Arp! Arp!”), I’m afraid I’ll have to disappoint you. If you’re interested in seeing what traffic your TCP/IP enabled devices on your home-network send/receive, then I think I have some good news for you. This is a geeky story, so unless you wear a tinfoil hat I suggest you read something else instead
My Dish Network ViP 622 receiver is hooked up to my Internet connection here at home. Where they previously used a phone line to download program information, send status, etc. it will now use the broadband connection. This opens the door to some other applications/features, for example “DishOnline”, which allows you to rent movies over the Internet: select movie from large catalog, pay small fee, download movie over Internet connection, watch within 24hrs, movie disappears from hard disk.
Neat, if it works. However it does not work here! I wanted to do a test-rental while Pia was here and I’m not going to hear the end of it for months to come: some Barbie/Rapunzel movie was supposed to be available this weekend and I was stupid enough to mention it before it was here, but it never made it to the receiver’s hard disk, which meant that we had to do other stuff like going to concerts, the Rodeo, dropping of recyclables (Pia LOVES to smash glass bottles) and seeing WALL-E (soo cute!) at the movie theater.
The initiation of the download from the Dish Network receiver would complete successfully, but the download itself would never complete. It would start off with “I’m done downloading in 1 hr!”, followed by “3 hrs to complete download!” 20 mins later and finally “6 hrs 32 mins to complete download!” 24 hrs (!) later. Something in the communication between my receiver and the dish-endpoint on the Internet was screwed up in a big way. Every time I tried to download the movie I was experiencing no other connection problems at all.
It was time to get out the stethoscope and try to figure out why I saw those issues. It’s a lot more complicated than it used to be: most home networks are now run by routers/switches as opposed to hubs in the past. The advantage of a switch is that it knows where to send data packets to instead of a hub, which is dumb, and sends data to all devices on the network at the same time. The later allows one to listen on conversations that happen on the network without being a participant. In a switched environment, devices which are not involved in the communication will never see any data-packets from that communication. This means that I can’t easily trace the PVRs communication with the Dish Network servers.
So, how do I figure out what the receiver is trying to do? There are quite a number of different ways, but I just want to touch on one that I find the most elegant one. ARP (the Address Resolution Protocol) is one of the principal building blocks of Ethernet networks. Without going into too much detail, it provides a correlation between hardware Ethernet addresses (also known as MAC-addresses) and IP-addresses. Here’s a quick tcpdump for two ARP packets:
# tcpdump -n -l -vv -s 1500 arp tcpdump: listening on msk0, link-type EN10MB (Ethernet), capture size 1500 bytes 13:56:18.161661 arp who-has 192.150.23.100 tell 192.150.23.1 13:56:18.161673 arp reply 192.150.23.100 is-at 00:1c:25:84:48:f5 ...
192.150.23.1 (my main router) asks which system can help with 192.150.23.100’s Ethernet address. And sure enough, the router gets an answer: the hardware address of 192.150.23.100 is “00:1c:25:84:48:f5″. With the IP address information and the hardware address information, the router can create packets that will end up at the right point.
In a switched environment, no other device on the home network will see the communication between two other devices. The switch will make sure that no chatter is broadcast and instead connects two parties directly.
But I *do* want to see what the Dish Network PVR is sending/receiving. And that’s where ARP spoofing/poisoning comes into play. A frightening high percentage of devices do blindly accept ARP packets, even if they did not ask for one. I’m going to lie to two units on my home-network: the Dish Network PVR is being told that another system is the main router and the main router is being told that the same other system is the Dish Network PVR. I use “arpspoof” for this (which happens to be part of the DSniff tool-suite). In two different shell-windows I say: “arpspoof -t PVR ROUTER” and “arpspoof -t ROUTER PVR”, which injects my system into the communication between “ROUTER” and “PVR”. The man-in-the-middle will continue to send “ARP replies” to ROUTER and PVR, even if they did not issue an “ARP request”.
Let’s see this in action! Here’s the first shell window that “spoofs” the first device (telling the PVR that I’m the main router):
# arpspoof -t 192.150.23.121 192.150.23.1 00:1c:25:84:48:f5 00:08:89:43:21:d7 : arp reply 192.150.23.1 is-at 00:1c:25:84:48:f5 00:1c:25:84:48:f5 00:08:89:43:21:d7 : arp reply 192.150.23.1 is-at 00:1c:25:84:48:f5 00:1c:25:84:48:f5 00:08:89:43:21:d7 : arp reply 192.150.23.1 is-at 00:1c:25:84:48:f5 ...
And here’s the second shell window (telling the router that I’m the PVR):
# arpspoof -t 192.150.23.1 192.150.23.121 00:1c:25:84:48:f5 00:1e:2a:4a:45:34 : arp reply 192.150.23.121 is-at 00:1c:25:84:48:f5 00:1c:25:84:48:f5 00:1e:2a:4a:45:34 : arp reply 192.150.23.121 is-at 00:1c:25:84:48:f5 00:1c:25:84:48:f5 00:1e:2a:4a:45:34 : arp reply 192.150.23.121 is-at 00:1c:25:84:48:f5 ...
In order for this to work, your Operating System (FreeBSD in my case) will need to be configured to do IP Forwarding. Normally your OS will drop packets that arrive on the network interface, which are not associated with an IP-address on any of your interfaces. We need to forward those packets instead of silently dropping them. For FreeBSD you would use a sysctl command to achieve that (if you want to make that change permanent, you would add it to /boot/loader.conf):
# sysctl net.inet.ip.forwarding=1 net.inet.ip.forwarding: 0 -> 1 #
Telling PVR that we are the main router? Check! Telling router that we are the PVR? Check! IP-Forwarding enabled? Check! The final step is to capture the network traffic from the PVR. In yet another shell window I execute:
# tcpdump -s 1500 -w pvr.tcpdump host 192.150.23.121 and not arp tcpdump: listening on msk0, link-type EN10MB (Ethernet), capture size 1500 bytes ...
At this point all network traffic coming from or going to the Dish Network PVR is captured in a file call pvr.tcpdump. This file is compatible with network analysis tools like WireShark. I walk over to the PVR and perform some actions that result in traffic on the broadband interface. Once I’m done, I head back to the FreeBSD system and stop the tcpdump. I load the resulting pvr.tcpdump file into WireShark and, voila, there we have all the nifty details of the communication of the device with the mothership (stb001.dishaccess.tv in this case):

Dish Network communication in WireShark
The same works for your Wii, PS3 and other home network devices as well.