Skip to main content

Capturing a Packet Trace from an iOS Device

Capturing a Packet Trace from an iOS Device

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 📱

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.

Xcode Devices

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
Packet capture

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.

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!

Member for

2 years 7 months
Matt Eaton

Long time iOS and server side team lead with a love for Python, Swift, ObjC, C, C++, networking, testing, network debugging, embedded development, technical writing, and research.

Comments

Ian Wilkinson

Thu, 05/03/2018 - 02:37 PM

Thanks for your informative post! I am interesting in simulating packet loss at the iOS app level (not the entire system level, so I can’t use Link Conditioner), to see how my app performs in bad network scenarios. Is there any way to do that?

Thank you very much, Ian!  If I am understanding you correctly you should be able to simulate packet loss with the Link Conditioner and run a packet trace with the technique described in this article all at the same time.  The remote virtual interface should pick up this TCP traffic the same way.

Daniele - Nexo…

Thu, 05/03/2018 - 10:47 PM

Nice article. if you like to spend money :) there is Charles for iOS (and macOS). Of course, the output is not easy to be exported, i mean from ios to mac.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.