Friday 23 September 2022

Fight Internet Censorship - Run a Snowflake Proxy

 Why run a snowflake proxy?

News reports indicate that current events caused a sharp increase in blocked or limited internet accessibility in several countries. One option to circumvent these measures is to use a TOR browser. Also available on mobile phones - e.g. Onion Browser for iOS.

In the cable tray under my desk, there lives a Raspberry Pi

As one method to aid circumventing DNS, IP and routing measures, you can run a snowflake proxy. Your PC or server temporarily registers with a public broker as a snowflake proxy. A user's TOR browser will ask the broker for the address of a snowflake proxy, which will give access to the TOR network. Snowflake is one of several bridging techniques that can be chosen in the browser if it can't connect to the TOR network directly.

Snowflake Schematic (originally from here)

Can I get in trouble for running a snowflake proxy?

If you live in a healthy democracy, it is most unlikely to get into trouble for running a snowflake proxy. Other than running a TOR Exit Node (very bad idea!), your IP address won't show up in any web server logs.

Can anyone do bad things over my connection?

Yes. But you will never know, as all communication is encrypted. Like any technology, TOR can be used for good and bad. - I decided that at this moment the benefits outweigh the risks. I hope that will change some time soon.

If you don't run a dedicated server, consider running snowflake as a plugin for Firefox or chrome, so you can help while surfing the web.

Will it eat up my Internet bandwidth?

That depends. It does not even remotely for me, but I have the luxury of a super stable 100/40 MBit/s DSL connection.

Set up Snowflake on a Raspberry Pi

There are several tutorials on the web, but none worked flawlessly 1st try. So here is my take. I assume you have a basic knowledge of Linux/Unix.

Fetch the current version of the GO programming language for the Raspi:

me@myhost:$ wget

--2022-09-22 14:32:59--
.... much Output deleted .....
go1.19.1.linux-armv6l.tar 100%[===================================>] 111,29M  1,38MB/s    in 33s
2022-09-22 14:33:32 (3,42 MB/s) - »go1.19.1.linux-armv6l.tar.gz« saved [116690970/116690970]

Unpack that to /usr/local (or wherever you like it best):

me@myhost:$ sudo tar -C /usr/local -xzf go1.19.1.linux-armv6l.tar.gz

You can get rid og the archive to free up the space:

me@myhost:$ rm go1.19.1.linux-armv6l.tar.gz

Add the location of the go binary to your path to make things easy:

me@myhost:$ vi ~/.profile

At the end of the file simply add these two lines:


Save that (ESC : w q)

You can now either log off and on again, or type

me@myhost:$ source ~/.profile

to update the environment variables.

If you haven't installed git already, do so by typing:

me@myhost:$ sudo apt install git

If you have a preferred directory where you build your stuff, cd to there. Otherwise just type:

me@myhost:$ git clone

Then change to the proxy subdirectory:

me@myhost:$ cd snowflake
me@myhost:$ cd proxy

And build the snowflake proyx:

me@myhost:$ go build

Once that has completed, you can run it right from where you are:

me@myhost:~/snowflake/proxy $ ./proxy -verbose

2022/09/24 14:01:55 starting
2022/09/24 14:01:56 WebRTC: Created offer
2022/09/24 14:01:56 WebRTC: Set local description
2022/09/24 14:01:56 Offer:... OUTPUT REMOVED
2022/09/24 14:02:25 NAT Type measurement: unknown -> restricted = restricted
2022/09/24 14:02:25 NAT type: restricted
2022/09/24 14:02:35 sdp offer successfully received.
2022/09/24 14:04:48 OnDataChannel
2022/09/24 14:04:48 Connection successful.
2022/09/24 14:04:48 OnOpen channel
2022/09/24 14:10:56 connected to relay: wss://
2022/09/24 14:10:58 OnClose channel
2022/09/24 14:10:58 Traffic throughput (up|down): 8 KB|11 KB -- (43 OnMessages, 16 Sends, over 15 seconds)
2022/09/24 14:10:58 copy loop ended
2022/09/24 14:10:58 datachannelHandler ends

It might take a while for someone to actually connect. Don't worry if you see time-outs.

CTRL-C ends the process. On a Raspberry Pi, you'll probably want to run the proxy even while logged off. My way of doing that is not what you'd want for a permanent installation. As I do a lot of experimental stuff on the Raspi, I like to manually start what I want to run:

me@myhost:$ nohup ./proxy > ~/snowflake.log 2>&1 &

That has the downside that you manually have to kill the process when you want to stop it. 

me@myhost:$ kill -9 $(pidof proxy)

Some extra load on the Raspi

The proxy takes a fair bit of CPU power from the Raspberry. But it never even comes close to using the full capacity and the sub processes balance nicely over the four cores of my somewhat aged pi.

Moderate extra load on the Raspberry Pi

Sniffing snowflake traffic on your network

You can actually find out where the users using your proxy are located. As the clients connect (well, it is UDP, so strictly speaking "connect" is not quite right) to your proxy, you can use tcpdump for a quick analysis:

me@myhost:$ sudo tcpdump -i eth0 -s 1500 port not 22 and port not 53

On the output, look out for UDP traffic. There will be some lines looking like this:
18:09:46.914455 IP > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.914894 IP > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.915551 IP > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.915987 IP > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.916724 IP > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.917321 IP > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.918309 IP > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.919010 IP > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.919814 IP > 188.208.20Y.XXX.39043: UDP, length 1265

To protect the user, I edited out the full IP.
The IP (or possibly hostname, if it can be resolved) can be fed to the excellent Domain Dossier web site from for analysis.

The Network whois record will show who owns that network and where the company is located. In this case it is (no wonder at this moment) in Teheran, Iran.
That result was to be expected
From a brief observation, I see almost exclusively IPs from providers in Iran, Iraq and Russia.

The slowflake log

When not in verbose mode, the proxy logs to stdout (or in my case to snowflake.log) hourly and reports some statistics:
me@myhost:~ $ tail -f snowflake.log
2022/09/18 04:12:49 In the last 1h0m0s, there were 7 connections. Traffic Relayed ↑ 1 GB, ↓ 87 MB.
2022/09/18 05:12:49 In the last 1h0m0s, there were 8 connections. Traffic Relayed ↑ 3 MB, ↓ 487 KB.
2022/09/18 06:12:49 In the last 1h0m0s, there were 20 connections. Traffic Relayed ↑ 327 MB, ↓ 34 MB.
2022/09/18 07:12:49 In the last 1h0m0s, there were 17 connections. Traffic Relayed ↑ 14 MB, ↓ 4 MB.
2022/09/18 08:12:49 In the last 1h0m0s, there were 34 connections. Traffic Relayed ↑ 46 MB, ↓ 18 MB.
2022/09/18 09:12:49 In the last 1h0m0s, there were 15 connections. Traffic Relayed ↑ 23 MB, ↓ 12 MB.
2022/09/18 10:12:49 In the last 1h0m0s, there were 40 connections. Traffic Relayed ↑ 286 MB, ↓ 70 MB.
2022/09/18 11:12:49 In the last 1h0m0s, there were 19 connections. Traffic Relayed ↑ 46 MB, ↓ 15 MB.
2022/09/18 12:12:49 In the last 1h0m0s, there were 27 connections. Traffic Relayed ↑ 134 MB, ↓ 35 MB.
2022/09/18 13:12:49 In the last 1h0m0s, there were 13 connections. Traffic Relayed ↑ 32 MB, ↓ 3 MB.

The traffic volume varies widely from a few MBytes s to a GByte per hour.