• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer
webrtcHacks

webrtcHacks

Guides and information for WebRTC developers

  • Home
  • About
    • Chad Hart
    • Philipp Hancke
  • Subscribe
  • Contact
  • Show Search
Hide Search

Reverse-Engineering Technology apple, Blackbox Exploration, ip leakage, Safari Philipp Hancke · September 27, 2021

Apple’s not so private relay fails with WebRTC

Update: iOS 15.1 (released on October 27th 2021) makes private relay work with WebRTC. You may still find the post below useful for background on WebRTC NAT/Firewall traversal.


Safari is getting a lot of criticism these days. This includes plenty about WebRTC. There are frequent grumblings about missing features and others like regressions (such as this from webrtcHacks author Das-Inge Aas) despite active community interest in the form of detailed bug reports. One of the underlying problems is Apple’s very long release cycle and opaque roadmap. This makes it hard to test in advance and report bugs. The other is that it is pretty unclear what makes it into a release and what does not. “iCloud Private Relay” turned out to be such a case. This feature is currently broken with WebRTC.

iCloud Private Relay is one of the new features in iOS 15 available with iCloud+. For some background reading, refer to this interview or this excellent support article from Apple for technical information. In a nutshell private relay is supposed to hide your IP address. Apple provides a proxy service that is only aware of your IP address and they forward the request on to yet-to-be-identified third-party content providers that actually establish the connection. Apple is aware of your IP address, but not what site you are looking at. The website provider doesn’t get your IP address, keeping you anonymous to them.

At least that is how it is supposed to work. We did some quick tests on the public iOS 15 release that was posted last week and discovered WebRTC’s Interactive Connectivity Establishment (ICE) process breaks Private Relay. We’ll show this in action in a moment, but first, let’s review ICE and what it matters.

WebRTC NAT and Firewall Traversal Recap

WebRTC is a peer-to-peer (p2p) protocol. Your camera, microphone, screen share, and data streams are sent directly from your web browser to another web browser. Peer-to-peer is used because a direct p2p connection is usually the fastest and low latency is critical for quick, interactive communications.

To establish a direct connection, the browsers need to know each other’s IP addresses. Network Address Translation (NAT) and firewalls often prevent this direct communication. That’s where Interactive Connectivity Establishment (ICE) comes in. ICE is a procedure for making sure this IP address information gets between you and the callee. One of the most common methods is a Session Traversal Using NATs or STUN server. Your browser pings the STUN server and it responds with the public IP it sees for you. Your browser then gets this data and uses it as part of the negotiation process.

WebRTC STUN returns your public IP address

When you make an RTCPeerConnection, you should specify the iceServers object as part of the configuration.

If you are new to this, see Chad’s Kranky Geek video for a more detailed explanation:

WebRTC IP leaks

Doesn’t that expose your private IP address? Yes, it does and that is by design. This topic comes up in WebRTC quite often and we’ve written about it often.

How often does this happen? We can actually make an approximation using the Chrome Platform Status tracker. To establish a WebRTC connection that actually sends something, the app needs to make both a setLocalDescription and setRemoteDescription call. Looking at the stats, the local description is called more often than the remote description:

Chrome stats: setLocalDescription Chrome stats: setRemoteDescription

There is a big difference here – 6% vs. 0.3%. Why would an app do a setLocalDescription and not setRemoteDescription? Well if you wanted to track a user’s local IP addresses and used that for fingerprinting you wouldn’t need the setRemoteDescription. The only reason for this magnitude of difference is tracking, and you can often see this yourself by looking for sites you don’t recognize in webrtc-internals / about:webrtc.

mDNS to the rescue

This was not the desired intent of these API’s. To help resolve this issue, Multicast DNS (MDNS) candidates were introduced. When enabled, randomly generated addresses that use a UUID – i.e. eb93e835-73d6-4a13-b6f6-2be4f3dee256.local are used instead of your IP addresses. These MDNS entries can be resolved on the local network only, still allowing for important use-cases like file transfer.

By the way – it was Apple folks who came up with the idea and it is great (also hey Googlers, mind updating the status of your Android implementation of that feature?).

Fippo did a whole talk on that one if you want more information:

Test Private Relay and WebRTC yourself

If there is an expectation of IP address privacy with private relay, how does Apple explain the following simple experiment:

Private Relay OFF

  1. Turn off Private Relay in your iOS 15 iCloud settings
  2. Go to https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
    This is a pretty simple test that uses WebRTC to ask a STUN server for the device’s public IP address. This is done via UDP sockets and part of the core WebRTC functionality for NAT traversal.
  3. Click the “Gather candidates” button at the bottom.
  4. We see three candidates in each case – two host addresses, obfuscated via MDNS, and a server reflexive (srflx) one that has been gathered via STUN.

Private Relay ON

  1. Now go back and turn On Private Relay and restart Safari.
  2. Open the same WebRTC samples page
  3. “Gather Candidates” again:

That srflx candidate from the STUN server is a problem – that’s your real IP address! Search for “what is my IP address” and you’ll see Private Relay is working there. It seems Apple forgot to proxy WebRTC STUN requests.

What’s Going on at Apple?

Was Apple aware of this? Reddit was a month ago. The Safari Tech Preview release notes as well.
mentioned a cryptic “WebRTC relay” functionality at the beginning of September. This pointed to two commits in the Webkit git repository:

  • Enable WebRTC relay by default
  • Enable WebRTC relay for SafariViewController

These commits predate the Reddit discussion by a few weeks.

Under the hood what needs to happen is an integration between the socket abstraction libwebrtc uses and Safari so that when libwebrtc opens a UDP socket and sends a STUN packet to the server this gets relayed. We can find the commit for this as well, dating back to the end of June:
[Cocoa] Migrate WebRTC UDP socket handling to NW API

So how come the iOS 15 release shipped without proper integration between WebRTC and private relay?

Impact on WebRTC applications

To be fair, the feature is a public Beta. Perhaps Apple had issues with Private Relay and WebRTC services so they haven’t turned that on yet.

That is a real possibility. Remember WebRTC is supposed to be peer-to-peer as much as possible. For input-sensitive low-latency streaming, relaying traffic via not one but two entities (in separate organizations) seems like a terribly bad idea. We hope Apple’s relay servers have been thoroughly tested and preserve the standard properties of WebRTC and ICE like 5-tuples. They will also need to deal with streaming bitrates of tens of megabits per second without adding much latency or packet loss. If not, then WebRTC services may need to ask their users to turn off Private Relay when using WebRTC in Safari.

{“authors”: [“Philipp Hancke“, “chad hart“]}

Reverse-Engineering, Technology apple, Blackbox Exploration, ip leakage, Safari

Related Posts

  • FaceTime finally faces WebRTC – implementation deep diveFaceTime finally faces WebRTC – implementation deep dive
  • Guide to WebRTC with Safari in the Wild (Chad Phillips)Guide to WebRTC with Safari in the Wild (Chad Phillips)
  • Reeling in Safari on WebRTC – A Closer Look at What’s SupportedReeling in Safari on WebRTC – A Closer Look at What’s Supported
  • Are we There Yet? WebRTC standards Q&A with Dan BurnettAre we There Yet? WebRTC standards Q&A with Dan Burnett

RSS Feed

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

  • Sponsored. Become a webtcHacks sponsor

Email Subscription

Subscribe to our mailing list

* indicates required

Twittering

Tweets by @webRTChacks
webrtcHacksguides and information for WebRTC developers

Footer

SITE

  • Post List
  • About
  • Contact

Categories

  • Guide
  • Other
  • Reverse-Engineering
  • Standards
  • Technology

Tags

apple Blackbox Exploration Brief camera Chrome code computer vision DataChannel debug e2ee Edge extension gateway getUserMedia ICE ims insertable streams ios ip leakage janus jitsi MCU Microsoft NAT opensource Opus ORTC Promo Q&A raspberry pi Safari SDES SDP sfu signaling simulcast standards TensorFlow TURN video vp8 Walkthrough Web Audio webrtc-internals wireshark

Follow

  • Twitter
  • YouTube
  • GitHub
  • RSS

webrtcHacks · copyright © 2023