Setting up my own "Private Relay" Knockoff with Tor

Apple’s Private Relay is a pretty awesome concept. As I understand it, it’s pretty much a faster version of the Tor network (as it only jumps through two nodes) that is managed by Apple and easily toggle-able in the Settings app. I don’t know if they are actually using the Tor protocol but I can assume they are as their description of Private Relay matches up pretty closely to my understanding of Tor.

The upsides of using the Private Relay:

  • It’s an easy button for private browsing.
  • When it works, it is faster than Tor and has most of the same benefits.
  • Private Relay doesn’t proxy private IP space. This means you can use Safari+Private Relay to privately browse the internet and still access your router at home (or other resources on your LAN).

Those are big upsides.

At the time of me writing this, there are a couple of really big downsides to Apple’s Private Relay:

  • It’s super unstable (in Apple’s defense iOS 15 is still in beta) – Safari pretty much doesn’t work for me at all if I have the Private Relay turned on.
  • It’s exclusive to Apple products – you can’t even use Private Relay with third party apps on your Apple device.
  • Since you can’t specify which apps use the Private Relay it really only provides privacy when browsing in Safari or using other Apple apps. I really don’t use any of the Apple apps except Safari on my phone so the Private Relay doesn’t do much for all the other non-Apple apps I use.

After some thought, I just decided to see if I can work around these downsides using Tor. However, I don’t want to use the Tor Browser because one of my favorite upsides of the Safari + Private Relay is that I can still access all my devices in private IP space without having to turn off Private Relay.


To replicate my setup you need a Linux server. I keep my devices always-connected to a VPS running Wireguard and so I’m using that same Wireguard connection and VPS to run my proxy.

Install Docker on your server.


SOCKS Proxy:

First, let’s setup a Tor SOCKS proxy. This will allow you to point your desktop browsers directly at your SOCKS proxy which will allow them to use Tor.

Run the following Docker command to use the PeterDaveHello/tor-socks-proxy image:

docker run -d --restart=always --name tor-socks-proxy -p 9150:9150/tcp peterdavehello/tor-socks-proxy:latest

I won’t go into detail on how to do this but I’d recommend restricting that port with a firewall to make sure that only specific IP addresses can use the SOCKS proxy.

My server’s IP address where I will connect to the proxy is You can configure Firefox to use the proxy in Settings > General > Network Settings > Settings > Manual Proxy Configuration. Refer to the screenshot below for specifics – I would recommend you put the same IP ranges in the No proxy for section as that will allow you access private IP space.

alt text

The steps are relatively similar on other browsers, this article seems to cover the steps on the other browsers:

You can also use the SOCKS 5 proxy in the command line if you install proxychains. After installing proxychains you can configure /etc/proxychains.conf like so:

remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000

socks5 9150

You can test like so:

proxychains curl

PAC File for all Devices:

For iOS to use a SOCKS proxy, I found the easiest solution was to setup a small HTTP server that only servers a custom PAC file that I wrote and to point at that file for automatic proxy configuration. This approach is actually beneficial as you can just point all your devices at the PAC file and make your config changes there for your clients connecting to SOCKS.

So let’s create the simple HTTP server and a PAC file.

First, let’s create a directory for the PAC file to live in:

mkdir -p /opt/http-proxy/html

Then create /opt/http-proxy/html/proxy.pac with the following contents:

function FindProxyForURL(url, host)

    // Allow direct connections for LAN traffic 
    if (isPlainHostName(host) ||
        shExpMatch(host, "*.local") ||
	isInNet(dnsResolve(host), "", "") ||
	isInNet(dnsResolve(host), "",  "") ||
	isInNet(dnsResolve(host), "",  "") ||
	isInNet(dnsResolve(host), "", ""))
        return "DIRECT";
     // Proxy traffic if none of the rules above match
     return "SOCKS";

Modify the SOCKS IP address at the end to match your server’s IP address – not

If you want a more complex config for your PAC file, I would look here, as I found this example very useful:

Then, you can setup a very simple HTTP server for the PAC file with the following one-liner:

docker run -p 80:80 -d --name http-pac -v /opt/http-proxy/html:/usr/local/apache2/htdocs httpd

If your server’s IP address was, there should be a file at that you can point your devices to for automatic configuration.

In iOS you can only configure the proxy per wireless network you connect to (which is dumb, but whatever) by going to Settings > Wi-Fi > the “I” icon > HTTP PROXY > Automatic. Set the URL to the URL of the PAC file.

alt text

In iOS this will make sure that when you are on the specified wireless network you will use the PAC file for your configuration. You will have to setup the proxy per wireless network if you made it always-available to your iOS device.

I won’t go into setting up a PAC file on Android as I don’t use an Android as my daily-driver anymore but it looks like the steps are pretty similar according to this article.

Back on desktop, you can also point your desktop browser to use automatic configuration instead of manually pointing at the SOCKS proxy. Here’s a screenshot:

alt text


Test out your setup by checking if your public IP address has changed when you visit

Assuming this all works, you should have a pretty similar setup to Apple’s Private Relay that is free, works across platforms and is not limited to Apple software. If you use Tor like this, I would recommend that you donate to the Tor Project.

Written on August 4, 2021