Search This Blog

Tuesday, February 19, 2019

OpenBSD, OpenVPN, and a bittorrent client

Foreword

I do not use or condone the use of torrenting software for the illegal sharing of copyrighted material, i.e. piracy. This post is for promoting the use of torrents for legal file sharing and for informational purposes.

Most of this post will be useful to other operating systems and VPN clients. The only part specific to OpenBSD is the PF firewall rules.

Bittorrent

Despite the nefarious reputation of torrenting, it is a pretty amazing technology that has legitimate purposes. Bittorrent is a file transfer protocol. The typical way you download a file from the internet is as follows: you find the file download link of the file you want, you click it which sends a request to the server, a connection is established, and the file server serves you the file. There are many protocols, e.g. FTP, but regardless of the protocol used the whole file is hosted on a server somewhere, and you download the whole file from that server. If the person/company hosting the file server is risk-averse, they have backup file servers in case the primary one goes down, but that's not always the case. For "free" files like Linux distros, a common practice is to have multiple mirrors, which are file servers that have copies of the file, so even if the primary source and some of the mirrors go down, you can still download the file from another mirror. Bittorrent is different. In order to improve robustness, a file that is served with bittorrent is broken up into many smaller pieces. The computers that are currently downloading ("peers") or have fully downloaded the file serve ("seed") these pieces to other computers that are downloading ("leechers"). This is called a "swarm". A computer downloading might pull parts of a file from 100 different sources. A torrent file (.torrent) contains how the pieces go together and information about the "tracker", but doesn't contain any of the actual file to be downloaded. A tracker is a server that handles creating connections between peers, and it doesn't store or process any of the file to be transferred. A more modern approach uses distributed hash tables (DHT), removing the single failure point of the tracker for establishing connections. The bittorrent protocol reduces strain on the file server (no single central file server that has to do all of the serving), vastly improves redundancy/robustness, and can work well with low network bandwidths and dropouts. It's also tamper resistant. If a hacker gains access to a central file server, the hacker can compromise all of the files being served from that server. With bittorrent, each piece of the file to be downloaded has a cryptographic hash computed for it when the torrent was created and these are stored in the .torrent file. If a piece is modified, the hash changes, and the bittorrent client (the piece of software running on a computer doing the downloading and seeding) knows to reject that piece. A computer wishing to download a file has to obtain a copy of the file's .torrent file, which the bittorrent client interprets, communicates with the tracker/DHT thus creating connections, downloads pieces, and assembles the file, all without a central file server. Pretty cool, right? 

Unfortunately, it has not been widely adopted for legal purposes, likely due to its association with illegal file sharing of copyrighted material. It's also partially due to the greedy nature of humans: in order for a bittorrent system to work, the files have to be seeded by multiple sources, which implies leaving the fully downloaded file on your machine for a long time and seeding it (letting others use your upload network bandwidth). This is, of course, rare, and so a common problem with both legal and illegal torrents is a lack of seeders. In the illegal realm, there are "private trackers" that enforce strict rules on the ratio of seeded data to downloaded data, but as their name suggests, they are private, hidden, hard-to-get-into communities. In the legal realm, what often happens is similar to the central file server with mirrors topology mentioned earlier: a central server that initiated the torrent shares the file with its mirrors, which then also seed the torrent. Users (leechers) download the file, but don't necessarily have to seed it (though it would help with speeds if everyone did). The various advantages over a single server serving the file are still present, but it feels less democratic because the people using the file aren't sharing it. An example of this would be ubuntu distro downloads via torrents. Another reason widespread adoption hasn't occurred is the relative simplicity on the user end of http or ftp file transfers: click a link to download, vs. installing and configuring torrent client, finding torrent files with seeders, etc. 

Many network operators outright block the normal ports used for bittorrent, though due to its ability to operate on udp or tcp on any port, it's impossible to completely block without packet inspection techniques. That's where a VPN comes in: since VPNs encrypt the network traffic going through them, packet inspection techniques don't work. As mentioned in a previous post, VPNs are also useful for maintaining privacy while online.

Using a Bittorrent Client To Share Files

As mentioned earlier, a bittorrent client is a piece of software running on your computer that handles the uploading and downloading of files. There are many different ones, but for the purposes of the rest of this post, I will use qBittorrent, which is an open source version of uTorrent. 

In order to start a file download, you need to obtain through normal download channels a .torrent file or magnet link of the file you wish to download and open it with the torrent client. The client then connects to the tracker(s) listed in the .torrent file to help find connections, or directly finds other peers via DHT. Then the client connects directly to the peers in order to request pieces and send pieces, thus becoming part of a swarm. The client may also report progress to trackers to help the tracker with its peer recommendations. When the client has all of the pieces of the file, it assembles them, and then starts sharing the file as a seeder instead of a peer.

Many clients have a built in function for creating your own .torrent file from a file you wish to share. In qbittorrent, go to Tools->Torrent Creator. Navigate to the file or folder you want to share. It will automatically calculate the number of pieces to split it into. If you want it to be private, i.e. you send the .torrent file to the people you want to share the file with, then you can select don't share with DHT network and don't put any public tracker urls in the box. If you want to share it publicly, then don't check the private box and put a few public tracker announcement urls in the corresponding box. You can add comments and other data, too. Then click create torrent. That's all there is to it. It's definitely easier than setting up your own file server, and I think it takes less than time than uploading to a file share site, e.g. google drive, and creating a sharing link...it certainly isn't harder. 

Another cool thing: some clients, including qbittorrent, can be used as trackers. This is useful for sharing files among a small group of people.

Hopefully you now have a good understanding of how torrenting works. The following sections will show how to set up qbittorrent on openbsd with an openvpn vpn. 

Firewall Rules 

Properly implement firewalls help reduce security risks by controlling network traffic. The next two sections detail the general firewall requirements when not use a VPN and when using a VPN. These should be applicable to all operating systems. I assume that your setup is a single host (computer) behind a router. More complicated network architectures will require more complicated settings. I discuss OpenBSD-specific firewall rules further down.

Generally, unless you're using a security hardened OS or firewall, all outbound connections on a host are allowed by default. This kind of makes sense: if a program is making an unwanted outbound connection request from your computer, then it has already compromised your system. Out going connections will use a random network port, and you can block outbound ports and connections using firewall rules. On the contrary, most inbound ports are blocked by default. Some common ones, like the ones used for ssh, http, etc. might be open by default. Inbound ports can be opened using firewall rules, which allow inbound connections to be made. Depending on your firewall, you can restrict the a rule to apply to a specific protocol (tcp, udp) network device, IP address, or program. Note that once a connection is established, data can flow either direction, regardless of whether the connection originated from an outbound or inbound request.

Without a VPN

In this example, the bittorrent client is on a host (computer) with a firewall that is connected to a router that has its own firewall, and the router is connected to the internet. The network interface device on the host that connects to the router will be called "ext1" that has an IP address of 10.0.1.1. for this example, and the computer has another network device connected to the router called "ext2" with an IP address of 10.0.1.2. These IP address are static IP addresses are assigned to the host network devices in the host OS and by the router. DHCP (dynamic IP addresses) are not ideal for firewall rule creation because if the IP address of the network device changes, and a firewall rule was created for the previous IP address, it will no longer apply.

If your host firewall allows outbound connections by default, then host firewall rules for the bittorrent client aren't necessary because it will be able to create outbound connections by default. If you want to restrict the client's outbound connections to a certain network device, e.g. ext1, or IP address, e.g. 10.0.1.1, then you can do that with firewall outbound rules. This is useful if you want the bittorrent traffic to only go over a certain network interface. Some bittorrent clients allow you to select the network interface to use, but they might switch to another if that one becomes unavailable for whatever reason, so firewall rules are safer.

If your host firewall blocks outbound connections by default, you'll need to allow the bittorrent client to make any outbound tcp and udp connection. If you want to restrict the client's outbound connections to a certain network device, e.g. ext1, or IP address, e.g. 10.0.1.1, then you only allow connections over that device or from that IP address.

Your router's firewall will probably allow outbound connections by default. If so, you don't need to do anything with the router's firewall configuration. If not, in the case of custom router firewalls, then you will need allow all outbound udp and tcp traffic from the desired host device's IP, e.g. 10.0.1.1. Router firewalls will block inbound connections by default.

The bittorrent client should now work fine. It will be able to make outbound connections to peers and seeds. Once the connections are established, you can both download and seed. However, seeds and peers will not be able to find you because your router firewall and host firewall block incoming connections by default. This limits the number of connections you can make, which limits your net download and upload speeds. If upnp is enabled on your router firewall and host, the client might be able to accept inbound connections. However, UPnP has security flaws (think about it...allows remote connections to bypass a firewall...not good) and should almost always be disabled if any part of the network interfaces with the internet.

So, without upnp, how do we allow inbound connections to the bittorrent client? The first step is to select an inbound port number. You want to choose one in the range 49152-65535 because these are "unregistered" to any specific piece of software. I will call this the "listening port". Next, create an inbound host firewall rule allowing tcp and udp connections over the listening port. It's good practice to restrict this "hole" in the firewall as much as possible. For example, you can restrict the open inbound port to connections made via the ext1 interface, or to ext1's IP address (10.0.1.1), and (if possible) only for the bittorrent client program. Next, set the listening port in the bittorrent client to the one you chose; if your client doesn't allow you to pick it, you need to find out which port it listens on for inbound connections and use that as the listening port. The last step is to allow the inbound connection through your router firewall. This is where "port forwarding" comes in. In your firewall's advanced settings, look for "virtual server" or "port forwarding". You want your router to forward inbound traffic aimed at your public facing IP address on the listening port to your internal IP address, e.g. 10.0.1.1., on the listening port. Create the port forwarding rule for both TCP and UDP protocols with the external and internal ports the same as the listening port, and the internal IP as the IP of the host network device, e.g. ext1's 10.0.1.1. That should be all of the necessary firewall rules.

To test this setup, start up our bittorrent client (with the listening port you chose earlier) and have it start downloading or seeding a file. This means the client will be actively listening on the listening port. Go to canyouseeme.org. It should find your public facing IP address. Change the port to your listening port and click "check port". It should say success: this means you can accept incoming connections, which should vastly improve torrent performance. If you get an error, your firewall rules are probably not correct.

Bittorrent client tips: deselect any of the following connection options: "use upnp/NAT", "use different port on each start up", "random port". If you can select the network device to use (might be in advanced options), do so, so it doesn't use a random device that you don't have firewall rules setup for.

With a VPN

Using a torrent client with a VPN is recommended. In fact, I recommend using a VPN all of the time. Whoever is watching the torrents can see which IP address the pieces are going to, and thus see who is downloading the file...not necessarily a problem for legal file transfers, but this is the most common way people who download illegal files get caught. However, if you use a VPN, the VPN server's IP address is the one the pieces are seen going to. If the VPN provider is bad, they keep internal logs that correlate their users' IP addresses with their server IP addresses. If the VPN provider is in the US, they can be court-ordered to keep logs, which can then be subpoenad. So, rules to follow: get a VPN with servers outside of the US, and use one that (at least says) doesn't keep logs. This doesn't prevent people from doing something dumb and getting caught, though. For example, if you sign in to a website, e.g. gmail, when accessing the VPN, then your VPN IP is now associated with everything you do during that session. Anyways, OPSEC is not the point of this post.

The setup is almost the same as the case without the a VPN (read first paragraph, previous section), except now a VPN tunnel is created through the router to the VPN server. A virtual network device will be created that has its own IP address, and the VPN server's firewall will take the job of your router's firewall. Thus, your router settings and firewall are irrelevant now, i.e. don't do any port forwarding in your router settings.

The host firewall rules will be the same as the without a vpn example, except applied to the new VPN virtual interface device and IP address instead of the physical interface device (ext1 in the last example). It's a good idea to block all connections for the client program on all devices except for the VPN virtual device and its IP address. You'll also want to change your default gateway to the IP address of your VPN interface. These rules force all traffic through the VPN. If this is not desired, you can implement fancy routing rules to route certain traffic through the VPN and certain traffic on the normal interface to your router.

The VPN server's firewall will allow all outbound traffic and block all inbound traffic (except maybe for certain commonly used ports).

The bittorrent client should now work fine. It will be able to make outbound connections to peers and seeds. Once the connections are established, you can both download and seed. However, seeds and peers will not be able to find you because the VPN server's firewall and host firewall block incoming connections by default. This limits the number of connections you can make, which limits your net download and upload speeds. VPN servers do not enable upnp, so make sure you disable that in your bittorrent client.

Setting up port forwarding is different than the previous example. The first step is to get a forwarded port from your VPN provider (make sure they offer this service, not all do). If they do offer this service, you usually can't choose which port is forwarded, they just assign you one. I will call this the "listening port". Next, create an inbound host firewall rule allowing tcp and udp connections over the listening port. It's good practice to restrict this "hole" in the firewall as much as possible. For example, you can restrict the open inbound port to connections made via the virtual VPN interface, or to its IP address, and (if possible) only for the bittorrent client program. Next, set the listening port in the bittorrent client to the one given to you by the VPN provider; if your client doesn't allow you to change it, you should use a different client. Don't setup any port forwarding rules in your router...they aren't necessary due to the VPN tunnel. That should be all of the necessary firewall rules.

To test this setup, start up our bittorrent client (with the listening port you chose earlier) and have it start downloading or seeding a file. This means the client will be actively listening on the listening port. Go to canyouseeme.org. It should find your public facing IP address. Change the port to your listening port and click "check port". It should say success: this means you can accept incoming connections, which should vastly improve torrent performance. If you get an error, your firewall rules are probably not correct.

Bittorrent client tips: deselect any of the following connection options: "use upnp/NAT", "use different port on each start up", "random port". If you can select the network device to use (might be in advanced options), set it to the virtual VPN device, so it doesn't use a random device that you don't have firewall rules setup for.

OpenVPN Setup

I cover most of the steps required to get OpenVPN + PIA working in a previous post. I'll cover the changes I've made since then in this section.

PIA only offers port fowarding on certain servers. I copied my previous ovpn configuration to a new one, then deleted all but one of the servers from that list. I changed the auth-user-pass line to "auth-user-pass /path/to/pia-login.txt", where the pia-login.txt contains my PIA username on one line and my password on the second line. This link shows how to encrypt and decrypt the credentials file, but I didn't implement that. Instead, I just made it readable and writeable by root only, and since openvpn has to be launched by root, this works fine. My reasoning is that if someone compromises the computer enough to get root access, your PIA credentials will be the least of your concerns. I added logging with "log-append /var/log/openvpn/openvpn", which is useful for debugging, though I'll probably switch that off in the future. I modified the up and down script lines to point to new scripts, which I'll talk about momentarily, and changed the "up" to a "route-up".

The old scripts only changed the DNS settings by replacing the resolv.conf file. The new up and down scripts still do that, but also do a lot more.

Note: gateway changes are still handled by the openvpn's "redirect-gateway def1" option.

Up Script 

First, the up script checks if the physical interface is active. If it isn't, then the VPN can't be active, so it exits. Next, it waits for the VPN to connect. If it takes longer than 120s to connect, then even if it connects later, PIA won't assign a port number, so it exits. Once it's connected, it changes the DNS settings. Then it asks a PIA server for forward port assignment via curl. Finally, it changes the firewall settings (discussed below).

The up script has to be called by a helper script that runs the up script in the background and then exits (exit 0). The reason for this is that, as a security measure (therefore by design), OpenVPN will not allow any packets to traverse the tunnel while any script which was started by the openvpn binary is still executing, which causes curl to fail. The helper script sort of tricks openvpn into thinking its done running setup scripts, thus allowing traffic through the connection. The helper script has to be called by the "route-up" openvpn option instead of the normal "up" because the former waits for the connection to be fully established.

Script link below.

Down Script

First, the down script undoes the changes the up script made to the DNS. Then it changes the firewall settings back to the way they were before the up script ran. Script link below.

Improved PF Settings

I made a lot of changes to my PF firewall settings to improve functionality and security. Here's my new pf.conf (with some stuff obscured, and many comments removed):
#header lines...
wi_if = "iwn0"
ext_if = "ext0"
ovpn_if = "tun0"
lan_net = "192.168.X.X/24" 
# don't filter on loopback interface
set skip on lo 
# scrub incoming packets
match in all scrub (no-df) 
#default: block everything
block 
#antispoofing:
block in quick from urpf-failed 
# only allow ssh connections from LAN. Can restrict to a few IP's later.
#pass in on $ext_if inet proto tcp from $lan_net to $ext_if port ssh flags S/SA synproxy state 
pass out on $ovpn_if proto { tcp udp icmp } all keep state 
# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010 
# Port build user does not need network
block return out log proto {tcp udp} user _pbuild 
anchor "piaopenvpnsetup"{
    pass out on $ext_if to 192.168.X.X #this is the router gateway IP
    pass out on $ext_if proto udp from self to any port 1197
anchor piaportforward
Anchors allow for dynamic rule changes. Inline anchors (anchors with their rules specified in the pf.conf file), e.g. piaopenvpnsetup, are read and implemented at boot The piaopenvpnsetup anchor's rules are only necessary during the setup of the openvpn connection. The first rule is necessary so that DNS can resolve the PIA server's (listed in the .ovpn file) IP address. The second rule is necessary for PIA to establish the connection. They are flushed (removed) by the openvpn up script after the connection is established. They are added back in by the openvpn down script.

Anchors that don't have the rules inline, nor specify a path to a file with rules in it, e.g. piaportforward, are not implemented at boot. This rule is only loaded when the anchor-piaportforward file is created and the command pfctl -a piaportforward -f /etc/anchor-piaportforward is run by the up script. The down script flushes this anchor's rule. The rule is: pass in on $ovpn_if proto { tcp udp } from any to $ovpn_if port 12345 , where the port number is the port assigned by PIA in the up script. Even though the rules aren't defined in pf.conf, the "anchor piaportforward" line in pf.conf is critical. I spent about 6 hours trying to figure out why this anchor's rules weren't being applied before finding that in a tutorial somewhere. You can actually load the anchor without that line in the pf.conf, and pfctl -a piaportforward -s rules will show the rules as active, but they won't actually be active, so don't forget that line.

qBittorrent Installation and Launcher Script

Installing qbittorrent on openbsd is easy: pkg_add qbittorrent . You then launch it and its GUI manually with qbittorrent (gui-less version is called "qbittorrent-nox" I think). You can then go in and make the settings changes recommended above.

If your forwarded port changes, then it'd be nice to be able to update qbittorrent's listening port automatically. I created a launching script that does that. First, it checks to see if qbittorrent is running or not. If it is not, it launches it. Then it uses the Web API and curl to update the listening port.

Scripts

Link to the scripts.

OSs that have PIA Client Support

The PIA client supports many operating systems. It works similar to OpenVPN, but is much easier to setup and use. If your system is supported, I suggest using it. Requesting a forwarded port is as simple as click a check box in the settings, and the port is displayed on the client's gui. You should still make your own firewall rules, and you'll have to adjust the qbittorrent listening port, but it handles all of the VPN configuration stuff for you.

Possibly Useful Links


Final Words

Have fun. Don't do illegal shit.


No comments:

Post a Comment