OpenBSD was founded by Theo de Raadt in late 1995.
De Raadt was one of the co-founders of the NetBSD project, but after differences in opinion regarding development direction, release coordination, and project management, he was asked to resign from the NetBSD core group.
In response, de Raadt decided to fork NetBSD 1.0 to create a new project. The first official release, OpenBSD 1.2, was shipped in July 1996, followed quickly by OpenBSD 2.0 in October 1996.
The project was established with a flat organizational model where Theo de Raadt acts as the lead coordinator, making design decisions with inputs from committers.
Security Auditing and the “Secure by Default” Philosophy (1996–Present)
From its inception, the OpenBSD project focused on a proactive approach to security: systematic source code auditing.
The developers began auditing the entire codebase line-by-line, searching for security vulnerabilities, buffer overflows, and race conditions.
This audit led to the design of the famous slogan: “Only two local vulnerabilities in the default install, in a heck of a long time!” (originally zero, then one, and now two over more than 25 years of distribution).
Security was integrated as a default design constraint; services that could be disabled were turned off by default, and cryptographic tools were integrated directly into the base system.
Security advisories are numbered sequentially per release (e.g. 001_syspatch or 002_pf) and are accompanied by source code patches.
The Cryptographic Export Regulations Conflict
During the late 1990s, the United States government restricted the export of strong cryptographic software (treating it as munitions).
To bypass these legal restrictions, Theo de Raadt established the OpenBSD project in Calgary, Canada.
The cryptographic libraries and code were written and hosted on servers located outside the USA, enabling OpenBSD to ship with full-strength encryption protocols worldwide without legal complications.
This international development structure allowed OpenBSD to lead the implementation of cryptographically secure daemons globally.
Genesis of OpenSSH, LibreSSL, and OpenBGPD
OpenBSD has spawned several critical, widely-used open-source software tools:
OpenSSH (1999): When licensing issues affected the SSH program, OpenBSD developers wrote a secure fork. Today, OpenSSH is the default secure remote administration standard across almost all Linux, macOS, and BSD systems.
OpenBGPD / OpenOSPFD (2004): Secure, clean routing daemon alternatives built to replace complex legacy daemons.
LibreSSL (2014): Following the devastating Heartbleed security vulnerability in OpenSSL, the OpenBSD team forked the codebase to create LibreSSL, cleaning up decades of legacy code and APIs to enforce modern security standards.
OpenNTPD (2004): A secure, clean implementation of the Network Time Protocol (NTP), designed to run as a sandboxed process.
OpenBSD Release Timeline and Architecture Mapping
The table outlines major OpenBSD releases, including their hardware support and life status:
Marketing Release
Kernel Version
Release Year
Main CPU Architectures
Status
OpenBSD 2.0
2.0-RELEASE
1996
i386, SPARC, Alpha, HP300
End of Life (EOL)
OpenBSD 3.0
3.0-RELEASE
2001
i386, alpha, sparc64, macppc
End of Life (EOL)
OpenBSD 4.0
4.0-RELEASE
2006
i386, amd64, sparc64, macppc
End of Life (EOL)
OpenBSD 5.0
5.0-RELEASE
2011
i386, amd64, sparc64, armish
End of Life (EOL)
OpenBSD 6.0
6.0-RELEASE
2016
amd64, i386, arm64, octeon
End of Life (EOL)
OpenBSD 7.0
7.0-RELEASE
2021
amd64, arm64, i386, riscv64
End of Life (EOL)
OpenBSD 7.4
7.4-RELEASE
2023
amd64, arm64, i386, powerpc
End of Life (EOL)
OpenBSD 7.5
7.5-RELEASE
2024
amd64, arm64, riscv64, octeon
Active Support
OpenBSD 7.6
7.6-RELEASE
2024
amd64, arm64, riscv64, octeon
Active Support
OpenBSD 7.7
7.7-CURRENT
2025
amd64, arm64, riscv64
Development
Introduction
What is OpenBSD?
OpenBSD is a free and open-source operating system descended from Berkeley Software Distribution (BSD) Unix, focusing on security, code correctness, and cryptography.
Like FreeBSD, OpenBSD is developed as a single, cohesive repository hosting both the kernel and core userland utilities.
OpenBSD is widely recognized as a premier security operating system, serving as the development home for OpenSSH, LibreSSL, and the PF (Packet Filter) firewall.
POSIX Compliance and Standards
OpenBSD adheres strictly to the POSIX standards (IEEE Std 1003.1), prioritizing standard behavior over custom OS extensions.
The project rejects features that increase system complexity at the cost of security audits, meaning it occasionally drops support for obsolete or overly complex POSIX APIs.
BSD License vs GPL
Released under the permissive BSD License, OpenBSD permits modification and commercial integration without copyleft restrictions.
This has allowed companies like Cisco, Juniper, and various cloud providers to integrate OpenSSH and OpenBSD components into their commercial routing and hypervisor products.
Core Advantages of OpenBSD
Security Hardening by Default: Includes proactive defense technologies like KARL, W^X, malloc guard pages, and sandboxing APIs (pledge and unveil).
High Code Quality: The entire codebase undergoes continuous security audits, resulting in clean, readable source code.
PF Firewall Integration: Serves as the native home of the PF firewall, which features clean syntax and robust packet inspection.
Cohesive Base System: Includes secure, built-in services like OpenSMTPD, OpenNTPD, and iked, eliminating the need to install third-party mail, time, or VPN packages.
Core Disadvantages of OpenBSD
Performance Trade-offs: In multi-core CPU environments, OpenBSD’s symmetric multiprocessing (SMP) throughput can be slower than FreeBSD’s or Linux’s due to a focus on security checks over raw speed.
No Native OpenZFS Support: Due to CDDL licensing conflicts and memory management choices, OpenZFS is not natively supported in the base install, relying instead on the traditional FFS (Fast File System).
Slower Driver Porting: Graphics acceleration drivers (DRM/KMS) and high-speed wireless drivers are ported from Linux, occasionally resulting in delay support cycles.
Comparison: OpenBSD vs FreeBSD vs Linux vs macOS
The table highlights core differences between the operating systems:
# Download the official OpenBSD install image# Fetch the SHA256 checksum file to verify download integrityfetch https://cdn.openbsd.org/pub/OpenBSD/7.6/amd64/install76.imgfetch https://cdn.openbsd.org/pub/OpenBSD/7.6/amd64/SHA256# Validate the checksum matches on a Unix-like systemsha256sum -c SHA256 --ignore-missing# Burn image to a USB flash drivesudo dd if=install76.img of=/dev/sdX bs=1M status=progresssync
The Interactive CLI Installer (bsd.rd)
OpenBSD boots into a lightweight ramdisk installer named bsd.rd.
The installer uses a clean, text-based interactive wizard that asks questions to guide the setup:
Select install mode: (I)nstall, (U)pgrade, or (A)utoinstall.
Install system file packages (called sets: base76.tgz, comp76.tgz, game76.tgz, xbase76.tgz).
Partitioning Layout: softraid Encrypted Setup
Rather than formatting a raw drive, security-focused administrators configure encrypted volumes using OpenBSD’s softraid subsystem:
# Enter shell from the installer prompt# 1. Initialize partition layout on disk 'sd0'fdisk -iy sd0# 2. Create a disklabel with partition 'a' as RAID typedisklabel -E sd0# (Add partition 'a' spanning the entire disk, type 'RAID')# 3. Create an encrypted softraid container on partition 'sd0a'bioctl -c C -l sd0a softraid0# (Enter passphrase to encrypt the volume)# 4. The system maps the new decrypted container to virtual disk 'sd1'# Exit shell and return to installer, choosing 'sd1' as installation target diskexit
Automated Installation Template (install.conf)
OpenBSD supports unattended hands-off installations using an install.conf responses script loaded over floppy, disk, or HTTP:
# /etc/install.conf responses templateSystem hostname = openbsd-serverPassword for root = $1$hashed_password_here$Change the default console to com0 = noSetup a user = sysadminPassword for user = $1$user_hashed_password$Allow root ssh login = noWhat timezone are you in = US/EasternLocation of sets = httpHTTP Server = cdn.openbsd.orgServer directory = pub/OpenBSD/7.6/amd64Set name(s) = +* -game*
First Boot Configuration and syspatch updates
Upon booting into a fresh OpenBSD install:
syspatch: OpenBSD’s binary patching system. It fetches pre-compiled security and errata patches from official servers and applies them to the base system instantly.
doas: A lightweight alternative to sudo developed for OpenBSD. Configured via /etc/doas.conf.
# Check for and apply system security patches on first bootsudo syspatch# Configure doas to permit your user 'sysadmin' to run administrative commands# Create the file /etc/doas.confecho "permit keepenv :wheel" | sudo tee /etc/doas.conf# Test doas privilege escalationdoas pkg_add -u
Kernel & Architecture
Monolithic Design with KARL (Kernel Address Randomized Link)
OpenBSD uses a monolithic kernel architecture where all drivers, filesystems, and memory allocators run inside a single supervisor address space.
To protect the kernel from exploit code injection attacks, OpenBSD implements KARL (Kernel Address Randomized Link) on every boot:
During a normal boot or update, the system relinks the kernel object files in a completely randomized order.
Each boot runs a unique kernel binary with different internal function offsets, preventing attackers from relying on static memory addresses to jump into shellcode.
W^X (Write XOR Execute) Memory Enforcements
W^X is a security enforcement policy implemented at the hardware page table level.
A page of memory can be writeable, or executable, but never both at the same time.
This prevents stack overflows from writing execution payloads into stack space and running them, blocking standard buffer overflow exploit vectors.
Attempting to violate W^X results in immediate process termination by the kernel:
# If a process attempts to allocate memory that is both writeable and executable:# Kernel raises a SIGSEGV signal and logs the violation to system logs:# dmesg | tail -n 2# app[1025] mprotect: W^X violation
Hardened Memory Allocator: malloc protections
OpenBSD’s userspace memory allocator (malloc) is built from the ground up with defensive features designed to break exploit payloads:
Guard Pages: Places unmapped pages (guard pages) before and after memory block allocations. Accessing these pages triggers an immediate core dump, blocking heap overflow indexing.
Address Randomization: Randomizes heap allocations, preventing memory layouts from being predicted.
Junk Filling: Fills newly allocated memory with junk bytes (0xdb) and writes junk bytes (0xdf) to memory upon being freed. This breaks applications relying on uninitialized variables or trying to read freed buffers (use-after-free).
Control variables: Users control allocator options using the MALLOC_OPTIONS environment variable:
# Run an application enabling extra heap checks and junkingexport MALLOC_OPTIONS="J"./my_app
System Startup Boot Flow
The boot sequence is designed for verification:
BootROM/UEFI: Loads the early boot loader code from disk.
boot (2nd Stage Bootloader): Initializes early system parameters and loads the kernel (/bsd).
Kernel Initialization: Mounts the root directory (FFS) and spawns the first user space process, init (PID 1).
rc.d Scripts: Reads service configurations from /etc/rc.conf.local and starts system services.
OpenBSD Boot Process Flow
The diagram outlines the secure boot sequence of an OpenBSD system:
flowchart TD
HW[Power On / BIOS / UEFI] --> BOOT[Boot Loader /boot]
BOOT --> KARL[KARL Execution\nRelinks kernel in random order]
KARL --> KERN[Kernel Starts\n/bsd execution]
KERN --> INIT[init Spawning\nPID 1 Created]
INIT --> RC[rc.d Daemon Scripts\nProcesses config from rc.conf.local]
RC --> LOG[getty Terminals\nLogin Shell Prompt]
style HW fill:#1a202c,color:#fff
style KARL fill:#9b2c2c,color:#fff
style RC fill:#276749,color:#fff
style LOG fill:#744210,color:#fff
Shell & Terminal
Default Korn Shell (Ksh) Environment
The Korn Shell (ksh) is the default shell for both the root user and standard system accounts on OpenBSD.
ksh is POSIX-compliant, extremely lightweight, and has a smaller memory footprint than Bash or Zsh.
Shell Customization
Ksh configurations are defined in the user’s home profile directory:
# ~/.profile configuration parametersexport HISTFILE=$HOME/.ksh_historyexport HISTSIZE=1000# Set interactive visual prompt showing host and current pathPS1='[OpenBSD] $USER:$PWD $ '# Enable vi-style terminal command line editingset -o vi# Set default editor pathexport EDITOR=vi
Unix Permissions and File Flags
In addition to standard owner/group file permissions, OpenBSD supports file flags via the chflags command:
schg: System Immutable flag. Can only be altered when the system is in single-user mode or securelevel is ⇐ 0.
sappnd: System Append-only flag. Permits appending text to log files, but blocks modifications and deletions.
# Lock a critical configuration file using the system immutable flagsudo chflags schg /etc/resolv.conf# Lock syslog logs to prevent attackers from deleting evidence of intrusionsudo chflags sappnd /var/log/messages
User & Group Management
The Account Database Structures
OpenBSD stores password data inside /etc/master.passwd, which is protected from read permissions for non-privileged accounts.
Passwords are hashed using the bcrypt algorithm (which was invented by OpenBSD developers in 1999). Bcrypt uses a configurable cost parameter to slow down dictionary and brute force attacks.
Account Management Commands
Users are managed using standard Unix utilities:
# Add a new group 'admins'sudo groupadd -g 1010 admins# Create a new user with home directory, shell, and primary groupsudo useradd -u 1010 -g admins -m -s /bin/ksh -c "System Administrator" sysadmin# Set user passwordsudo passwd sysadmin# Add 'sysadmin' to the wheel group (required to switch to root shell)sudo usermod -G wheel sysadmin# Delete a user account and purge their filessudo userdel -r sysadmin
Using doas for Privilege Escalation
OpenBSD developed doas as a secure, simple replacement for sudo.
Its configuration file is /etc/doas.conf, which uses a strict syntax:
# /etc/doas.conf examples
# 1. Allow wheel group members to execute commands as root, keeping their environment variables
permit keepenv :wheel
# 2. Allow user 'operator' to restart the web server without entering a password
permit nopass operator as root cmd rcctl args restart nginx
Login Classes (/etc/login.conf)
OpenBSD groups users into login classes to configure system resource limit profiles:
# /etc/login.conf section entry example# Limit memory and process boundaries for developer classesdevelopers:\ :datasize-max=2048M:\ :datasize-cur=1024M:\ :maxproc-max=512:\ :openfiles-cur=1024:\ :tc=default:
System Configuration & Services (rc.d)
The rcctl Service Management Tool
OpenBSD uses a unified CLI utility named rcctl to enable, disable, configure, and monitor system services.
System services are defined in /etc/rc.d/ and configured in /etc/rc.conf.local.
# Enable a service (e.g., nginx) to start on bootdoas rcctl enable nginx# Start the service immediatelydoas rcctl start nginx# Check service running statusrcctl check nginx# Reload service configurations without stopping executiondoas rcctl reload nginx# Restart the servicedoas rcctl restart nginx# Disable the servicedoas rcctl disable nginx# Change service startup flags (e.g., run httpd in chroot mode)doas rcctl set httpd flags "-v"
The /etc/rc.conf.local Configuration File
OpenBSD reserves /etc/rc.conf for default system services.
Custom services and configuration overrides are written to /etc/rc.conf.local:
# Example /etc/rc.conf.local entriespkg_scripts="nginx postgresql"sshd_flags=""ntpd_flags="-s"
# Make executabledoas chmod +x /etc/rc.d/customapp# Enable and start the servicedoas rcctl enable customappdoas rcctl start customapp
Package Management & Ports Collection
Package Managers (pkg_add, pkg_delete, pkg_info)
OpenBSD manages binary packages using the pkg_* command suite:
# Configure repository mirrors by writing to /etc/installurl# Example: https://cdn.openbsd.org/pub/OpenBSD# Install a binary package (e.g., git)doas pkg_add git# Search for a package matching a keywordpkg_info -Q nmap# List all installed packagespkg_info# Query which package installed a specific file pathpkg_info -E /usr/local/bin/git# Update all installed packages to their latest versionsdoas pkg_add -u# Uninstall a packagedoas pkg_delete git# Remove unused dependencies and clean package databasedoas pkg_delete -a
Proxy Settings for pkg_add
If accessing internet resources through an enterprise gateway, define proxy paths:
The ports tree contains makefile build configurations to compile packages from source:
# Clone the ports treecd /usrdoas cvs -qd anoncvs@anoncvs.ca.openbsd.org:/cvs checkout -P ports# Navigate to the target port (e.g., net/nmap)cd /usr/ports/net/nmap# Compile from source and installdoas make install clean
Package Cryptographic Signature Validation
To prevent package tampering, OpenBSD requires all binary packages to be cryptographically signed.
The package system uses signify (a tool developed by OpenBSD) to sign packages using public/private key pairs.
If a downloaded package does not match the signature keys stored in /etc/signify/, the installer rejects it:
OpenBSD uses the Fast File System (FFS) as its default filesystem.
To optimize metadata write speeds without risking data corruption during sudden power losses, FFS utilizes Soft Updates.
Soft Updates calculates dependency relationships for metadata updates, ensuring they are written to disk in a logical order that prevents filesystem corruption, eliminating the need for journaling.
# Check filesystem configurations in /etc/fstab# Example line:# /dev/sd0a / ffs rw,wxallowed,softdep 1 1# (softdep indicates Soft Updates is active)
Encrypting Swap Space
To prevent sensitive memory fragments (such as encryption keys or user credentials) from being written to swap space in cleartext, OpenBSD encrypts swap pages by default.
During every boot, the kernel generates a new, random cryptographic key for swap space, making swap data unreadable after reboot.
softraid Crypto Partition Encryption
OpenBSD manages disk encryption using the softraid subsystem, which wraps partitions in a virtual encrypted container:
# 1. Initialize softraid partition SD0# 2. Attach partition SD0 to biomgr driver to create virtual container SD1# 3. Mount filesystem onto virtual container disk partition 'sd1a'# Check the status of encrypted softraid disksbioctl softraid0
Security Sandboxing: pledge & unveil
Sandboxing Philosophy
OpenBSD includes two unique system calls that allow developers to sandbox applications: pledge(2) and unveil(2).
Unlike complex container frameworks or security wrappers (like AppArmor or SELinux), these sandboxing features are implemented directly in the application source code.
pledge(2) System Call Constraints
The pledge(2) system call allows a process to voluntarily limit the types of system calls it can make.
A program declares the resources it needs (called “promises”) at startup, and the kernel blocks it from making any system calls outside that set.
If a pledged program attempts to make an unauthorized system call (e.g., trying to initiate a network request after promising only file read access), the kernel immediately terminates the process with a SIGABRT signal.
Pledge Promise Categories and Syscalls Mapping
The table outlines the promise string parameters and the associated kernel operations they permit:
Promise Name
Permitted Capabilities
Key Associated System Calls
stdio
Basic standard I/O and memory
read, write, mmap, getpid, exit
rpath
Read access to files
open, read, stat, readlink
wpath
Write access to files
write, open (write mode), ftruncate
cpath
Create/delete files
mkdir, rmdir, unlink, rename
inet
Network socket connections
socket, connect, bind, sendto, recvfrom
exec
Program execution
execve, fork (under strict rules)
proc
Process limits control
fork, getprio, setprio, kill
flock
File lock operations
flock, fcntl
unveil(2) File Path Virtualization
The unveil(2) system call limits the files and directories that a process is allowed to see.
A program can “unveil” specific directory paths with read, write, execute, or create permissions, and the kernel blocks it from accessing any other parts of the filesystem.
Once a process locks its unveiled paths (by calling unveil(NULL, NULL)), it cannot unveil any more files.
Networking, Firewall & Redundancy
Network Interface Configuration
OpenBSD configures network interfaces using static configuration files in /etc/:
Files follow the format /etc/hostname.interface_name.
# Configure a static IP on interface card 'em0'# Create/edit the file /etc/hostname.em0inet 192.168.1.100 255.255.255.0 NONE# Configure interface to use DHCP# Edit the file /etc/hostname.em0dhcp# Start/Stop the interfacedoas sh /etc/netstart em0
The Native PF (Packet Filter) Firewall
OpenBSD is the native home of the PF firewall.
PF features a clean syntax, table structures, and robust network address translation (NAT).
Advanced PF Rule Profiles
Below is a production configuration profile featuring tables, port redirection (NAT), and SSH protection rules:
# /etc/pf.conf configuration profile
ext_if = "em0"
web_servers = "192.168.1.10"
table <bruteforce> persist
table <blocklist> persist file "/etc/blocked_ips"
set skip on lo0
block all
# Outgoing traffic tracking
pass out on $ext_if proto { tcp, udp, icmp } all keep state
# Block list enforcements
block in quick on $ext_if from { <bruteforce>, <blocklist> } to any
# Port forwarding redirection (NAT)
pass in on $ext_if proto tcp to any port 80 rdr-to $web_servers port 80
# Protect SSH against brute force attacks
pass in on $ext_if proto tcp to any port 22 \
keep state (max-src-conn 10, max-src-conn-rate 5/3, \
overload <bruteforce> flush global)
# Enable PFdoas pfctl -e# Load and validate pf.conf rule configurationsdoas pfctl -f /etc/pf.conf# List active rulesdoas pfctl -sr# List active connections state tabledoas pfctl -ss
High Availability via CARP (Common Address Redundancy Protocol)
CARP allows multiple OpenBSD hosts on a local network to share an IP address.
If the master node goes offline, the backup node automatically assumes the IP address, providing seamless failover.
# Fetch the root anchor keys for DNSSEC validationdoas unbound-anchor -a "/var/unbound/db/root.key"# Enable and start the Unbound servicedoas rcctl enable unbounddoas rcctl start unbound
Virtualization & Compatibility (vmd)
The vmd Hypervisor
OpenBSD includes a native hypervisor called vmd (Virtual Machine Daemon) to run guest operating systems.
vmd is designed to run OpenBSD or Linux guest virtual machines, prioritizing security over complex virtualization extensions.
Virtual Machine Configuration (/etc/vm.conf)
# Global settings
switch "vswitch0" {
interface bridge0
}
# Virtual Machine Definition
vm "guest_vm" {
memory 2048M
disk "/var/vm/guest_vm.raw"
interface { switch "vswitch0" }
}
VM Management Commands
# Create a 20 GB raw virtual disk filevmctl create -s 20G /var/vm/guest_vm.raw# Enable and start the VM servicedoas rcctl enable vmddoas rcctl start vmd# Start the virtual machinedoas vmctl start guest_vm# Console access to the running VMdoas vmctl console guest_vm# Stop the virtual machinedoas vmctl stop guest_vm
System Diagnostics, Tuning & Troubleshooting
Runtime Tuning via sysctl
Adjust kernel settings at runtime:
# Enable IP forwardingdoas sysctl net.inet.ip.forwarding=1# Adjust maximum open files limitdoas sysctl kern.maxfiles=65536
Hardening Kernel Parameters via sysctl.conf
OpenBSD administrators enforce high security levels by overriding default kernel behaviors inside /etc/sysctl.conf:
Critical Hardening Options
ddb.console: Controls whether keyboard console buttons can drop the system into the kernel debugger (DDB). Disabling this prevents local users from bypassing authentication.
net.inet.ip.redirect: Controls whether the kernel accepts ICMP redirect packets. Disabling this prevents network redirects and MITM route hijackings.
net.inet.tcp.drop_synfin: Drops TCP packets that have both the SYN and FIN flags set, which are commonly used by port scanners to bypass logging rules.
vmstat: Display virtual memory allocations and page stats.
iostat: Monitor disk I/O metrics.
netstat: Monitor network connections and interfaces.
fstat: List open files held by running processes.
pledge and unveil Sandboxing Simulation (C Program)
Sandboxing Subsystem Simulation
Below is a complete C program simulating OpenBSD’s pledge and unveil sandboxing runtime system.
It defines virtual process contexts, capability structures, path maps, and checks if file operations or network accesses violate the process’s promises:
/* ============================================================================== * File: openbsd_sandbox_simulation.c * Description: Simulation of OpenBSD pledge(2) and unveil(2) security sandboxing. * Author: VR-Rathod * ============================================================================== */#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include <stdbool.h>#define MAX_PATHS 8#define PATH_LEN 64// Sandbox capability flagstypedef struct { bool stdio; bool rpath; bool wpath; bool cpath; bool inet; bool exec;} SandboxPromises;// Unveiled directory mapping detailstypedef struct { char path[PATH_LEN]; char permissions[4]; // e.g. "r", "rw", "rwx" bool active;} UnveiledPath;// Sandbox Process Context structuretypedef struct { SandboxPromises promises; UnveiledPath paths[MAX_PATHS]; uint32_t path_count; bool pledged; bool unveiled_locked;} SandboxContext;SandboxContext g_ctx;// Initialize sandbox process contextvoid init_sandbox() { g_ctx.promises.stdio = true; g_ctx.promises.rpath = true; g_ctx.promises.wpath = true; g_ctx.promises.cpath = true; g_ctx.promises.inet = true; g_ctx.promises.exec = true; for (int i = 0; i < MAX_PATHS; i++) { g_ctx.paths[i].active = false; } g_ctx.path_count = 0; g_ctx.pledged = false; g_ctx.unveiled_locked = false; printf("[SANDBOX] Initialized context with full system privileges.\n");}// Simulates the pledge(2) system callbool virtual_pledge(const char *promises_str) { if (g_ctx.pledged) { printf("[ERROR] pledge() has already been called. Re-pledging is blocked.\n"); return false; } // Remove default permissions g_ctx.promises.stdio = false; g_ctx.promises.rpath = false; g_ctx.promises.wpath = false; g_ctx.promises.cpath = false; g_ctx.promises.inet = false; g_ctx.promises.exec = false; // Parse the promises string if (strstr(promises_str, "stdio")) g_ctx.promises.stdio = true; if (strstr(promises_str, "rpath")) g_ctx.promises.rpath = true; if (strstr(promises_str, "wpath")) g_ctx.promises.wpath = true; if (strstr(promises_str, "cpath")) g_ctx.promises.cpath = true; if (strstr(promises_str, "inet")) g_ctx.promises.inet = true; if (strstr(promises_str, "exec")) g_ctx.promises.exec = true; g_ctx.pledged = true; printf("[PLEDGE ACTIVE] Promises restricted to: \"%s\"\n", promises_str); return true;}// Simulates the unveil(2) system callbool virtual_unveil(const char *path, const char *permissions) { if (g_ctx.unveiled_locked) { printf("[ERROR] unveil() is locked. Further path additions are blocked.\n"); return false; } // Locking unveil mappings if (path == NULL && permissions == NULL) { g_ctx.unveiled_locked = true; printf("[UNVEIL LOCKED] Path visibility configurations locked.\n"); return true; } if (g_ctx.path_count >= MAX_PATHS) { printf("[ERROR] Maximum unveiled paths limit reached!\n"); return false; } strncpy(g_ctx.paths[g_ctx.path_count].path, path, PATH_LEN); strncpy(g_ctx.paths[g_ctx.path_count].permissions, permissions, 4); g_ctx.paths[g_ctx.path_count].active = true; printf("[UNVEIL PATH] Path \"%s\" unveiled with permissions: \"%s\"\n", path, permissions); g_ctx.path_count++; return true;}// Helper function to verify path matches unveiled configurationsbool verify_path_permission(const char *target_path, const char req_perm) { // If unveil has not been called, access is allowed by default if (g_ctx.path_count == 0 && !g_ctx.unveiled_locked) return true; for (int i = 0; i < MAX_PATHS; i++) { if (g_ctx.paths[i].active && strncmp(target_path, g_ctx.paths[i].path, strlen(g_ctx.paths[i].path)) == 0) { if (strchr(g_ctx.paths[i].permissions, req_perm) != NULL) { return true; } } } return false;}// Intercept and validate file read operationsbool virtual_read_file(const char *file_path) { // 1. Check pledge promises if (g_ctx.pledged && !g_ctx.promises.rpath) { printf("[KILLED] Process terminated by SIGABRT: pledge violation on read call!\n"); exit(1); } // 2. Check unveil path limits if (!verify_path_permission(file_path, 'r')) { // Returns a 'No such file or directory' error printf("[ACCESS BLOCKED] read_file failed on path: \"%s\" (not unveiled)\n", file_path); return false; } printf("[SUCCESS] File read successful: \"%s\"\n", file_path); return true;}// Intercept and validate file write operationsbool virtual_write_file(const char *file_path) { // 1. Check pledge promises if (g_ctx.pledged && !g_ctx.promises.wpath) { printf("[KILLED] Process terminated by SIGABRT: pledge violation on write call!\n"); exit(1); } // 2. Check unveil path limits if (!verify_path_permission(file_path, 'w')) { printf("[ACCESS BLOCKED] write_file failed on path: \"%s\" (not unveiled)\n", file_path); return false; } printf("[SUCCESS] File write successful: \"%s\"\n", file_path); return true;}// Intercept and validate network operationsbool virtual_network_connect(const char *address, int port) { if (g_ctx.pledged && !g_ctx.promises.inet) { printf("[KILLED] Process terminated by SIGABRT: pledge violation on network connect call!\n"); exit(1); } printf("[SUCCESS] Connected to server: %s:%d\n", address, port); return true;}// Intercept process creation operationsbool virtual_execve(const char *binary_path) { if (g_ctx.pledged && !g_ctx.promises.exec) { printf("[KILLED] Process terminated by SIGABRT: pledge violation on execve call!\n"); exit(1); } printf("[SUCCESS] Successfully executed binary: %s\n", binary_path); return true;}int main() { printf("=== OPENBSD PLEDGE AND UNVEIL SIMULATION ===\n"); init_sandbox(); // 1. Unveil directories and lock path configurations virtual_unveil("/usr/home/user/docs", "r"); virtual_unveil("/tmp", "rw"); virtual_unveil(NULL, NULL); // Lock further path additions // Test file access inside unveiled directory virtual_read_file("/usr/home/user/docs/report.txt"); // Test file access outside unveiled directories (should be blocked) virtual_read_file("/etc/master.passwd"); // 2. Pledge syscall promises virtual_pledge("stdio rpath"); // Remove write and network capabilities // Test read in permitted path (should pass) virtual_read_file("/usr/home/user/docs/notes.md"); // Test network connection (should fail and terminate process) printf("\n[INFO] Attempting network call (violates pledge stdio rpath)...\n"); virtual_network_connect("192.168.1.5", 80); printf("[ERROR] This line should never execute if process was killed.\n"); return 0;}
Shell & Automation Scripts
OpenBSD Production-Ready Automation Scripts
Below are five complete, production-grade automation scripts designed for OpenBSD system administrators:
Script 1: Automated User Provisioning and doas Setup
Creates system admin users and configures permissions in /etc/doas.conf:
#!/bin/sh# ==============================================================================# Script: user_provisioner.sh# Description: Automates user creation and doas configurations on OpenBSD.# Author: VR-Rathod# ==============================================================================USERNAME=$1USER_CLASS="staff"if [ -z "$USERNAME" ]; then echo "Usage: $0 <username>" exit 1fiecho "[INFO] Creating user account: ${USERNAME}"useradd -m -g =wheel -L ${USER_CLASS} -s /bin/ksh "${USERNAME}"echo "[INFO] Setting up user password..."passwd "${USERNAME}"# Add permissions to /etc/doas.confDOAS_CONF="/etc/doas.conf"if [ ! -f "$DOAS_CONF" ]; then touch "$DOAS_CONF" chmod 600 "$DOAS_CONF"fi# Append permit rulesecho "permit keepenv ${USERNAME} as root" >> "$DOAS_CONF"echo "[SUCCESS] User ${USERNAME} created and added to ${DOAS_CONF}."exit 0
Script 2: Automated backup script using softraid/crypto management
Mounts an encrypted softraid partition, performs system backup, and unmounts the volume safely:
#!/bin/sh# ==============================================================================# Script: softraid_backup.sh# Description: Mounts encrypted softraid, backups files, and decrypts pool.# Author: VR-Rathod# ==============================================================================CRYPTO_DEV="sd0e" # Raw partition mapped to RAIDDECRYPTED_DISK="sd2" # Decrypted disk mapped by bioctlMOUNT_DIR="/mnt/secure_backup"SOURCE_DIR="/var/www"echo "[INFO] Decrypting softraid partition..."bioctl -c C -l "/dev/${CRYPTO_DEV}" softraid0if [ $? -ne 0 ]; then echo "[ERROR] Failed to decrypt partition." exit 1fiecho "[INFO] Mounting volume..."mkdir -p "$MOUNT_DIR"mount "/dev/${DECRYPTED_DISK}a" "$MOUNT_DIR"echo "[INFO] Running tar backup..."tar -czf "${MOUNT_DIR}/www_backup_$(date +%F).tar.gz" "$SOURCE_DIR"echo "[INFO] Unmounting and locking partition..."umount "$MOUNT_DIR"bioctl -d "$DECRYPTED_DISK"echo "[SUCCESS] Backup complete. Container encrypted."exit 0
Script 3: PF Firewall CARP State Inspector and Failover Logger
Monitors CARP interfaces and logs state updates for high-availability setups:
#!/bin/ksh# ==============================================================================# Script: carp_monitor.sh# Description: Monitors and logs CARP interface state transitions.# Author: VR-Rathod# ==============================================================================CARP_IF="carp0"LOG_FILE="/var/log/carp_monitor.log"LAST_STATE=""log_event() { echo "[$(date '+%F %T')] [CARP] - $1" >> "$LOG_FILE"}while true; do CURRENT_STATE=$(ifconfig "$CARP_IF" 2>/dev/null | grep "carp:" | awk '{print $2}') if [ -z "$CURRENT_STATE" ]; then log_event "ERROR: Interface ${CARP_IF} not found." sleep 30 continue fi if [ "$CURRENT_STATE" != "$LAST_STATE" ]; then if [ -n "$LAST_STATE" ]; then log_event "WARNING: State transitioned from ${LAST_STATE} to ${CURRENT_STATE}!" # If transition to master, reload routing tables if [ "$CURRENT_STATE" = "MASTER" ]; then pfctl -f /etc/pf.conf fi else log_event "Monitoring active. Current state: ${CURRENT_STATE}" fi LAST_STATE="$CURRENT_STATE" fi sleep 5done
Script 4: Security Update and syspatch check Cron
Checks for binary patches, security updates, and packages vulnerabilities:
Script 5: Process Sandbox Wrapper using pledge/unveil (Concepts)
Template wrapper script illustrating process isolation rules:
#!/bin/sh# ==============================================================================# Script: run_sandboxed.sh# Description: Concept script detailing OpenBSD daemon sandboxing setups.# Author: VR-Rathod# ==============================================================================DAEMON="/usr/sbin/httpd"CHROOT_DIR="/var/www"# Restrict daemon process execution to read/write within /var/www onlyecho "[INFO] Starting daemon in chroot sandboxed container..."exec "$DAEMON" -d -u -u -t "$CHROOT_DIR"
OpenBSD Command Reference
Complete Command Reference (150+ Commands)
System Administration & Information
sysctl -a # Query all active kernel variablessysctl kern.version # Read kernel version detailssysctl kern.maxfiles # Query maximum open file descriptors limitsysctl kern.securelevel # Query active kernel security level valueuname -a # Display system details, architecture, and kernel versionsyspatch # Apply binary patches to base operating systemsyspatch -c # Check if binary patches are availabledmesg # Read the system boot and kernel message buffersdate # Display or adjust system calendar time settingsuptime # Show system uptime, load averages, and user countshutdown -p now # Power down the system immediatelyreboot # Reboot the system immediatelyrcctl enable nginx # Enable service to start on bootrcctl disable nginx # Disable service from starting on bootrcctl start nginx # Start a system service daemonrcctl stop nginx # Stop a system service daemonrcctl restart nginx # Restart a system service daemonrcctl check nginx # Check if a service is running and view its PIDrcctl get nginx # Show all parameters of a servicercctl set nginx flags "-v" # Set startup arguments for a servicekldstat # List all loaded kernel modules (legacy compat)locale # Print active language and encoding configurationspciconf -l # List PCI bus hardware devices and vendor codesusbconfig # List USB controllers and attached devicesdevinfo # Print system hardware device treesinstallurl # File location mapping official mirrors (/etc/installurl)signify # Cryptographic signing utilitysignify -C -p pubkey.pub -x check.sig # Verify file checksum signature
Storage & Filesystem Administration
fdisk sd0 # View partition layout on disk sd0fdisk -iy sd0 # Initialize partition table on disk sd0disklabel sd0 # View partitions within drive label sd0disklabel -E sd0 # Edit partitions within drive label sd0newfs /dev/rsd0a # Format partition with FFS filesystemfsck -y /dev/rsd0a # Scan and repair FFS partition, auto-fixing issuesmount /dev/sd0a /mnt # Mount partition to target directory pathumount /mnt # Unmount target device mount pointdf -h # Display mounted filesystem space usagedu -sh /var/log/ # Calculate directory space usagebioctl softraid0 # Display status of softraid encryption disksbioctl -c C -l sd0a softraid0 # Create an encrypted softraid container on sd0abioctl -d sd1 # Detach/lock encrypted softraid disk sd1mount_cd9660 /dev/cd0 /mnt # Mount ISO 9660 CD-ROM devicetunefs -p / # Print filesystem details for mount point
Process Management & Diagnostics
ps aux # Display running processespgrep -u root sshd # Find process IDs matching criteriapkill -9 -u testuser # Kill processes matching criteria immediatelykill -15 1024 # Terminate process gracefully using SIGTERMkill -9 1024 # Terminate process immediately using SIGKILLtop -o cpu # Monitor system processes, sorted by CPU usagevmstat -s # Display page allocation statisticsiostat -w 2 # Print disk I/O metrics every two secondssystat -ifstat # Full-screen network interface statisticssystat -vmstat # Full-screen virtual memory and scheduling statisticsfstat -p 1024 # List open files held by specific process IDsockstat -4 -l # List processes listening on open TCP/UDP portsprocstat -f 1024 # Print detailed file descriptor table of a processlimit # Display shell session resource limitsulimit -n 2048 # Adjust open file descriptors limit in shellnice -n 10 backup.sh # Run process with low priority levelrenice +15 -p 1024 # Lower priority level of active process ID
Networking & Port Diagnostics
ifconfig # List active network interfaces and configurationsifconfig em0 up # Enable network interface card em0ifconfig em0 down # Disable network interface card em0ifconfig em0 inet 192.168.1.5 # Configure IP address on interface em0netstart # Shell script executing interface configurations (/etc/netstart)route add default 192.168.1.1 # Add default gateway path to routing tableroute show # Display active network routing tablesping -c 5 1.1.1.1 # Send ICMP echo requests to verify remote hosttraceroute 8.8.8.8 # Display hop path to remote destinationnetstat -rn # Display active routing tables in numeric formatnetstat -i # Display network interface statisticsnetstat -an | grep LISTEN # List open sockets listening for incoming connectionsarp -a # Display ARP IP-to-MAC address mapping tablesdig @8.8.8.8 google.com # Perform DNS lookup queries using Google DNShost google.com # Perform quick DNS host resolution querync -zv 192.168.1.100 22 # Test connection to remote port (Netcat)curl -I https://openbsd.org # Fetch HTTP headers of target web serverfetch https://site.com/file.zip # Download file over HTTP/FTPtcpdump -i em0 # Capture network packets passing through interface em0ndp -an # Display IPv6 neighbor cache mapping details
Package & Ports Management
pkg_add git # Install a binary packagepkg_add -u # Upgrade all installed binary packages to latest versionspkg_delete git # Uninstall an installed binary packagepkg_info -Q nmap # Search repositories for matching packagespkg_info tmux # Display metadata details of an installed packagepkg_info -L tmux # List all files installed by a packagepkg_delete -a # Delete orphaned dependenciespkg_add -ui # Upgrade packages interactively
Security, Auditing & Hardening
chflags schg critical_file # Set system immutable flag on a filechflags noschg critical_file # Clear system immutable flag on a filechflags sappnd log_file # Set system append-only flag on a log filels -lao # List directory files displaying system flagsuseradd -m -g =wheel test # Create system user accountuserdel -r test # Delete user account and home directoriesvipw # Safely edit system master password filedoas -u operator rcctl restart nginx # Run command as another user via doaspfctl -e # Enable the PF firewall enginepfctl -d # Disable the PF firewall enginepfctl -f /etc/pf.conf # Load firewall rules from pf.conf filepfctl -sr # Display currently loaded firewall rulespfctl -ss # Display active state tables of the firewallpfctl -vvss # Verbose display of active firewall connections and counterspfctl -t bad_ips -T show # List IP addresses stored inside PF table bad_ipspfctl -t bad_ips -T add 1.1.1.1 # Add IP address to PF firewall table bad_ipspfctl -t bad_ips -T delete 1.1.1.1 # Delete IP address from PF firewall table bad_ipspfctl -F all # Flush all PF rules, tables, counters, and active statessyspatch -l # List all applied binary security patchessyspatch -r # Revert the last applied binary security patchdoas -s # Open an interactive supervisor root shell sessionencrypt -b 8 # Generate bcrypt hash of a string password using cost 8signify -V -p /etc/signify/openbsd-76-base.pub -x check.sig -m file # Verify signature on a filektrace ./my_app # Enable system call tracing on a process (writes to ktrace.out)kdump # View ktrace.out execution log (highly useful for pledge/unveil debugs)vmctl show # List all running guest virtual machines and JIDs under vmdvmctl status # Query virtualization resource allocations and memory poolsunbound-checkconf # Verify syntax configurations of the unbound resolver fileunbound-anchor # Download trust anchor keys for DNSSEC validationifconfig carp0 carpdev em0 # Map CARP interface to hardware network controller em0