Creating a BTSync encrypted read-only peer

Oct 18, 2015

Tag: linux

Update (January 23, 2016): encrypted folders are a standard feature since version 2.3 of Bittorrent Sync. As a consequence, you can now get the necessary keys from the user interface.

The problem

BitTorrent Sync is a peer-to-peer folder synchronisation utility. Its day-to-day use is comparable to cloud sync such as Dropbox, Google Drive, or OneDrive, however there is no central party that stores the data and coordinates synchronisation. Since there is no centralized storage and the user can decide who can read a folder, BitTorrent Sync provides more privacy and security.

Since Bittorrent Sync is a peer to peer system, at least one peer needs to be online to syncronize a particular folder. For this reason, many users use a NAS or other always-on machine to have a peer that is always visible. (E.g., we use a Raspberry Pi 2 as an always-on peer.)

Unfortunately, most residential internet connections have limited upstream bandwidth. Consequently, synchronizing with your always-on peer can be slow outside the confines of your home (or business) network. The obvious solution to this problem is to use a VPS or dedicated server in a well-connected data center as a (read-only) peer. However, this brings back some of the downsides of cloud-based solutions: if your peer is hacked or seized, a third party has access to all your synchronized data.

Shared keys

Luckily, Bittorrent Sync has an elegant solution, known as a encrypted read-only peer. Unfortunately, this feature is not advertised outside their key structure spec. To understand how this feature works, we will first do a quick run-down of how folders are shared in Bittorrent Sync. As of Bittorrent Sync 2.0, there are two types of folders:

Although the newer advanced folders offer more flexibility (such as changing access rights), only standard folders currently provide a solution to the `vulnerable cloud peer’ problem. To understand how this works, we have to dissect the mechanics of standard folders a bit. Normally, there are two types of keys: a read-write key and a read-only key. The read-write key starts with an A, followed by 160 bits of random material encoded in Base32. For example:

AKBI7V5S7ANHJTZ2VJ66M5KEAHLFQPYEP

Sync derives a couple of things (in)directly from this key:

Unfortunately, the spec is not completely clear on how the read-only and folder IDs are derived. I could not quickly reproduce the keys in most of the obvious ways (e.g. expanding the secret to 256 bit using SHA3 and generating the ED25519 keypair using that material). The mechanism has definitely changed since it was last reverse engineered.

The solution

Bittorrent Sync knows another type of read-write key that is described in the key structure spec. This key also consists of 160-bits of random material, but is prefixed by a D rather than A. The GUI does not provide an option to generate such a key. Luckily, it is easy to do so in a UNIX with some Python:

$ dd if=/dev/urandom bs=20 count=1 | \
  /usr/bin/python -c "import sys;import base64; sys.stdout.write(base64.b32encode(sys.stdin.read()))" | \
  sed 's/^/D/'

The change of A to D causes Bittorrent Sync to generate a read-only key twice the size (prefixed by E). The key now contains separate secrets for connecting to other peers and data encryption. Additionally, an encrypted read-only secret is created. This consists of the initial half of the read-only key and uses the prefix F. Peers that have this encrypted read-only secret can connect to and sync with other peers. However, they cannot decrypt the data, since they do not have the encryption key.

So, in our cloud scenario, this provides an elegant solution:

Luckily, the UI is pretty nice once you have generated a secret starting with D. Under the folder preferences, you can see all keys:

Viewing keys

Setting up a cloud peer

Setting up a Bittorrent Sync on a VPS is pretty easy. I won’t provide a copy-paste guide to set up a VPS, because security. But assuming that you set up a VPS with systemd (I use Debian stable on Scaleway) and have Bittorrent Sync installed in /opt/btsync, you can use the configuration below. The use of systemd gives us two advantages over e.g. System V init: (1) Bittorrent Sync can be restarted automatically if it crashes and (2) setting up instances for multiple users is easy.

Per-user configuration

Assuming that you have a user alex, create the directories .sync, btsync, btsync-aux:

$ mkdir .sync btsync btsync-aux

Create a self-signed keypair that will be used by the Bittorrent Sync web UI:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout .sync/sync.key -out .sync/sync.crt

Then create a file .sync/sync.conf with the following content:

{
  "storage_path" : "/home/alex/btsync-aux",
  "display_new_version": false,
  "disk_low_priority" : true,
  "lan_encrypt_data" : true,
  "rate_limit_local_peers" : false,
  "folder_rescan_interval" : 600,
  "folder_defaults.delete_to_trash" : true,
  "folder_defaults.use_lan_broadcast" : true,
  "folder_defaults.use_relay" : true,
  "folder_defaults.use_tracker" : true,
  "sync_trash_ttl" : 365,
  "folder_defaults.known_hosts" : "",
  "use_upnp" : false,
  "webui" :
  {
    "directory_root" : "/home/alex/btsync",
    "listen" : "127.0.0.1:8888",
    "force_https" : true,
    "ssl_certificate" : "/home/alex/.sync/sync.crt",
    "ssl_private_key" : "/home/alex/.sync/sync.key"
  }
}

If multiple users will have an instance on that host, you should give them unique port numbers. You can use the same setup for each Bittorrent Sync user.

You can check if the configuration works by starting Bittorrent Sync (as alex):

$ /opt/btsync/btsync --nodaemon --config /home/alex/.sync/sync.conf

You can stop Bittorrent Sync by sending a SIGINT signal (Ctrl-C)

systemd unit

Next, we will have to create a systemd unit file which can be used to control the lifecycle. We will use a unit file ending with @, so that we can start instances per user. Create the file /etc/systemd/system/btsync@.service with the following contents:

[Unit]
Description=BitTorrent Sync for %i

[Service]
Type=simple
User=%i
ExecStart=/opt/btsync/btsync --nodaemon --config /home/%i/.sync/sync.conf
WorkingDirectory=/home/%i
Restart=always

[Install]
WantedBy=multi-user.target

The configuration is pretty simple: the btsync command is invoked as before, though we are using variables in to set the correct username. Moreover, the Restart policy is set to always so that btsync will be restarted when it exits.

You can now start/stop/restart the Bittorrent Sync instance for the user alex with:

$ sudo systemctl start btsync@alex.service
$ sudo systemctl stop btsync@alex.service
$ sudo systemctl restart btsync@alex.service

If you want to start the instance automatically during boot:

$ sudo systemctl enable btsync@daniel.service

Accessing the web interface

To add folders using read-only encrypted secrets, use the web interface (click the gear, and then Manual connection). Although the web interface is protected using a user/password combination set up during the first use, you probably do not want to expose it to the net. For this reason, the configuration above binds it to localhost. To access the web interface on http://localhost:8888, set up an SSH tunnel to your VPS:

$ ssh -L 8888:localhost:8888 <your-VPS>

Also, if you are using the Pro of Bittorrent Sync version locally, create a new identity for the cloud peer (otherwise, it would get access to any read-write or read-only secrets that you use).

Note: To avoid that Sync needs relay servers, look up the port in the preferences, and ensure that it is not blocked by your firewall.