Search This Blog

Friday, December 27, 2019

Selling my compute cluster. Interested?

I'm selling the mini HPC cluster. The details of its creation and iterations are in this blog, but final specs are:
  • 5 nodes, 10 processors
  • 108 cores, 216 threads at 3+GHz each
  • 320 GB of RAM
  • Headnode: ASUS Z10PE-D8, 2x Xeon E5-2690V4 ES, 8x8GB 2Rx8 PC4-19200 ECC RDIMMs, 500GB Samsung 960 Evo NVMe, 2x 3TB HDD in RAID1, 480GB SSD, GTX Titan, CX354A FDR IB HCA. 
  • Compute nodes: Supermicro 6027TR-HTR, which has 4x identical nodes: 2x E5-2690v2, 8x8GB dual rank PC3-14900R ECC RDIMMs, 120GB SSD, CX354A FDR IB HCA 
  • Mellanox SX6005 FDR switch: 12 ports at 56 Gbit/s 
  • 2x 8 port unmanaged 1Gbe switches, one for IPMI, one for intranet 
  • Riello UPS: 3300VA, 2300W 
  • APC NetShelter CX Soundproof Server Cabinet with custom, automatic heat extraction system 
  • All cables
  • Working CentOS 7, OpenFOAM, python, OpenMPI, SLURM installations
3D printer not included

I know roughly what I could part it out for, but I'd like to try to find a buyer who would want to use it as a cluster. 

Asking price: $7k OBO


Been busy...

Back stateside again. Still very limited on room, though, so hobby progress has been limited.

Got the 3D printer recalibrated and set up on a shelf in the garage.

Wanhao i3 V2.1
Moved the filament spool off the top to the side. Bought a 16x16" tile for it to sit on, perfect size. Smoke alarm taped to the underside of the next shelf up (top left of picture). The filament dryer is the same one I had in England, so I have a 110V-220V power adapter sitting behind it. I found the same one in the US but for 110V power on eBay for $39 ("Rosewill" brand here), and I bought it so I can ditch the giant power adapter. The clear plastic cylinder parts should be the same, so I can extend it to hold 3-4 spools, which is nice. Printed an XYZ calibration cube and benchy first, then a new spool holder since the green one was on its last legs. Currently printing some wall mount holders for remotes for new ceiling fans we bought my mother in law for Christmas (guess who gets to install them...). 3D printer to-do: replace X belt and add belt tensioner.

I've been mentoring FloridaTech's Base11 space challenge team (Florida Tech Rocketry, FTR). The goal is to be the first university team to launch a liquid bipropellant rocket to space. I've been teaching them fluid systems analysis, fluid systems component selection, CFD, structural analysis, thermal analysis, basic design process, etc etc etc. They have a pretty solid preliminary rocket design and detailed engine and test stand design now. FIT promised to fund the whole thing, but you know how that goes...so currently looking at other funding options.

I've also been spending a lot of time over the past couple years working research contracts for various aerospace companies, most of them slosh CFD or slosh testing related. FIT has a large linear stage capable of shaking full scale spacecraft tanks, and we've designed and are fabricating a second one now. We got about half way through a NASA spacecraft tank test program before realizing we'd need a linear stage capable of much higher frequency excitation than the current one , or anyone has as far as I know...I mean, I guess there are vibration tables, but the excitation amplitude on those is tiny. The new linear stage should be capable of shaking 8000lb tanks at 6 Hz over ~4mm, which is kinda terrifying. Currently finishing fabrication on 1/5 scale upper stage propellant tank simulators. Slosh testing will start in about a month on those. My advisor and I wrote (so basically I wrote...) a proposal for another NASA slosh research project that got approved, so that's probably coming March-ish. I'm leading about 3 grad students and 4 undergrads working on these and some other aerospace/propulsion related projects.

Busy busy. So even though most of this blog is about my hobbies and not-rocket stuff, I am doing a lot of "rocket science", though I should have foreseen I wouldn't be at "MIT" for ever. Kinda dumb naming the blog that, oh well...live and learn.

As I tell the FTR team: "Skip all your classes, build rockets".

Thursday, February 21, 2019

OpenBSD and growfs: growing a partition

I didn't notice until recently, but the automatic partitioning scheme I used during installation left about half of the volume unused. I decided I want to add all of that space to my /home partition. If you have more than two partitions, e.g. root and swap, adding space to a partition that isn't the last is almost impossible without reinstalling. Luckily, and probably by design, /home is the last partition on the disklabel, so this should be simple.

First, backup all of your files. If your disk is sd0, run: disklabel sd0 . Compute how much space you have (units are sectors, which are 512 bytes) between the end of the last partition (probably /home) and the end of the volume. Now compute the new total size of the partition. Write those numbers down. Note the letter of the last partition, e.g. sd0k. Make sure nothing is running in the /home directory. cd to /, then run umount /home or umount /dev/sd0k (where k is the letter of your last partition). You may have to use the -f option to force it to unmount. Now run disklabel -E sd0 . This opens the interactive disklabel editor. Type "c" and enter (you can also use "m" instead of "c", see the man pages). It will show you the maximum size, which you can type in, or you can type in how much ever you want to grow the partition with a + number of sectors. Check the numbers it gives against what you calculated: the number it gives should be close, but slightly smaller. After that, type "q", enter, "yes", enter. That will exit the interactive editor and save changes. Now do: growfs sd0k . This will grow the filesystem to the size of the partition. Next, check the partition: fsck /dev/sd0k . Let this run until it's finished. Now mount the partition again: mount /dev/sd0k /home . Make sure your files are still there. Run disklabel sd0 one more time just to check. That's it!

Note: These steps works just fine for partitions on an encrypted volume: that's how mine is setup.

Unfortunately, there isn't an easy tool for shrinking partitions.

Links: 1 2 3

OpenBSD USB transfer speed woes, and a hack to get around that

One of the major problems with OpenBSD is how slow file transfers are to non-openbsd file systems. It has ports of various file system adapters, like ntfs-3g (which is based on FUSE) for reading/writing to NTFS formatted media. However, these have known speed issues that no one has bothered to fix yet.

As a test, I tried to copy files from the internal HDD to an external 8TB USB 3.0 HDD formatted NTFS. In Windows and various Linux distros, the sustained write speed is 70 MB/s+. In Openbsd, I plugged it into a confirmed usb 3 port (usbdevs -v), mounted it with ntfs-3g /dev/sd2j /mnt/usb1, and then tried to copy a large (>1GB) file to it with cp or rsync. Rsync has a progress option which shows write speeds. cp wasn't much if any faster. I couldn't get over 2.2 MB/s write speed with a USB 3.0 port, or over 1.6 MB/s with a USB 2.0 port. I tried the ntfs-3g mount options noatime and big_writes, but they had no affect on write speed. Openbsd's port doesn't have an async option. I also tried a USB 3.0 flash drive, also formatted NTFS, that can get higher write speeds than the external HDD in Windows, but it's even slower on the Openbsd laptop.

From what I've read online, there's literally nothing you can do unless you feel like re-writing ntfs-3g or something like that.

I found a hack around this limitation. I setup a ftp server (ftpd) on the openbsd computer and added the following pf firewall rules in an anchor:

pass in on $ext_if proto tcp from $lan_net to port 21
pass in on $ext_if proto tcp from $lan_net to port > 49151

I then enabled and started the ftpd service. I connected the USB HDD to my Windows machine (on same LAN as the openbsd computer), and did "add network location" in windows, ftp://xxx.xxx.xxx.xxx (IP of my openbsd computer) and logged in with the user account on the openbsd computer. This allowed me to browse files on the openbsd computer. I copied (ctrl+c ctrl+v) a large (>1GB) file from the openbsd computer to the usb hdd. Interestingly, window's transfer time estimate was too long...calculating speed from that, it was estimating ~2 MB/s. However, the actual average transfer speed was ~8.5MB/s. Thus, it's about 4x faster to transfer files from openbsd->FTP->Windows->USB HDD than openbsd->USB HDD. I didn't attempt any ways to speed this up, and the openbsd laptop's network adapter is limited to 100Mbps, so it might be possible to get higher transfer speeds.

Update: Hit ~13 MiB/s (12 continuous) running 2 file transfers with the filezilla client in windows. That's right at the upper limit of the 100 Mbit/s ethernet port on the openbsd machine. It could probably handle much faster with a gigabit connection.

If the X windows system didn't convince me, this example really showcases why openbsd is meant to be a server OS, and not a personal computer OS.

Wednesday, February 20, 2019

Headnode Wake-on-lan Support

In a previous post, I mentioned setting up DDNS with NoIP, configuring my router with the DDNS name, and configuring it to forward SSH traffic. This effectively lets me control the headnode, and thus the cluster, from anywhere in the world over SSH. However, I still have to leave the headnode on 24/7 in order to have access to it.

This is where wake-on-lan (wol) comes in. The most common approach is the "magic packet" approach, where a packet with the network adapter's mac address in a certain pattern is sent to the network adapter, thus telling it to wake the computer up. Your network adapter, motherboard, and PSU have to support it to work, which is where my first problem was. The ASUS Z10PE-D8 has two ethernet ports on board, but neither support wake-on-lan. This is not an oversight: ASUS specifically excluded that capability to try to get you to buy their management chip (ASMB8-iKVM), which is fairly expensive, though comes with a bunch of nice remote management features. Since I needed another port for internet anyways, I purchased a 4 port gigabit pcie card (IBM rebrand of Intel i340-t4) that supports wake-on-lan on port 1. After configuring the router and static IP for the new adapter, I could run ethtool (interface name) to examine its wake-on-lan capability. Sure enough, there was a "g" next to wake-on-lan, meaning it supports magic packets. Not all ethernet adapters support wake-on-lan...make sure the one you are planning to buy does before you buy it.

I followed various guides for implementing wake-on-lan. Links: 1 2 3. Originally, it was only meant to be used within a LAN. I found a windows powershell script (there are a bunch, just google them) that creates a magic packet based on the headnode internet interface's MAC address and then broadcasts it to 255.255.255.255. This successfully woke the headnode. However, more work needed to be done to be able to wake-on-lan over the internet.

I created another port forwarding rule ("virtual server" in my router) to forward UDP traffic from an external port to an internal port with the headnode's static IP address. Typical ports for wake on lan are 7 or 9, but I think you can use any. The headnode already has a static IP address, but I also had to create a static ARP assignment in the router, which binds a MAC address to that IP address. I already had DDNS setup with a hostname for my public facing IP. I modified the windows powershell script (on my laptop) to look up the IP address of a given hostname, gave it the cluster's DDNS hostname, changed the port to the external port I forwarded, logged into my VPN so that I would send the wake-on-lan packet from the external internet, and ran the script. Boom, wake-on-lan over internet. I also tested this using the "wake-on-lan" android app when connected to my cell network. There's a wakeonlan linux package, too. Many options to get this to work.

Security disclaimer: opening inbound ports in a router firewall is never without risks. Make sure your computer's firewall rules are setup correctly.

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.


Sunday, February 17, 2019

OpenBSD and wifi

Recently decided to attempt to use wifi + dhcp instead of static ethernet just for the learning experience. The openbsd networking FAQ, and the ifconfig man pages are pretty good resources for this.

There are many different wireless adapter brands/lines, and in bsd systems, they get their own name. So instead of all wireless adapters getting "wan0, wan1, etc", there could be ral0, ap0, etc. I had to create a hostname.if file for the wireless interface that included the nwid of the network I wanted to connect to (this can be scanned for with ifconfig) and the password in the format: "nwid MYWIFI wpakey MYPASSWORD", and then a second line with dhcp. Make sure you back up your original resolv.conf file: dhclient will overwrite it, though can control the dhclient's behavior with a /etc/dhclient.conf. For example, say you wanted to use a different name server, you could add a line to the dhclient.conf: "supersede domain-name-servers XXX.XXX.XXX.XXX". I have an openvpn up script that replaces this anyways, so I'm not concerned about it.

I then had to edit my pf.conf. I made a backup of the old one for the ethernet interface, then did the following: created a $wi_if variable for the wireless interface device, commented out the $ext_if lines, added "pass out on $wi_if to $lan_net" since the wireless network uses the same 192.168.1.X subnet, then changed the pass in and out rules on udp port 1197 (for VPN to establish) from the $ext_if to the $wi_fi. That's all. The "pass out on $wi_if to $lan_net" rule is necessary because the openvpn needs to be able to communicate over the original internet channel before establishing a connection (for DNS for example). I can comment this out and reload after the VPN channel is established. In fact, I should probably figure out some way cancel that rule once the VPN is established and then to only allow traffic to certain $lan_net IPs for ssh, scp, etc. That'd be more secure. pf can't discriminate based on program, but it can based on user. If a program was only used by a particular user, then it'd be even better to limit allowed connections to that user. Anyways, clearly there are some general improvements I could make to the firewall. I'll probably end up having to experiment with them.

Finally, I needed to run "sh /etc/netstart", which restarts all of the network connections, including starting openvpn. This brought the wifi interface up and started the openvpn connection, which takes longer because it keeps retrying until the wifi connection is established. After getting the firewall rules above correct, it worked. If the wireless connection drops, the vpn connection doesn't register it has been disconnected. I'm not sure how to go about fixing that. Every time it happens, I have to stop openvpn, then run "sh /etc/netstart" again. If you plan to use your openbsd laptop + openvpn with a wireless connection, I suggest writing some sort of script that monitors the wireless connection and does the above automatically.

"tcpdump -i wifi0 -y IEEE802_11_RADIO" (where wifi0 is your wireless adapter) is a nifty one-liner that will output current signal strength and noise of the wireless connection. Useful for finding a good place in the room to use your laptop.