Title: Some OpenBSD features that aren't widely known | |
Author: Solène | |
Date: 20 February 2024 | |
Tags: openbsd unix | |
Description: In this article, you will learn about some OpenBSD | |
features you may not know about | |
# Introduction | |
In this blog post, you will learn about some OpenBSD features that can | |
be useful, but not widespread. | |
They often have a niche usage, but it's important to know they exist to | |
prevent you from reinventing the wheel :) | |
OpenBSD official project website | |
# Features | |
The following list of features are not all OpenBSD specific as some can | |
be found on other BSD systems. Most of the knowledge will not be | |
useful to Linux users. | |
## Secure level | |
The secure level is a sysctl named `kern.securelevel`, it has 4 | |
different values from level -1 to level 2, and it's only possible to | |
increase the level. By default, the system enters the secure level 1 | |
when in multi-user (the default when booting a regular installation). | |
It's then possible to escalate to the last secure level (2), which will | |
enable the following extra security: | |
* all raw disks are read-only, so it's not possible to try to make a | |
change to the storage devices | |
* the time is almost lock, it's only possible to modify the clock | |
slowly by small steps (maybe 1 second max every so often) | |
* the PF firewall rules can't be modified, flushed or altered | |
This feature is mostly useful for dedicated firewall with rules that | |
rarely change. Preventing the time to change is really useful for | |
remote logging as it allows being sure of "when" things happened, and | |
you can be assured the past logs weren't modified. | |
The default security level 1 already enable some extra security like | |
"immutable" and "append-only" file flags can't be removed, these | |
overlooked flags (that can be applied with chflags) can lock down files | |
to prevent anyone from modifying them. The append-only flag is really | |
useful for logs because you can't modify the content, but this doesn't | |
prevent adding new content, history can't be modified this way. | |
OpenBSD manual pages: securelevel | |
OpenBSD manual pages: chflags | |
This feature exists in other BSD systems. | |
## Memory allocator extra checks | |
OpenBSD's memory allocator can be tweaked, system-wide or per command, | |
to add extra checks. This could be either used for security reasons or | |
to look for memory allocation related bugs in a program (this is VERY | |
common...). | |
There are two methods to apply the changes: | |
* system-wide by using the sysctl `vm.malloc_conf`, either immediately | |
with the sysctl command, or at boot in `/etc/sysctl.conf` (make sure | |
you quote its value there, some characters such as `>` will create | |
troubles otherwise, been there...) | |
* on the command line by prepending `env MALLOC_OPTIONS="flags" | |
program_to_run` | |
The man page gives a list of flags to use as option, the easiest to use | |
is `S` (for security checks). It is stated in the man page that a | |
program misbehaving with any flag other than X is buggy, so it's not | |
YOUR fault if you use malloc options and the program is crashing | |
(except if you wrote the code ;-) ). | |
OpenBSD manual pages: malloc (search for MALLOC OPTIONS) | |
## File flags | |
You are certainly used to files attributes like permissions or | |
ownership, but on many file systems (including OpenBSD ffs), there are | |
flags as well! | |
The file flags can be altered with the command `chflags`, there are a | |
couple of flags available: | |
* nodump: prevent the files from being saved by the command `dump` | |
(except if you use a flag in dump to bypass this) | |
* sappnd: the file can only be used in writing append mode, only root | |
can set / remove this flag | |
* schg: the file can not be change, it becomes immutable, only root can | |
alter this flag | |
* uappnd: same as sappnd mode but the user can alter the flag | |
* uchg: same as schg mode but the user can alter the flag | |
As explained in the secure level section above, in the secure level 1 | |
(default !), the flags sappnd and schg can't be removed, you would need | |
to boot in single user mode to remove these flags. | |
Tip: remove the flags on a file with `chflags 0 file [...]` | |
You can check the flags on files using `ls -ol`, this would look like | |
this: | |
``` | |
terra$ chflags uchg get_extra_users.sh | |
terra$ ls -lo get_extra_users.sh | |
-rwxr-xr-x 1 solene solene uchg 749 Apr 3 2023 get_extra_users.sh | |
terra$ chflags 0 get_extra_users.sh | |
terra$ ls -lo get_extra_users.sh | |
-rwxr-xr-x 1 solene solene - 749 Apr 3 2023 get_extra_users.sh | |
``` | |
OpenBSD manual pages: chflags | |
## Crontab extra parameters | |
OpenBSD crontab format received a few neat additions over the last | |
years. | |
* random number for time field: you can use `~` in a field instead of a | |
number or `*` to generate a random value that will remain stable until | |
the crontab is reloaded. Things like `~/5` work. You can force the | |
random value within a range with `20~40` to get values between 20 and | |
40. | |
* only send an email if the return code isn't 0 for the cron job: add | |
`-n` between the time and the command, like in `0 * * * * -n | |
/bin/something`. | |
* only run one instance of a job at a time: add `-s` between the time | |
and the command, like in `* * * * * -s /bin/something`. This is | |
incredibly useful for cron job that shouldn't be running twice in | |
parallel, if the job duration is longer than usual, you are ensured it | |
will never start a new instance until the previous one is done. | |
* no logging: add `-q` between the time and the command, like in `* * * | |
* -q /bin/something`, the effect will be that this cron job will not be | |
logged in `/var/cron/log`. | |
It's possible to use a combination of flags like `-ns`. The random | |
time is useful when you have multiple systems, and you don't want them | |
to all run a command at the same time, like in a case they would | |
trigger a huge I/O on a remote server. This was created to prevent the | |
usual `0 * * * * sleep $(( $RANDOM % 3600 )) && something` that would | |
run a sleep command for a random time up to an hour before running a | |
command. | |
OpenBSD manual pages: crontab | |
## Auto installing media | |
One cool feature on OpenBSD is the ability to easily create an | |
installation media with pre-configured answers. This is done by | |
injecting a specific file in the `bsd.rd` install kernel. | |
There is a simple tool named upobsd that was created by semarie@ to | |
easily modify such bsd.rd file to include the autoinstall file, I | |
forked the project to continue its maintenance. | |
In addition to automatically installing OpenBSD with users, ssh | |
configuration, sets to install etc... it's also possible to add a | |
site.tgz archive along with the usual sets archives that includes files | |
you want to add to the system, this can include a script to run at | |
first boot to trigger some automation! | |
These features are a must-have if you run OpenBSD in production, and | |
you have many of them to manage, enrolling a new device to the fleet | |
should be automated as possible. | |
GitHub project page: upobsd | |
OpenBSD manual pages: autoinstall | |
## apmd daemon hooks | |
Apmd is certainly running on most OpenBSD laptop and desktop around, | |
but it has features that aren't related to its command line flags, so | |
you may have missed them. | |
There are different file names that can contain a script to be run upon | |
some event such as suspend, resume, hibernate etc... | |
A classic usage is to run `xlock` in one's X session on suspend, so the | |
system will require a password on resume. | |
Older blog post: xlock from apmd suspend script | |
The man page explains all, but basically this works like this for | |
running a backup program when you connect your laptop to the power | |
plug: | |
```shell | |
# mkdir -p /etc/apm | |
# vi /etc/apm/powerup | |
``` | |
You need to write a regular script: | |
```shell | |
#!/bin/sh | |
/usr/local/bin/my_backup_script | |
``` | |
Then, make it executable | |
```shell | |
# chmod +x /etc/apm/powerup | |
``` | |
The daemon apmd will automatically run this script when you connect a | |
system back to AC power. | |
The method is the same for: | |
* hibernate | |
* resume | |
* suspend | |
* standby | |
* hibernate | |
* powerup | |
* powerdown | |
This makes it very easy to schedule tasks on such events. | |
OpenBSD manual page: apmd (section FILES) | |
## Using hotplugd for hooks on devices events | |
A bit similar to what apmd by running a script upon events, hotplugd is | |
a service that allow running a script when a device is added / removed. | |
A typical use is to automatically mount an USB memory stick when | |
plugged in the system, or start cups daemon when powering on your USB | |
printer. | |
The script receives two parameters that represents the device class and | |
device name, so you can use them in your script to know what was | |
connected. The example provided in the man page is a good starting | |
point. | |
The scripts aren't really straightforward to write, you need to make a | |
precise list of hardware you expect and what to run for each, and don't | |
forget to skip unknown hardware. Don't forget to make the scripts | |
executable, otherwise it won't work. | |
OpenBSD manual page: hotplugd | |
## Altroot | |
Finally, there is a feature that looks pretty cool. In the daily | |
script, if an OpenBSD partition `/altroot/` exists in `/etc/fstab` and | |
the daily script environment has a variable `ROOTBACKUP=1`, the root | |
partition will be duplicated to it. This permit keeping an extra root | |
partition in sync with the main root partition. Obviously, it's more | |
useful if the altroot partition is on another drive. The duplication | |
is done with `dd`. You can look at the exact code by checking the | |
script `/etc/daily`. | |
However, it's not clear how to boot from this partition if you didn't | |
install a bootloader or created an EFI partition on the disk... | |
OpenBSD manual pages: hier (hier stands for file system hierarchy) | |
OpenBSD manual pages: daily | |
OpenBSD FAQ: Root partition backup | |
## talk: local chat in the terminal | |
OpenBSD comes with a program named "talk", this creates a 1 to 1 chat | |
with another user, either on the local system or a remote one (setup is | |
more complicated). This is not asynchronous, the two users must be | |
logged in the system to use `talk`. | |
This program isn't OpenBSD specific and can be used on Linux as well, | |
but it's so fun, effective and easy to setup I wanted to write about | |
it. | |
The setup is easy: | |
```shell | |
# echo "ntalk dgram udp wait root /u… | |
# rcctl enable inetd | |
# rcctl start inetd | |
``` | |
The communication happens on localhost on UDP ports 517 and 518, don't | |
open them to the Internet! If you want to allow a remote system, use a | |
VPN to encrypt the traffic and allow ports 517/518 only for the VPN. | |
The usage is simple, if you want alice and bob to talk to each other: | |
* alice type `talk bob`, and bob must be logged in as well | |
* bob receives a message in their terminal that alice wants to talk | |
* bob type `talk alice` | |
* a terminal UI appears for both users, what they write will appear on | |
the top half of the UI, and the messages from recipient will appear on | |
the half bottom | |
This is a bit archaic, but it works fine and comes with the base | |
system. It does the job when you just want to speak to someone. | |
# Conclusion | |
There are interesting features on OpenBSD that I wanted to highlight a | |
bit, maybe you will find them useful. If you know cool features that | |
could be added to this list, please reach me! |