25 years of OpenBSD Security Tools: syslock and sysunlock

If you missed the overview post, you can see it here. This one is about managing immutable and append-only files on *BSD, Linux, and macOS. Immutable and Append-Only Files BSD-derived operating systems (including macOS) and Linux both support the concept of files being made immutable, so that neither their contents nor attributes can be changed. They also both support files being made append-only, so that the existing contents cannot be changed except by adding more data to the end. They do it in slightly different ways. ...

June 5, 2026 · 17 min

25 years of OpenBSD security tools

I’ve been using and administering OpenBSD systems since 1999 (OpenBSD 2.5). During that time, I’ve written numerous scripts to make things easier, more automated, or more secure, or sometimes just to improve my understanding of how things work. When I started managing my home systems, I ran several Internet-exposed services on my home network (DNS, mail, web, SSH). I used djbdns, qmail, and Apache httpd at the start before switching to nsd/unbound for DNS and postfix for mail, and finally to OpenSMTPD for mail. When I got tired of excessive inbound traffic I moved my authoritative DNS to a provider while keeping an internal zone and resolvers, set up two cloud servers for mail and my public webserver. My home network became a hardened, minimal-exposure architecture that only allows Wireguard from expected sources and mail (after mutual TLS authentication with certificates) while continuing to run internal services. ...

June 2, 2026 · 5 min

Tips on using OpenBSD's pledge and unveil in perl scripts

 OpenBSD 5.9 (current as of this post is 7.5) introduced the "pledge" system call and 6.4 introduced the "unveil" system call, which together provide a means of more granular control of system access by processes running on the system to enforce least privilege.  When a program calls "pledge", it provides a list of categories of system calls (called "promises") that it is planning to make during the life of the running process (children have to make their own pledges and are not restricted), and attempts to make calls outside of those areas will cause the call to be blocked and the process to be killed. Additional calls to pledge cannot add new categories but it can remove them, so access can become more restrictive but not less restrictive. ...

August 4, 2024 · 7 min

Google Bard on file system immutability flags in OpenBSD

 Unlike ChatGPT, Bard pretty much nailed it on the initial prompt. (However, Bard refused to answer my questions about the Mars Effect like the ones I gave to ChatGPT, even when reworded to be clear I was asking for descriptions of what the effect is and what explanations are offered rather than asking it to identify causes itself.) It does lose points for grammar in the second sentence, though! write a few paragraphs explaining immutable flags in OpenBSD including the commands for setting them and the difference between system and user immutable flags Sure. Here is a few paragraphs explaining immutable flags in OpenBSD, including the commands for setting them and the difference between system and user immutable flags. ...

April 19, 2023 · 3 min

Some nonsense from ChatGPT about file system immutability flags in OpenBSD

 I was thinking about writing a blog post about file system immutability flags in OpenBSD, and thought I'd ask ChatGPT to write it for me. It appears to have gleaned its content from OpenBSD man pages, but it is highly misleading and inaccurate, misrepresenting the key distinction between system and user immutability flags. What it got right is that only the superuser (root) can set and unset the system immutability flag (schg/noschg) while users (if they own the file) can set and unset the user immutability flag (uchg/nouchg). But either flag can be set or unset on any kind of file. ...

January 21, 2023 · 8 min

A few thoughts on OpenBSD 5.8

I’ve been using OpenBSD since way back at release 2.3 in 1998, so I’ve gone through upgrades that took a fair amount of work due to incompatible changes, like the switch from ipf to pf for host firewalling or the change to ELF binaries. The upgrade from 5.7 to 5.8 was a pretty smooth and easy one, for the most part. The two most painful changes for me were the replacement of sudo with doas and the dropping of support in the rc.conf for the pf_rules variable. While sudo is still available as a package, I like the idea of reducing attack surface with a simpler program, so I made the switch. The two things I miss most about sudo are the ability to authenticate for a period of time and the ability to have a single config file across a whole set of servers. The former I’m just living with, the latter I’ve adjusted to by having a single config file that has lines commented out depending on which server it’s on. I did have one moment of concern about the quality of doas when it incorrectly reported the line number on which I had a syntax error in the config file–fortunately, this was just a failure to increment the line count on continuation lines (ending with a “") which is fixed in the -current release. The removal of the pf_rules variable support from rc.conf was a bigger issue–I used to just put the default pf.conf rules file in place with each release and upgrade, and keep my changes in a pf.conf.local file that was specified in the pf_rules variable. The effect was that from the period after the upgrade until I noticed the change, my systems were using the default rules and thus more exposed than they were supposed to be. This wasn’t the first time an incompatible change decreased my level of security–the removal of tcpwrappers support from SSH was another. I used to use a combination of pf rules and hosts.allow as additional layers of protection on my SSH access, and had a set of tools that allowed me to easily add IP addresses to or remove them from my hosts.allow files. This would have been a layer of defense still in place with the loss of my pf rules, had it still been in existence. Fortunately, I also have SSH on a non-standard port and only allow SSH key logins, not user/password logins, and most of my systems can’t be reached on any port without first making a VPN connection, which requires two-factor authentication. A minor annoying change that was made in 5.8 was putting the file /var/unbound/db/root.key into /etc/changelist, so that the file gets checked daily by the security script. The issue with this is that if you are actually using unbound with DNSSEC, this file changes daily, though only in the comments. My “reportnew” log monitoring tool has a feature that allows you to be notified if files that are expected to change on some periodic schedule do not change, and that would be more appropriate than getting daily notifications that yes, the autotrust anchor file has been updated yet again. But what would really be ideal here would be a check that the non-comment components have not changed. (Others have also complained about this.) A final issue I’ve run into with OpenBSD 5.8 is not a new issue, but it’s one that still hasn’t been fixed with pf. That is that pf logs certain traffic (IGMP in particular) when it matches a rule that does not call for logging. This appears to be the same issue that was fixed earlier this year in pfsense, which is derived from an older fork of pf.

November 23, 2015 · 3 min

How to use Google Authenticator with OpenBSD, OpenSSH, and OpenVPN--and why you might not want to

I thought that Google Authenticator might be a quick and easy two-factor authentication solution for VPN access to my personal network, so I did some Google searches to see if that were so. I found quite a few sources describing how to set it up with systems that use Linux Pluggable Authentication Modules (PAM), but very little about using it with BSD Authentication on OpenBSD. The most promising link I came across was to an implementation of Google Authentication for OpenBSD that was last updated in early 2013, based on Google’s PAM code, but I couldn’t get it to work. It compiled and installed, and the googleauth code for generating a secret (and a very insecure way of generating a QR code to use to import it into the Google Authenticator application) worked fine, but I couldn’t successfully use it for console login, OpenSSH login, or OpenVPN login. I also found the standard OpenBSD port for openvpn_bsdauth, which compiled, installed, and worked successfully for password authentication by adding these lines to my OpenVPN configuration: ...

October 31, 2013 · 7 min
Mastodon Verification