Building DynFi Firewall
DynFi Firewall is a modern firewall based on FreeBSD. The software is fully open sourced, but having a fully open sourced system isn’t enough these days. Almost 40 years ago Ken Thompson in his article “Reflections on trusting trust” showed us that software that can’t be built and verified by the community shouldn’t be trusted. Following his idea we would like to show how to build DynFi Firewall step-by-step. This is exactly the same process used in the release process of the software.
The DynFi Firewall uses standard FreeBSD build mechanisms. What is innovative however is that it also uses a package base which isn’t so popular yet. In case of the ports the firewall uses poudriere with an overlay for building. Overlays are also a new technique which allows to merge multiple ports trees into a single one.
Thanks to these techniques we are able to keep all our changes in separate repositories and easily merge them with next quarterly ports branches.
Before we start the prerequisite is to install a couple tools required by the build system.
First one is poudriere. At the time of writing the article, the overlays are not yet in the release of poudriere available in FreeBSD. Because of that the easiest way is to fetch the main poudriere branch and install it from the official repo - https://github.com/freebsd/poudriere.
As well we also have to install a jq(1) which is a command-line JSON processor.
# pkg install jq
The build scripts are prepared to build everything in the user directory. However there are some tools, like poudriere, which require root privileges.
Because of that we also require that the user has root access through sudo(8).
The firewall is built from couples of repositories. All source code is hosted publicly on GitHub.
The project is splitted into following repositories:
- FreeBSD-base - its a FreeBSD repository with the custom changes used by the firewall
- dynfi-overlay - it’s a ports overlay, this repository contains all additional or modified ports required by the Firewall
- dynfi-build - it’s a set of building scripts used to build a DynFi Firewall
We will start by fetching the dynfi-builder.
$ git clone https://github.com/DynFi/dynfi-build
The FBSD_TREE variable in common.subr allows us to point where the FreeBSD-base repo is located. By default the location is in the dynfi-build directory. Let’s pull it to that directory.
$ cd dynfi-build $ git clone https://github.com/DynFi/FreeBSD-base freebsd
The build system is prepared to work in multiuser environments, or multi-poudriere instances.
Because of that all poudriere files are kept in a private user directories. To set up all necessary environment variables required by poudriere we prepared a
poudriere.sh script. This script is a wrapper to a default poudriere instance with all settings required to build a project in the home directory.
First we have to choose a FreeBSD ports branch we want to use.
Currently DynFi Firewall is built based on the 2021Q2 branch. We simply use
poudriere.sh to fetch this branch.
$ sh poudriere.sh ports -c -p 2021Q2 -B 2021Q2 [00:00:00] Creating 2021Q2 fs at /usr/home/buildtest/dynfi-build/poudriere-base/ports/2021Q2... done [00:00:00] Cloning the ports tree... done $
The command above will fetch the 2021Q2 ports branch to poudriere under the ports name 2021Q2.
Next step is to create a port with the
dynfi-overlay. We can use the same technique as in the previous exemple.
In this case we will just tell poudriere not to use the official repository but the one hosted on GitHub.
The ports name used by the build system is
dynfi-overlay, this can be changed in common.subr file under
$ sh poudriere.sh ports -c -p dynfi-overlay -m git+https -U ‘https://github.com/DynFi/dynfi-overlay‘ [00:00:00] Creating dynfi-overlay fs at https://github.com/DynFi/dynfi-overlay... done [00:00:00] Cloning the ports tree... done $
The DynFi Firewall uses signed packages. For this reason when building a system you have to also create signatures. Unfortunately this breaks a reproducible mechanism as the packages will have different signatures than the one you will see in official repositories - in feature we will work on providing a more robust way of verifying that.
The signing keys should be placed in the keys directory.
To create a singing key you can follow a method described in pkg-repo(8) man page which is:
$ openssl genrsa -out pkg-dff.key 2048 $ chmod 0400 pkg-dff.key $ openssl rsa -in pkg-dff.key -out pkg-dff.pub -pubout
This step is always required however if you want to use the official DynFi repository you don’t have to modify anything more.
If you would like to configure our own pkg repository you have to modify the
usr.sbin/pkg/DynFi-base.conf to point to our ports server and upload the signature to the
The file and the directory are in freebsd repo.
When we pull all of the repositories and we have signing keys we can start building the Firewall.
First we can start by building a DynFi World and Kernel. We can simply use a
$ sh build_base.sh Building world and kernel [...]
After this first step, we are ready to build the required ports.
This can be done by
build_packages.sh. This will build both the packages required for the install image as well as the packages required for the installer.
In upcoming features we can also try to separate those two. We provide -c option to the script to indicate that this is a clean build and everything should be rebuilded.
For the next build we can skip this option to speed up the process.
$ sh build_packages.sh -c Building the poudriere jail [00:00:00] Error: No such jail: dynfi-13-stable [00:00:00] Creating dynfi-13-stable fs at /usr/home/buildtest/dynfi-build/poudriere-base/jails/dynfi-13-stable... done [00:00:00] Checking out the sources with git+http... [...]
Finally we can build an installer with a simple script
build_installer.sh. New installers with vga and serial support will be built in the image directory.
$ sh build_installer.sh [.../usr/home/buildtest/dynfi-build/image/dynfi_installer_serial_0.99.021-20211031-222857.iso: 1.519:1, 5.265 bits/byte, 34.19% saved, 672233472 in, 442410256 out.] [...] /usr/home/buildtest/dynfi-build/image/dynfi_installer_vga_0.99.021-20211031-222857.iso: 1.519:1, 5.265 bits/byte, 34.19% saved, 672233472 in, 442410256 out.
When this step is done we can use new iso images to install the DynFi firewall.
If we have setup the ports server we can upload them using the
build_sync.sh script. This script will upload everything to the ports server.
Just remember to adjust the IP server in the common.subr file under the
DynFi Firewall is a modern firewall with a simple building mechanism. Mechanism uses unique methods like overlays or package bases.
Besides using those uniqueness mechanisms the whole process is wrapped up in a couple of simple to understand scripts.
If you like this article, please try to buy your devices from our e-shop ;-) This will allow the project to smoothly grow and provide you with more cutting edge features.