Debugging network activity on an iOS device can be challenging. There are fantastic tools built into Xcode that allow you to to see the data flowing in and out of the device, but troubleshooting network activity at the TCP level can be difficult. Often the best option you have is to perform a packet capture at the router level, but this presents it’s own set of challenges. Capturing packets at the router level casts a wide net and you end up capturing a lot of noise at the router level that can make debugging iOS TCP traffic very time consuming. Also, capturing TCP traffic at the router level does not give you a true perspective of what your cellular traffic looks like as WiFi traffic is often much faster. Luckily, within the last week, I learned that there is a way to expose a remote virtual interface on a iOS device from macOS. Exposing a virtual interface allows you to directly capture TCP traffic that is flowing in and out of the device's network interface. This is a true look at your network traffic from the TCP level, no matter if your traffic is over cellular or WiFi. And that is why I wanted to write this article, to give a brief explanation on how to expose a remote virtual interface on an iOS device and then run a packet capture from that interface. Let's get started!
Exposing a Remote Virtual Interface 📱
A complete writeup on exposing a remote virtual interface is available on Apple's developer documentation, but I wanted to take just the core steps and provide example of them below. To begin, make sure you have the iOS device plugged in and you can see your network interfaces on macOS and the iOS device by typing the following command:
$ ifconfig -l lo0 gif0 stf0 XHC20 en0 p2p0 awdl0 en1 en2 bridge0 utun0 utun1 utun2 utun3 en5
Next, open up Xcode and navigate to Window -> Devices and Simulators. Here Xcode should have your connected device and your device identifier. Copy down your device identifier because you will need it in the next step.
Next, use the rvictl tool to create and expose a remote virtual interface on your iOS device with your device identifier. To do this run the following command below.
$ rvictl -s 3fef456ab1664ca0b2a18e0550e27f4a9115b804 Starting device 3fef456ab1664ca0b2a18e0550e27f4a9115b804 [SUCCEEDED] with interface rvi0
From here you should now be able to see the newly created network interface once you run the ipconfig -l command again. On the terminal again, run that same command as before to see the new interface, rvi0. This is the network interface on the iOS device that you will be able to perform packet capture on!
$ ifconfig -l lo0 gif0 stf0 XHC20 en0 p2p0 awdl0 en1 en2 bridge0 utun0 utun1 utun2 utun3 en5 rvi0
Running a Packet Capture 🖥
Now for the fun part, capturing the TCP packet trace into a pcap. To do this, queue up your iOS application on your device that will be running your network activity. Next, on the terminal, type this command in to use the TCPDUMP tool to capture the network activity on the remote virtual interface that you just exposed (rvi0):
$ sudo tcpdump -i rvi0 -vvv -w packet_trace.pcap
You are all set now to run your network activity on your iOS device and see TCPDUMP capturing your network packets from the terminal. In this example I ran two network requests. The following screen shot below shows a sample of one of my tcp streams in Wireshark.
After you are finished, the last thing I recommend doing is removing your remote virtual interface on your iOS device. To do that, run the command below and you should be all set.
$ rvictl -x 3fef456ab1664ca0b2a18e0550e27f4a9115b804
In Summary ⌛️
In summary, I hope you have now learned a bit more about how to capture a packet trace directly from an iOS device. I would be interested to hear if this technique also works on tvOS or watchOS? Please write in and let me know if you test this out and you are successful or not.
Network debugging to me is fascinating. One of the most important things is that you need though to be successful is just the data you need about your TCP traffic and this technique can be very helpful for iOS debugging to eliminate network noise at the router level. I hope you have enjoyed this post and please if you have any questions comments or concerns, leave a comment, and I will get back to you as soon as possible. Thank you!