Xer0x's Underground

Thoughts on OpenBSD!


OpenBSD in my opinion is one of the best home/server OS. It's secure, robust and POSIX compliant (to a very large extent). Yes, it does lack RBAC (SELinux-like) and extremely complex ACLs (miss you systrace). But it really does a great job at locking the system down and making sure any code/binary shipped by the developers is almost guaranteed to be bug-free.


Again I would like to reiterate that it is not the perfect OS. If it wants mass adoption in any sense (specially enterprise), there are a few things I feel that can be done better.


First I believe either SELinux or AppArmour (like) systems need to be introduced in the OS because security at its heart is a multi-layered control approach (cyber resiliency). In modern times with 0day exploits coming out like marvel movies you cannot claim that "I won't be hacked, cause my source code is hack-proof and I stop memory issues." . Even programs written in Rust have been proved to have various kinds of issues. and then there is the issue of stupid users.


Another simple improvement that can be done is introducing Rust/Zig as the de-facto language, going forward all new systems/applications build for the OS should be written in Rust or Zig. I know the baggage of C is hard to let go and it will take time, maybe a huge number of components are never re-written in Rust, but the point is not to achieve 100% success. There is no 100% success in security and we can't be afraid of change just because C/C++ has ruled the world till now.


Now, let's see the good things,

The PF firewall in OpenBSD is hands down one of its most brilliant features. It's not just a firewall; it's a Swiss Army knife for network security. It handles stateful inspection with ease, supports adaptive rulesets, and even scales effortlessly across multiple CPUs. But what makes PF truly shine is its flexibility—you can do so much more than just basic packet filtering.


For example, you can build a custom Web Application Firewall (WAF) using PF. By writing precise rulesets to inspect HTTP traffic, block malicious patterns, and integrate with intrusion detection systems like Snort or Suricata, you can protect your web applications without relying on heavyweight external tools.


DDoS protection? PF has your back there too. With features like max-src-conn-rate and overload tables, you can automatically detect and block abusive connections. Combine this with ALTQ for traffic shaping, and you can throttle malicious traffic while ensuring legitimate users get a smooth experience—even during an attack.


It doesn’t stop there. PF lets you implement port knocking for stealthy access control, where a sequence of connection attempts to specific ports acts like a "secret handshake" for trusted users. This adds an extra layer of protection for sensitive services.


Want even deeper control? PF integrates seamlessly with OpenBSD’s packet-capture tools like tcpdump, letting you monitor traffic in real-time and script automated responses to anomalies.


How to Write PF Rules:


PF rules are configured in the /etc/pf.conf file. The syntax and logic are straightforward but highly expressive. Below is a breakdown of common rule types and examples.


Basic Syntax

action [direction] on [interface] proto [protocol] from [source] to [destination] [options]

A simple example would be:

block in all          # Block all incoming traffic by default
pass out all          # Allow all outgoing traffic

if you want to allow certain services:

pass in on em0 proto tcp from any to any port 22 # Allow SSH
block in on em0 proto tcp from any to any port 80 # Block HTTP

if you want state:

pass in on em0 proto tcp from any to any port 80 keep state

if you want to stop DDoS(here this is only for 80 TCP, you may do this for any port):

table <abusers> persist
block in quick from <abusers>
pass in on em0 proto tcp from any to any port 80 max-src-conn-rate 100/5 overload <abusers>

Shape certain traffic?

altq on em0 bandwidth 100Mb hfsc queue { web traffic }
queue web bandwidth 50% priority 5
pass out on em0 proto tcp to any port 80 queue web

SSH with Port knocking?

pass in on em0 proto tcp from any port 12345 keep state
block in on em0 proto tcp from any port 22

All of this is achieved while staying true to OpenBSD’s philosophy.

What else can we use to take advantage of OpenBSD?




Sysctl seems to be most interesting. These flags allow you to fine-tune the kernel’s behavior to harden your system against various attacks.



Below are some flags I always like to set:

FlagDefaultRecommendedDescription
kern.securelevel-12Sets system protection level, restricting kernel modifications.
hw.smt10Disables Simultaneous Multithreading to mitigate side-channel attacks.
kern.allowkmem10Restricts access to /dev/kmem and /dev/mem to prevent debugging exploits.

FlagDefaultRecommendedDescription
vm.swapencrypt.enable11 (unchanged)Encrypts data written to swap space for sensitive data protection.

FlagDefaultRecommendedDescription
net.inet.ip.forwarding00 (unchanged)Disables IP forwarding to reduce exposure to network attacks.
net.inet.tcp.rfc132310Disables TCP timestamps to prevent timing attacks.
net.inet.icmp.bmcastecho10Disables ICMP broadcast echo requests to prevent amplification attacks.

FlagDefaultRecommendedDescription
fs.posix.setuid10Restricts setuid binaries to prevent privilege escalation.

Unveil/Pledge:

For Unveil/Pledge, I think the below example sums up its capability very nicely.


#include <unistd.h>
#include <stdio.h>
#include <err.h>

int main(void) {
    // Unveil: Restrict file system access to only allow reading "/etc/example.txt"
    if (unveil("/etc/example.txt", "r") == -1) {
        err(1, "unveil failed");
    }

    // Lock the unveil configuration
    if (unveil(NULL, NULL) == -1) {
        err(1, "unveil lock failed");
    }

    // Pledge: Restrict program to only use standard I/O and file reading
    if (pledge("stdio rpath", NULL) == -1) {
        err(1, "pledge failed");
    }

    // Try to open and read the file
    FILE *file = fopen("/etc/example.txt", "r");
    if (!file) {
        err(1, "failed to open file");
    }

    char buffer[128];
    while (fgets(buffer, sizeof(buffer), file)) {
        printf("%s", buffer);
    }

    fclose(file);
    return 0;
}

In the above, Unveil is used to restrict file system access to /etc/example.txt in read-only mode, and once locked, no other paths can be accessed. Pledge further limits the program to only stdio and rpath system calls, ensuring it cannot perform operations beyond its intended purpose. Together, they form a simple but powerful way to confine applications.


There are some other system-level changes done by the OpenBSD team , if you are interested about lerning more go here and here.


That is it!, hope you like my thoughts on OpenBSD!, it was really fun exploring this awesome OS.

gladgers-hacker-gers-guardians-of-galaxy



Twitter LinkedIn Contact me on Signal

Contact me via email

#OpenBSD #research

← Back to blog