hyperreal.coffee

Setup a FreeBSD thick VNET jail for torrenting Anna’s Archive

Setup the VNET bridge

Create the bridge.

1ifconfig bridge create

Attach the bridge to the main network interface. igc0 in this case. For some reason, the resulting bridge device is named igb0bridge, rather than bridge0.

1ifconfig igb0bridge addm igc0

To make this persistent across reboots, add the following to /etc/rc.conf.

1defaultrouter="10.0.0.1"
2cloned_interfaces="igb0bridge"
3ifconfig_igc0bridge="inet 10.0.0.8/24 addm igc0 up"

Create the classic (thick) jail

Create the ZFS datasets for the jails. We’ll use basejail as a template for subsequent jails.

1zfs create -o mountpoint=/jails naspool/jails
2zfs create naspool/jails/basejail

Use the bsdinstall utility to bootstrap the base system to the basejail.

1export DISTRIBUTIONS="base.txz"
2export BSDINSTALL_DISTSITE=https://download.freebsd.org/ftp/releases/amd64/14.2-RELEASE/
3bsdinstall jail /jails/basejail

Run freebsd-update to update the base jail.

1freebsd-update -b /jails/basejail fetch install
2freebsd-update -b /jails/basejail IDS

We now snapshot the basejail and create a clone of this snapshot for the torrenting jail that we will use for Anna’s Archive.

1zfs snapshot naspool/jails/basejail@`freebsd-version`
2zfs clone naspool/jails/basejail@`freebsd-version` naspool/jails/torrenting

We now use the following configuration for /etc/jail.conf.

 1torrenting {
 2    exec.consolelog = "/var/log/jail_console_${name}.log";
 3    allow.raw_sockets;
 4    exec.clean;
 5    mount.devfs;
 6    devfs_ruleset = 11;
 7    path = "/jails/${name}";
 8    host.hostname = "${name}";
 9    vnet;
10    vnet.interface = "${epair}b";
11    $id = "127";
12    $ip = "10.0.0.${id}/24";
13    $gateway = "10.0.0.1";
14    $bridge = "igb0bridge";
15    $epair = "epair${id}";
16    
17    exec.prestart = "/sbin/ifconfig ${epair} create up";
18    exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}";
19    exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up";
20    exec.start += "/sbin/ifconfig ${epair}b ${ip} up";
21    exec.start += "/sbin/route add default ${gateway}";
22    exec.start += "/bin/sh /etc/rc";
23    exec.stop = "/bin/sh /etc/rc.shutdown";
24    exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a";
25    exec.poststop += "/sbin/ifconfig ${epair}a destroy";
26}

Now we create the devfs ruleset to enable access to devices under /dev inside the jail. Add the following to /etc/devfs.rules.

1[devfsrules_jail_vnet=11]
2add include $devfsrules_hide_all
3add include $devfsrules_unhide_basic
4add include $devfsrules_unhide_login
5add include $devfsrules_jail
6add path 'tun*' unhide
7add path 'bpf*' unhide

Enable the jail utility in /etc/rc.conf.

1sysrc jail_enable="YES"
2sysrc jail_parallel_start="YES"

Start the jail service for torrenting jail.

1service jail start torrenting

Setting up Wireguard inside the jail

Since we have the /dev/tun* devfs rule, we now need to install Wireguard inside the jail.

1jexec -u root torrenting
2
3pkg install wireguard-tools wireguard-go

Download a Wireguard configuration for ProtonVPN, and save it to /usr/local/etc/wireguard/wg0.conf.

Enable Wireguard to run when the jail boots up.

1sysrc wireguard_enable="YES"
2sysrc wireguard_interfaces="wg0"

Start the Wireguard daemon and make sure you are connected to it properly.

1service wireguard start
2
3curl ipinfo.io

The curl command should display the IP address of the Wireguard server defined in /usr/local/etc/wireguard/wg0.conf.

Setting up qBittorrent inside the jail

Install the qbittorrent-nox package.

1pkg install -y qbittorrent-nox

Before running the daemon from /usr/local/etc/rc.d/qbittorrent, we must run the qbittorrent command from the shell so that we can see the default password generated for the web UI. For some reason it is not shown in any logs, and the qbittorrent nox manpage wrongly says the password is “adminadmin”.

1pkg install -y sudo
2sudo -u qbittorrent qbittorrent-nox --profile=/var/db/qbittorrent/conf --save-path=/var/db/qbittorrent/Downloads --confirm-legal-notice 

Copy the password displayed after running the command. Login to the qBittorrent web UI at http://10.0.0.127:8080 with login admin and the password you copied. In the web UI, open the options menu and go over to the Web UI tab. Change the login password to your own. Save the options to close the menu.

Now press CTRL-c to stop the qbittorrent-nox process. Make the following changes to the torrenting jail’s /etc/rc.conf.

1sysrc qbittorrent_enable="YES"
2sysrc qbittorrent_flags="--confirm-legal-notice"

Enable the qBittorrent daemon.

1service qbittorrent start

Go back to the web UI at http://10.0.0.127:8080. Go to the options menu and go over to the Advanced tab, which is the very last tab. Change the network interface to wg0.

Finding the forwarded port that the ProtonVPN server is using

Install the libnatpmp package.

Make sure that port forwarding is allowed on the server you’re connected to, which it should be if you enabled it while creating the Wireguard configuration on the ProtonVPN website. Run the natpmpc command against the ProtonVPN Wireguard gateway.

1natpmpc -g 10.2.0.1

If the output looks like the following, you’re good.

1initnatpmp() returned 0 (SUCCESS)
2using gateway : 10.2.0.1
3sendpublicaddressrequest returned 2 (SUCCESS)
4readnatpmpresponseorretry returned 0 (OK)
5Public IP address : 62.112.9.165
6epoch = 58081
7closenatpmp() returned 0 (SUCCESS)

Now create the UDP and TCP port mappings, then loop natpmpc so that it doesn’t expire.

1while true ; do date ; natpmpc -a 1 0 udp 60 -g 10.2.0.1 && natpmpc -a 1 0 tcp 60 -g 10.2.0.1 || { echo -e "ERROR with natpmpc command \a" ; break ; } ; sleep 45 ; done

The port allocated for this server is shown on the line that says “Mapped public port XXXXX protocol UDP to local port 0 lifetime 60”. Port forwarding is now activated. Copy this port number and, in the qBittorrent web UI options menu, go to the Connections tab and enter it into the “Port used for incoming connections” box. Make sure to uncheck the “Use UPnP/NAT-PMP port forwarding from my router” box.

If the loop terminates, you’ll need to re-run this loop script each time you start a new port forwarding session or the port will only stay open for 60 seconds.

P2P NAT port forwarding script with supervisord

Install supervisord.

1sudo pkg install -y py311-supervisor

Enable the supervisord service.

1sudo sysrc supervisord_enable="YES"

Edit /usr/local/etc/supervisord.conf, and add the following to the bottom of the file.

1[program:natpmpcd]
2command=/usr/local/bin/natpmpcd
3autostart=true

Add the following contents to a file at /usr/local/bin/natpmpcd.

 1#!/bin/sh
 2
 3port=$(/usr/local/bin/natpmpc -a 1 0 udp 60 -g 10.2.0.1 | grep "Mapped public port" | awk '{print $4}')
 4echo $port | tee /usr/local/etc/natvpn_port.txt
 5
 6while true; do
 7    date
 8    if ! /usr/local/bin/natpmpc -a 1 0 udp 60 -g 10.2.0.1 && /usr/local/bin/natpmpc -a 1 0 tcp 60 -g 10.2.0.1; then
 9        echo "error Failure natpmpc $(date)"
10        break
11    fi
12    sleep 45
13done

Ensure the script is executable with chmod +x /usr/local/bin/natpmpcd.

supervisord will start the above shell script automatically. Ensure supervisord service is started.

1sudo service supervisord start

The script will print out the forwarded port number at /usr/local/etc/natvpn_port.txt.

1cat /usr/local/etc/natvpn_port.txt
248565

Reply to this post by email ↪