How to use snowflake proxies with the Tor daemon

You may already be familiar with Tor bridges when using Tor Browser. Tor bridges allow you to bypass internet censorship, and have the ability to mask the fact that you are using Tor to your ISP or any potential snoopers along your path to the internet. With Tor, you also have the option of utilizing a similar but more advanced way to circumvent censorship using snowflake proxies. As described by Tor;

Snowflake is a pluggable transport available in Tor Browser to defeat internet censorship. Like a Tor bridge, a user can access the open internet when even regular Tor connections are censored.

Source

Using snowflake proxies in Tor Browser is easy, and described in Tor’s documentation. However, the same can’t be said for using snowflake proxies while running the Tor daemon on your macOS or Linux machine. There are many reasons for wanting to run your own Tor daemon on your machine, such as SOCKS proxying various applications through Tor at all times.

This guide will show you how you can utilize snowflake proxies via snowflake-client with your Tor daemon’s configuration file (torrc) on macOS and Linux.

How To:

Run snowflake-client on macOS

This guide assumes that you have Homebrew installed.

Step 1: Install Tor & snowflake-client.

brew install tor
brew install snowflake

Step 2: Check if the Tor daemon is running. The output should be similar to what you see below.

user@machine ~ % brew services info tor
tor (homebrew.mxcl.tor)
Running: ✔
Loaded: ✔
Schedulable: ✘
User: user
PID: 1354

If it’s not running, start the service to see if it works.

brew services start tor

Step 3: Find and edit your torrc file.

If you installed Tor with Homebrew, the default path should be;

/opt/homebrew/etc/tor/torrc

Go ahead and edit this file with your favorite text editor.

Replace any text in the file with the following configuration. Note, if you do not trust the computer you are on, you will want to remove the -log option.

UseBridges 1

ClientTransportPlugin snowflake exec /opt/homebrew/bin/snowflake-client -url https://snowflake-broker.azureedge.net/ -front ajax.aspnetcdn.com -ice stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn -log /opt/homebrew/var/log/snowflake-client.log                                                                                     
                                                                                                                                                                                  
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72                                                                                                            
#Bridge snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA

You may need, or wish to tweak some of the parameters in the configuration such as the -url, -ampcache, -front or -ice endpoints. If you are trying to circumvent censorship, and the above configuration does not work, you may get some ideas of what other endpoints you can use from these pages:

Step 4: Restart Tor

Once you’ve placed the configuration in your torrc file, you need to restart the Tor daemon with the below command.

brew services restart tor

You can now tail or cat the log file if you have it enabled, to see if snowflake-client is being executed and receiving offers from the snowflake broker. If it’s working, you should see something similar to the following log output.

/opt/homebrew/var/log/tor.log
Dec 03 03:29:02.000 [notice] Catching signal TERM, exiting cleanly.
Dec 03 03:29:03.979 [notice] Tor 0.4.8.9 running on Darwin with Libevent 2.1.12-stable, OpenSSL 3.2.0, Zlib 1.2.12, Liblzma N/A, Libzstd N/A and Unknown N/A as libc.
Dec 03 03:29:03.980 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://support.torproject.org/faq/staying-anonymous/
Dec 03 03:29:03.980 [notice] Read configuration file "/opt/homebrew/etc/tor/torrc".
Dec 03 03:29:03.981 [notice] Opening Socks listener on 127.0.0.1:9050
Dec 03 03:29:03.982 [notice] Opened Socks listener connection (ready) on 127.0.0.1:9050
Dec 03 03:29:03.000 [warn] Cannot find maximum file descriptor, assuming: 256
Dec 03 03:29:03.000 [notice] Parsing GEOIP IPv4 file /opt/homebrew/Cellar/tor/0.4.8.9/share/tor/geoip.
Dec 03 03:29:04.000 [notice] Parsing GEOIP IPv6 file /opt/homebrew/Cellar/tor/0.4.8.9/share/tor/geoip6.
Dec 03 03:29:04.000 [notice] Bootstrapped 0% (starting): Starting
Dec 03 03:29:04.000 [notice] Starting with guard context "bridges"
Dec 03 03:29:04.000 [notice] Delaying directory fetches: No running bridges
Dec 03 03:29:04.000 [notice] new bridge descriptor 'flakey10' (cached): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey10 [1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko] at 192.0.2.3
Dec 03 03:29:05.000 [notice] Bootstrapped 1% (conn_pt): Connecting to pluggable transport
Dec 03 03:29:05.000 [notice] Bootstrapped 2% (conn_done_pt): Connected to pluggable transport
Dec 03 03:29:05.000 [notice] Bootstrapped 10% (conn_done): Connected to a relay
Dec 03 03:29:10.000 [notice] Managed proxy "/opt/homebrew/bin/snowflake-client": offer created
Dec 03 03:29:10.000 [notice] Managed proxy "/opt/homebrew/bin/snowflake-client": broker rendezvous peer received
Dec 03 03:29:12.000 [notice] Managed proxy "/opt/homebrew/bin/snowflake-client": connected
Dec 03 03:29:12.000 [notice] Bootstrapped 14% (handshake): Handshaking with a relay
Dec 03 03:29:12.000 [notice] Bootstrapped 15% (handshake_done): Handshake with a relay done
Dec 03 03:29:12.000 [notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits
Dec 03 03:29:12.000 [notice] Bootstrapped 95% (circuit_create): Establishing a Tor circuit
Dec 03 03:29:13.000 [notice] new bridge descriptor 'flakey3' (fresh): $2B280B23E1107BB62ABFC40DDCC8824814F80A72~flakey3 [1zOHpg+FxqQfi/6jDLtCpHHqBTH8gjYmCKXkus1D5Ko] at 192.0.2.3
Dec 03 03:29:13.000 [notice] Bootstrapped 100% (done): Done

If everything works, then you can start pointing applications on your machine to the default SOCKS proxy running on 127.0.0.1 port 9050. That will force the application to use Tor with snowflake proxies.

Run snowflake-client on Linux

This guide assumes that you are running a Debian based Linux distribution (such as Ubuntu). Many of the steps here may work on other Linux distributions, just with different commands.

Step 1: Install Tor & snowflake-client.

For installing Tor, follow the official steps to do so on Tor’s website.

For installing snowflake-client, you can either build it from source or install it via your Debian based distribution’s apt repository. For example, to install it on Debian or Ubuntu you can simply run;

apt install snowflake-client

Step 2: Check if the Tor daemon is running. The output should be similar to what you see below. The service should be enabled on boot by default.

user@machine:~$ sudo systemctl status tor
● tor.service - Anonymizing overlay network for TCP (multi-instance-master)
     Loaded: loaded (/lib/systemd/system/tor.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2023-12-03 05:04:45 EST; 3min 8s ago
    Process: 6627 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 6627 (code=exited, status=0/SUCCESS)
        CPU: 2ms

Dec 03 05:04:45 machine systemd[1]: tor.service: Deactivated successfully.
Dec 03 05:04:45 machine systemd[1]: Stopped Anonymizing overlay network for TCP (multi-instance-master).
Dec 03 05:04:45 machine systemd[1]: Stopping Anonymizing overlay network for TCP (multi-instance-master)...
Dec 03 05:04:45 machine systemd[1]: Starting Anonymizing overlay network for TCP (multi-instance-master)...
Dec 03 05:04:45 machine systemd[1]: Finished Anonymizing overlay network for TCP (multi-instance-master).

Step 3: Find and edit your torrc file.

By default on Debian based Linux distributions, the torrc file can be found at;

/etc/tor/torrc

Go ahead and edit this file with your favorite text editor using sudo.

Replace any text in the file with the following configuration. If your path to the snowflake-client is different, you’ll need to change that. Note, if you do not trust the computer you are on, you will want to remove the -log option.

UseBridges 1

ClientTransportPlugin snowflake exec /usr/bin/snowflake-client -url https://snowflake-broker.azureedge.net/ -front ajax.aspnetcdn.com -ice stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn -log /var/log/tor/snowflake-client.log

Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72
#Bridge snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA

You may need, or wish to tweak some of the parameters in the configuration such as the -url, -ampcache, -front or -ice endpoints. If you are trying to circumvent censorship, and the above configuration does not work, you may get some ideas of what other endpoints you can use from these pages:

Step 4: Restart Tor

Once you’ve placed the configuration in your torrc file, you need to restart the Tor daemon with the below command.

sudo systemctl restart tor

You can now tail or cat the log file with sudo if you have it enabled, to see if snowflake-client is being executed and receiving offers from the snowflake broker. If it’s working, you should see something similar to the following log output.

/var/log/tor/snowflake-client.log
--- Starting Snowflake Client ---
2023/12/03 10:04:45 Using ICE servers:
2023/12/03 10:04:45 url: stun:stun.voipgate.com:3478
2023/12/03 10:04:45 url: stun:stun.sonetel.com:3478
2023/12/03 10:04:45 url: stun:stun.voys.nl:3478
2023/12/03 10:04:45 url: stun:stun.bluesip.net:3478
2023/12/03 10:04:45 url: stun:stun.dus.net:3478
2023/12/03 10:04:45 Rendezvous using Broker at: https://snowflake-broker.torproject.net.global.prod.fastly.net/
2023/12/03 10:04:45 Domain fronting using: foursquare.com
2023/12/03 10:04:45 Started SOCKS listener at [scrubbed].
2023/12/03 10:04:46 NAT Type: unrestricted
2023/12/03 10:04:47 SOCKS accepted: {[scrubbed]   map[]}
2023/12/03 10:04:47 ---- SnowflakeConn: begin collecting snowflakes ---
2023/12/03 10:04:47 ---- SnowflakeConn: starting a new session ---
2023/12/03 10:04:47 WebRTC: Collecting a new Snowflake. Currently at [0/1]
2023/12/03 10:04:47 snowflake-18911604d8b442c8  connecting...
2023/12/03 10:04:47 redialing on same connection
2023/12/03 10:04:47 ---- SnowflakeConn: begin stream 3 ---
2023/12/03 10:04:47 WebRTC: DataChannel created.
2023/12/03 10:04:47 WebRTC: Created offer
2023/12/03 10:04:47 WebRTC: Set local description
2023/12/03 10:04:57 WebRTC: PeerConnection created.
2023/12/03 10:04:57 Negotiating via BrokerChannel...
Target URL:  snowflake-broker.torproject.net.global.prod.fastly.net 
Front URL:   foursquare.com
2023/12/03 10:04:59 BrokerChannel Response:
200 OK

2023/12/03 10:04:59 Received answer: [scrubbed]
2023/12/03 10:05:01 WebRTC: DataChannel.OnOpen
2023/12/03 10:05:01 WebRTC: At capacity [1/1]  Retrying...
2023/12/03 10:05:01 ---- Handler: snowflake assigned ----
2023/12/03 10:05:02 Traffic Bytes (in|out): 9143 | 14480 -- (13 OnMessages, 35 Sends)
2023/12/03 10:05:07 Traffic Bytes (in|out): 24386 | 22076 -- (49 OnMessages, 41 Sends)

If everything works, then you can start pointing applications on your machine to the default SOCKS proxy running on 127.0.0.1 port 9050. That will force the application to use Tor with snowflake proxies.