This post describes a technique for bypassing the IP address hiding feature of Apple’s iCloud Private Relay on iOS, iPadOS, and macOS devices. In a nutshell, Apple’s Safari browser can be tricked into establishing a direct connection to a public web server when applying DNS sinkholing techniques that make iCloud Private Relay servers believe that a web page is not public. And while this partially operates as designed to support connections to private servers, e.g., a home media server, the actual vulnerability is about loading (fake) private resources within a supposedly secured public context. This results in the ability to secretly read and map the actual IP address of a user visiting a website despite iCloud Private Relay being active. The vulnerability presented has been fixed in iOS 15.6, iPadOS 15.6, and macOS 12.5.

iCloud Private Relay 101

Apple announced the iCloud Private Relay service at WWDC in June 20211. The basic idea is to improve user privacy by routing web traffic over a chain of servers with the purpose of (1) encrypting DNS queries, (2) lowering the accuracy of IP-based location data, (3) breaking the ability to track users by their often quasi-static, quasi-personal IP address, and (4) allowing no party, not even Apple, to know both the user and the website visited. This new service is significant as the user IP address is potentially the last standing bastion for tracking users following earlier privacy improvements such as blocking third-party cookies2, preventing browser fingerprinting3, introducing throw-away email addresses4 5, and prohibiting in-app tracking without explicit consent6.

How the iCloud Private Relay works

Traditionally, opening a web page starts with the user’s device using the public domain name system (DNS) to obtain the IP address of the server that hosts the requested resource. Most of that traffic is still unencrypted and can be read by transit providers, e.g., the user’s ISP to sell the browsing history of the user to other parties. The user’s device then establishes a direct connection to the web server which allows the web server to the see IP address of the user. Various databases can then be used to map that IP address to an approximate location.

Users who browse the Web using the iCloud Private Relay neither use plain-text DNS nor do they directly connect to a web server. Instead, their request to visit a web page is routed through a chain of proxy servers: The first server is operated by Apple, and the second proxy server is operated by partners of Apple7.

iCloud Private Relay Exclusions

When Apple announced the iCloud Private Relay it described several scenarios that are not compatible with the iCloud Private Relay8: Local network connections, private servers, network extensions & VPNs, and proxy configuration. As much as I never received an exact confirmation for this, I’m strongly assuming that the vulnerability worked by making a public server look as if it was private.

Using a DNS sinkhole to make a public server appear private

Research has shown that the mechanism used to allow connections to private servers could be abused to unhide the user’s actual IP address on public servers.

iCloud Private Relay IP address leak

The mechanism works like this:

  1. The user requests a specially crafted web resource. This could happen invisibly as part of some JavaScript code or an invisible IFRAME.

  2. The iCloud Private Relay egress proxy tries to determine the IP address of the requested website.

  3. The DNS server of the attacker detects that the request is coming from an iCloud Private Relay egress proxy and returns an empty response (NXDOMAIN).

  4. Safari falls back to direct name resolution via the user’s default DNS servers.

  5. The DNS server of the website now returns an IP address and Safari subsequently establishes a direct HTTPS connection. Both sides can see the IP address of the other party.

Here is an example of what this looks like on the DNS server that hosts the attacker’s domain (a.i0q.de). First, several requests from a Cloudflare subnet arrive:

named: 172.68.53.25#56361 (i.a.i0q.de): view apple-relay: query: i.a.i0q.de IN A -E(0)D (188.34.203.150)
named: 172.68.53.25#43599 (i.a.i0q.de): view apple-relay: query: i.a.i0q.de IN AAAA -E(0)D (188.34.203.150)
named: 172.68.53.25#44885 (i.a.i0q.de): view apple-relay: query: i.a.i0q.de IN HTTPS -E(0)D (188.34.203.150) [ECS 173.48.112.0/24/0]
named: 172.68.53.25#53904 (i.a.i0q.de): view apple-relay: query: i.a.i0q.de IN AAAA -E(0)D (188.34.203.150) [ECS 173.48.112.0/24/0]
named: 172.68.53.25#22309 (i.a.i0q.de): view apple-relay: query: i.a.i0q.de IN A -E(0)D (188.34.203.150) [ECS 173.48.112.0/24/0]

The zone view “apple-relay” does not include any entry for i.a.i0q.de and returns an empty response. After Cloudflare gets no response, the device tries again directly, now from a Google subnet while the client uses 8.8.8.8 as its DNS resolver:

named: 172.253.214.13#42488 (i.a.i0q.de): view public: query: i.a.i0q.de IN HTTPS -E(0)DC (188.34.203.150) [ECS 173.48.112.0/24/0]
named: 172.253.195.199#40439 (i.a.i0q.de): view public: query: i.a.i0q.de IN A -E(0)DC (188.34.203.150) [ECS 173.48.112.0/24/0]

Since the view “public” has a CNAME entry for i.a.i0q.de, the device is now opening a direct connection that discloses the original device IP to the server on the other side.

As much as the exact original device IP is already known at this point, it is nevertheless interesting to point out that there was also a smaller leak of the Verizon FiOS subnet due to several DNS requests including EDNS Client Subnet9 information.

Mapping out iCloud Private Relay servers

For this research, the egress proxy servers of Apple’s partners have been statically mapped out from the Maxmind GeoLite2 ASN database10. Two of Apple’s three current partners - Fastly and Cloudflare - also explicitly publish their IP address ranges via APIs11 and web pages12. Information on Akamai’s IP ranges can be obtained from sites such as PeeringDB13, however, simply using Maxmind data turned out to be more straightforward.

PoC setup

Except for one limitation that will be discussed later, hiding a server from the DNS resolvers of Akamai, Cloudflare, and Fastly can be achieved with a standard installation of the open-source BIND DNS server software. Specifically, so-called “views” can be used to give different DNS replies based on the IP address of the requestor. This research uses two zone files for the same subdomain: An incomplete zone file for iCloud Private Relay, and a complete zone file for everything else.

# IP addresses of DNS resolvers used by Apple partners
acl icloud {
  # Subnets obtained from Maxmind ASN database by filtering for AKAMAI, CLOUDFLARE, and FASTLY
};

# Zone file with undefined host for Apple iCloud Relay
view "apple-relay" {
        match-clients { icloud; };
        zone "a.i0q.de" {
                type master;
                file "/etc/bind/db.i0q-icloud";
        };
};

# Zone file with defined name resolution for everyone else
view "public" {
        match-clients { any; };
        zone "a.i0q.de" {
                type master;
                file "/etc/bind/db.i0q-public";
        };
};
; db.i0q-icloud
        IN NS      ns.i0q.de.
; no records for iCloud Private Relay
; db.i0q-public
        IN NS      ns.i0q.de.
i       IN CNAME   d2hcjd3b99teia.cloudfront.net.

Vulnerability Scope

The technique presented could be applied to all versions of iOS/iPadOS 15 up to 15.5 (inclusive), and all versions of macOS 12 up to 12.4 (inclusive). As the only known limitation, users who rely on Cloudflare for their DNS resolution, e.g., use 1.1.1.1, were always protected from the presented demo/configuration that looks at Cloudflare as a single network. It seemed like DNS requests for Apple services arrive in a slightly different structure/sequence, e.g., always include IPv6 AAAA and HTTPS queries, however, it may not be possible at all to detect which part of Cloudflare’s services is sending a request.

Apple has another feature called Mail Privacy Protection which seems to load resources from a similar third-party infrastructure. In my testing Apple Mail would always reject loading resources from servers that are not public and as such never leaked the actual user IP address.

Live Demo

This demo shows that - given a vulnerable OS version - both the iCloud Private Relay IP address and the actual user IP address can be loaded within the same web page. There is also a direct link if the embedded version does not work.

Timeline

June 13, 2021 - Vulnerability reported to Apple

July 7, 2022 - Apple confirmed that a future security update will include changes that address the reported issue

July 20, 2022 - Release of iOS 15.6, iPadOS 15.6 and macOS 12.5

July 21, 2022 - Public disclosure

References