veilor-os/docs/HARDENING.md

4.4 KiB

Hardening Reference

What veilor-os locks down and why. Each item is applied by either the kickstart %post or the overlay tree shipped in /etc.

Boot chain

Item State Source
Secure Boot Required (bootloader signed) bootloader kickstart line
Kernel lockdown lockdown=integrity bootloader kernel args
Slab hardening slab_nomerge, init_on_alloc=1, init_on_free=1 bootloader
Stack offset randomize_kstack_offset=on bootloader
vsyscall vsyscall=none bootloader
LUKS2 aes-xts-plain64 / argon2id, mem=1GB, time=9 part pv.veilor
Module loading Locked 30s after graphical boot veilor-modules-lock.service

Kernel sysctl

/etc/sysctl.d/99-veilor-hardening.conf:

Key Value Why
kernel.kptr_restrict 2 hide kernel pointers from /proc
kernel.dmesg_restrict 1 dmesg root-only
kernel.yama.ptrace_scope 2 ptrace = parent only
kernel.perf_event_paranoid 3 unprivileged perf disabled
net.core.bpf_jit_harden 2 BPF JIT constant blinding
kernel.randomize_va_space 2 full ASLR
fs.suid_dumpable 0 no SUID core dumps
dev.tty.ldisc_autoload 0 block tty LPE vector
net.ipv4.tcp_syncookies 1 SYN flood mitigation
net.ipv4.conf.all.rp_filter 1 reverse-path filter
accept_source_route 0 (v4+v6) ignore source routing
accept_redirects 0 (v4+v6) ignore ICMP redirects

SELinux

  • Enforcing, targeted policy.
  • Custom module veilor-systemd grants systemd_modules_load_t the sys_admin and perfmon capabilities required by the modules-lock service. Source: scripts/selinux/veilor-systemd.te.

Network surface

  • firewalld default zone = drop.
  • Inbound: ssh only.
  • systemd-resolved: LLMNR off, DNSSEC allow-downgrade, DNS-over-TLS opportunistic. Resolvers: Cloudflare (1.1.1.1, 1.0.0.1), fallback Quad9 (9.9.9.9, 149.112.112.112).
  • chrony: NTS-authenticated time from time.cloudflare.com and nts.sth1/2.ntp.se. Pool fallback only.

SSH

/etc/ssh/sshd_config.d/10-veilor-hardening.conf:

  • PasswordAuthentication no
  • PermitRootLogin no
  • AllowUsers admin
  • X11Forwarding no
  • MaxAuthTries 3
  • ClientAliveInterval 300
  • LogLevel VERBOSE

Auth / accounts

  • Root account locked (passwd -l root). No interactive root login.
  • Single admin user, wheel group, full sudo.
  • pwquality.conf: minlen=14, 4 character classes required, dictcheck.
  • First-boot password flow: chage -d 0 admin expires the empty password immediately. veilor-firstboot.service runs on TTY1 before SDDM, prompts for new password, then starts the graphical session.

Audit

/etc/audit/rules.d/99-veilor-hardening.rules watches:

  • /etc/passwd, /etc/shadow, /etc/group, /etc/gshadow
  • /etc/sudoers, /etc/sudoers.d/
  • /etc/ssh/sshd_config*, /etc/selinux/, /etc/firewalld/
  • /etc/cron.*, /var/spool/cron/
  • /etc/sysctl.*, /etc/systemd/system/, /usr/lib/systemd/system/
  • All privileged binaries (sudo, su, passwd, mount, pkexec, etc.)
  • Kernel module load/unload syscalls
  • Permission/ownership changes by uid≥1000

Intrusion detection

fail2ban jails:

  • sshd — aggressive mode, 3 retries, 24h ban
  • pam-generic — 5 retries, 1h ban (catches XDM, su, sudo failures)

Backend: systemd journal. Action: firewalld rich rules.

USB

USBGuard daemon, ImplicitPolicyTarget=block.

Ships with empty allowlist. On first boot, admin runs:

sudo usbguard generate-policy > /etc/usbguard/rules.conf
sudo systemctl restart usbguard

This snapshots all currently-connected devices into the allowlist. Anything plugged in afterward is blocked unless explicitly allowed:

sudo usbguard list-devices
sudo usbguard allow-device <id>

Disabled services

abrt*, cups, cups-browsed, geoclue, avahi-daemon, bluetooth, ModemManager, gssproxy, atd, pcscd.socket, pcscd.service, kdeconnectd (removed at package level).

What's not enabled by default

  • Disk swap — replaced by zram (RAM-only, no key leak risk).
  • Bluetooth — disabled. Enable with systemctl enable --now bluetooth.
  • Printing — CUPS removed. Reinstall if needed: dnf install cups.
  • Snapd, Flatpak — not installed (Flatpak optional add-on).
  • PackageKit — removed; updates manual via dnf.