{ pkgs, lib, config, ... }: with lib; { options = { security.kernel.mitigations = mkOption { type = types.str; default = "auto,nosmt"; example = "off"; description = '' Control optional mitigations for CPU vulnerabilities. This is a set of curated, arch-independent options, each of which is an aggregation of existing arch-specific options. ''; }; }; config = { boot.kernelPackages = mkDefault pkgs.linuxPackages; #boot.kernelPackages = pkgs.linuxPackages_latest; #boot.kernelPackages = pkgs.linuxPackages_hardened; #boot.kernelPackages = pkgs.linuxPackages_latest_hardened; #environment.memoryAllocator.provider = "libc"; nix.settings.allowed-users = [ "@users" ]; /* nix.settings.substituters = [ "https://nix-community.cachix.org" ]; nix.settings.trusted-public-keys = [ "nix-community.cachix.org:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ]; */ nix.settings.trusted-users = [ "root" "@wheel" ]; networking.firewall.pingLimit = "--limit 60/minute --limit-burst 5"; security.allowSimultaneousMultithreading = false; security.apparmor.enable = mkDefault true; security.forcePageTableIsolation = true; security.lockKernelModules = mkDefault true; security.protectKernelImage = true; security.virtualisation.flushL1DataCache = "always"; # Only allow members of the wheel group to execute sudo by setting # the executable’s permissions accordingly. # This prevents users that are not members of wheel # from exploiting vulnerabilities in sudo such as CVE-2021-3156. security.sudo.execWheelOnly = true; boot.blacklistedKernelModules = [ # Obscure network protocols "ax25" "netrom" "rose" # Old or rare or insufficiently audited filesystems "adfs" "affs" "bfs" "befs" "cramfs" "efs" "erofs" "exofs" "freevxfs" "f2fs" "hfs" "hpfs" "jfs" "minix" "nilfs2" "ntfs" "omfs" "qnx4" "qnx6" "sysv" "ufs" ]; # kernel-hardening-checker -c /proc/config.gz -l /proc/cmdline -s <(sudo sysctl -a) -m show_fail boot.kernel.sysctl = { # Mitigate kernel pointer leaks "kernel.kptr_restrict" = 2; # Restricts the kernel log to the CAP_SYSLOG capability "kernel.dmesg_restrict" = 1; # Prevent information leaks #kernel.printk = "3 3 3 3"; # Restrict eBPF to the CAP_BPF capability # and enable JIT hardening techniques # such as constant blinding. "kernel.unprivileged_bpf_disabled" = 1; "net.core.bpf_jit_harden" = 2; # Restricts loading TTY line disciplines # to the CAP_SYS_MODULE capability to prevent # unprivileged attackers from loading vulnerable # line disciplines with the TIOCSETD ioctl "dev.tty.ldisc_autoload" = 0; # The userfaultfd() syscall is often abused to exploit # use-after-free flaws. # Due to this, this sysctl is used to restrict # this syscall to the CAP_SYS_PTRACE capability. "vm.unprivileged_userfaultfd" = 0; # kexec is a system call that is used # to boot another kernel during runtime. "kernel.kexec_load_disabled" = 1; # User namespaces are a feature in the kernel which aim to # improve sandboxing and make it easily accessible for # unprivileged users however, this feature exposes # significant kernel attack surface for privilege # escalation so this sysctl restricts the usage of user # namespaces to the CAP_SYS_ADMIN capability. "kernel.unprivileged_userns_clone" = 0; # Restricts all usage of performance events to the # CAP_PERFMON capability "kernel.perf_event_paranoid" = 3; # Helps protect against SYN flood attacks "net.ipv4.tcp_syncookies" = 1; # Protects against time-wait assassination # by dropping RST packets for sockets # in the time-wait state. "net.ipv4.tcp_rfc1337" = 1; # Disable ICMP redirect acceptance and sending to prevent # man-in-the-middle attacks and minimize information disclosure. "net.ipv4.conf.all.accept_redirects" = 0; "net.ipv4.conf.default.accept_redirects" = 0; "net.ipv4.conf.all.secure_redirects" = 0; "net.ipv4.conf.default.secure_redirects" = 0; "net.ipv6.conf.all.accept_redirects" = 0; "net.ipv6.conf.default.accept_redirects" = 0; "net.ipv4.conf.all.send_redirects" = 0; "net.ipv4.conf.default.send_redirects" = 0; # Disable source routing, a mechanism # that allows users to redirect network traffic. "net.ipv4.conf.all.accept_source_route" = 0; "net.ipv4.conf.default.accept_source_route" = 0; "net.ipv6.conf.all.accept_source_route" = 0; "net.ipv6.conf.default.accept_source_route" = 0; /* # Disable TCP SACK, which is commonly exploited # and unnecessary for many circumstances. # https://serverfault.com/questions/10955/when-to-turn-tcp-sack-off "net.ipv4.tcp_sack" = 0; "net.ipv4.tcp_dsack" = 0; "net.ipv4.tcp_fack" = 0; */ # Generate a random IPv6 address "net.ipv6.conf.all.use_tempaddr" = mkForce 2; "net.ipv6.conf.default.use_tempaddr" = mkForce 2; # Restricts usage of ptrace to only processes # with the CAP_SYS_PTRACE capability "kernel.yama.ptrace_scope" = 2; # Do source validation by confirming reverse path "net.ipv4.conf.all.rp_filter" = 1; "net.ipv4.conf.default.rp_filter" = 1; # Any process which has changed privilege levels or is execute only will not be dumped. "fs.suid_dumpable" = 0; "fs.protected_fifos" = 2; "fs.protected_regular" = 2; # TIOCSTI is a dangerous legacy operation that can be disabled on most systems. "dev.tty.legacy_tiocsti" = 0; # User namespaces are used primarily for Linux containers. If containers are in use, this requirement is not applicable. #"user.max_user_namespaces" = mkDefault 0; }; # DOC: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html boot.kernelParams = [ "oops=panic" #"quiet" #"loglevel=0" # Disable merging of slabs with similar size. May be necessary if there is # some reason to distinguish allocs to different slabs, especially in # hardened environments where the risk of heap overflows and layout control # by attackers can usually be frustrated by disabling merging. This will # reduce most of the exposure of a heap attack to a single cache (risks via # metadata attacks are mostly unchanged). Debug options disable merging on # their own. "slab_nomerge" # See slub_debug # https://gitlab.tails.boum.org/tails/tails/-/issues/19613#note_215741 "slub_debug=FZ" # Control whether the page allocator should randomize its free lists. "page_alloc.shuffle=1" # Kernel detects whether your CPU model is vulnerable to issues that PTI mitigates # Disabling this feature removes hardening, but improves performance of system calls and interrupts. "pti=auto" # Controls the behavior of vsyscalls # (i.e. calls to fixed addresses of 0xffffffffff600x00 from legacy code). # Most statically-linked binaries and older versions of glibc use these calls. # With none, vsyscalls don't work at all. # This makes them quite hard to use for exploits but might break your system. "vsyscall=none" # Filesystem is not registered and clients get a -EPERM as result # when trying to register files or directories within debugfs. "debugfs=off" # Disabled because the wireguard module is not signed "module.sig_enforce=0" # Disable kernel features that allow userland to modify the running kernel # or to extract confidential information from the kernel. "lockdown=confidentiality" # https://www.kernel.org/doc/Documentation/x86/x86_64/boot-options.rst "mce=bootlog" "mitigations=${config.security.kernel.mitigations}" # kspp | self_protection #"spectre_v2=on" # defconfig | self_protection #"spectre_v2_user=on" # defconfig | self_protection #"spec_store_bypass_disable=on" # defconfig | self_protection #"l1tf=on" # defconfig | self_protection #"mds=on" # defconfig | self_protection #"tsx_async_abort=on" # defconfig | self_protection #"srbds=on" # defconfig | self_protection #"mmio_stale_data=on" # defconfig | self_protection #"retbleed=on" # defconfig | self_protection #"spec_rstack_overflow=on" # defconfig | self_protection # Disable AVX to mitigate systems without microcode mitigation. No effect if the microcode mitigation is present. Known to cause crashes in userspace with buggy AVX enumeration. #"gather_data_sampling=force" # defconfig | self_protection # https://www.phoronix.com/news/randomize_kstack_offset-perf "randomize_kstack_offset=1" # kspp | self_protection # See https://unix.stackexchange.com/questions/592538/what-are-the-implication-of-using-iommu-force-in-the-boot-kernel-options "iommu=force" # clipos | self_protection # DMA unmap operations invalidate IOMMU hardware TLBs synchronously. "iommu.strict=1" # kspp | self_protection "kfence.sample_interval=100" # a13xp0p0v | self_protection "kfence.deferrable=1" # Unconditionally disables IA32 emulation "ia32_emulation=0" # a13xp0p0v |cut_attack_surface # A bit too much # https://patchwork.kernel.org/project/linux-security-module/patch/20190626121943.131390-2-glider@google.com/#22731857 #"init_on_alloc=1" # kspp | self_protection #"init_on_free=1" # kspp | self_protection ]; services.journald.extraConfig = '' Compress=true MaxRetentionSec=1month Storage=persistent SystemMaxUse=100M ''; systemd.coredump = { enable = mkDefault false; extraConfig = '' Compress=true MaxUse=1024M Storage=external ''; }; services.openssh = { # Avoid TOFU MITM by providing well known public keys here. knownHosts = { "git.sr.ht".hostNames = [ "git.sr.ht" ]; "git.sr.ht".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60"; "github.com".hostNames = [ "github.com" ]; "github.com".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl"; "gitlab.com".hostNames = [ "gitlab.com" ]; "gitlab.com".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf"; }; openFirewall = mkDefault false; settings = { Ciphers = [ # Not hardware accelerated, but fast enough and somehow more secure # (packet sizes are encrypted and less vulnerable to timing attacks). "chacha20-poly1305@openssh.com" # A bit more throughput. "aes128-gcm@openssh.com" "aes256-gcm@openssh.com" ]; KbdInteractiveAuthentication = mkDefault false; # Use key exchange algorithms recommended by `nixpkgs#ssh-audit` KexAlgorithms = [ "curve25519-sha256" "curve25519-sha256@libssh.org" "diffie-hellman-group16-sha512" "diffie-hellman-group18-sha512" "sntrup761x25519-sha512@openssh.com" ]; PasswordAuthentication = false; # Remove any remote gpg-agent's socket. StreamLocalBindUnlink = true; UseDns = mkDefault false; X11Forwarding = mkDefault false; }; }; }; /* TODO: https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project/Recommended_Settings ========================================================================================================================= option_name | type |desired_val | decision | reason | check_result ========================================================================================================================= CONFIG_WERROR |kconfig| y |defconfig | self_protection | FAIL: "is not set" CONFIG_X86_KERNEL_IBT |kconfig| y |defconfig | self_protection | FAIL: "is not set" CONFIG_BUG_ON_DATA_CORRUPTION |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_SHUFFLE_PAGE_ALLOCATOR |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_VIRTUAL |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_SG |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_INIT_ON_ALLOC_DEFAULT_ON |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_STATIC_USERMODEHELPER |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_SECURITY_LOCKDOWN_LSM |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_SECURITY_LOCKDOWN_LSM_EARLY |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY|kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_DEBUG_CREDENTIALS |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_NOTIFIERS |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_KFENCE |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_KFENCE_SAMPLE_INTERVAL |kconfig| is not off |a13xp0p0v | self_protection | FAIL: CONFIG_KFENCE is not "y" CONFIG_RANDSTRUCT_FULL |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_RANDSTRUCT_PERFORMANCE |kconfig| is not set | kspp | self_protection | FAIL: CONFIG_RANDSTRUCT_FULL is not "y" CONFIG_GCC_PLUGIN_LATENT_ENTROPY |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_MODULE_SIG |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_MODULE_SIG_ALL |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_MODULE_SIG_SHA512 |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_MODULE_SIG_FORCE |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_INIT_ON_FREE_DEFAULT_ON |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_EFI_DISABLE_PCI_DMA |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_RESET_ATTACK_MITIGATION |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_UBSAN_BOUNDS |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_UBSAN_LOCAL_BOUNDS |kconfig| y | kspp | self_protection | FAIL: is not found CONFIG_UBSAN_TRAP |kconfig| y | kspp | self_protection | FAIL: CONFIG_UBSAN_BOUNDS is not "y" CONFIG_UBSAN_SANITIZE_ALL |kconfig| y | kspp | self_protection | FAIL: CONFIG_UBSAN_BOUNDS is not "y" CONFIG_GCC_PLUGIN_STACKLEAK |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_STACKLEAK_METRICS |kconfig| is not set | kspp | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK is not "y" CONFIG_STACKLEAK_RUNTIME_DISABLE |kconfig| is not set | kspp | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK is not "y" CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_CFI_CLANG |kconfig| y | kspp | self_protection | FAIL: CONFIG_CC_IS_CLANG is not "y" CONFIG_CFI_PERMISSIVE |kconfig| is not set | kspp | self_protection | FAIL: CONFIG_CC_IS_CLANG is not "y" CONFIG_DEFAULT_MMAP_MIN_ADDR |kconfig| 65536 | kspp | self_protection | FAIL: "4096" CONFIG_IOMMU_DEFAULT_DMA_STRICT |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_INTEL_IOMMU_DEFAULT_ON |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_SLS |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_INTEL_IOMMU_SVM |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_AMD_IOMMU_V2 |kconfig| y | kspp | self_protection | FAIL: "m" CONFIG_SLAB_MERGE_DEFAULT |kconfig| is not set | clipos | self_protection | FAIL: "y" CONFIG_LIST_HARDENED |kconfig| y |a13xp0p0v | self_protection | FAIL: is not found CONFIG_RANDOM_KMALLOC_CACHES |kconfig| y |a13xp0p0v | self_protection | FAIL: is not found CONFIG_SECURITY_SELINUX_DISABLE |kconfig| is not set | kspp | security_policy | FAIL: "y" CONFIG_SECURITY_SELINUX_BOOTPARAM |kconfig| is not set | kspp | security_policy | FAIL: "y" CONFIG_SECURITY_SELINUX_DEVELOP |kconfig| is not set | kspp | security_policy | FAIL: "y" CONFIG_SECURITY_WRITABLE_HOOKS |kconfig| is not set | kspp | security_policy | FAIL: "y" CONFIG_SECURITY_DMESG_RESTRICT |kconfig| y | kspp |cut_attack_surface| FAIL: "is not set" CONFIG_ACPI_CUSTOM_METHOD |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_BINFMT_MISC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_INET_DIAG |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_KEXEC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_PROC_KCORE |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_HIBERNATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_COMPAT |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_IA32_EMULATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_MODIFY_LDT_SYSCALL |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_X86_MSR |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_MODULES |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_DEVMEM |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_LDISC_AUTOLOAD |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_X86_VSYSCALL_EMULATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_KPROBE_EVENTS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_UPROBE_EVENTS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_GENERIC_TRACER |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_FUNCTION_TRACER |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_STACK_TRACER |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_BLK_DEV_IO_TRACE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_PROC_PAGE_MONITOR |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_CHECKPOINT_RESTORE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_USERFAULTFD |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_DEVPORT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_DEBUG_FS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_PUNIT_ATOM_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_ACPI_CONFIGFS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_MTD_SLRAM |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_MTD_PHRAM |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_IO_URING |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_KCMP |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_RSEQ |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_PROVIDE_OHCI1394_DMA_INIT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_SUNRPC_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_FB |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y" CONFIG_VT |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y" CONFIG_BLK_DEV_FD |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "m" CONFIG_STAGING |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_KSM |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_KALLSYMS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_MAGIC_SYSRQ |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_KEXEC_FILE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_USER_NS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_X86_CPUID |kconfig| is not set | clipos |cut_attack_surface| FAIL: "m" CONFIG_X86_IOPL_IOPERM |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_ACPI_TABLE_UPGRADE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_EFI_CUSTOM_SSDT_OVERLAYS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_AIO |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_KPROBES |kconfig| is not set | lockdown |cut_attack_surface| FAIL: "y" CONFIG_BPF_SYSCALL |kconfig| is not set | lockdown |cut_attack_surface| FAIL: "y" CONFIG_IP_DCCP |kconfig| is not set |a13xp0p0v |cut_attack_surface| FAIL: "m" CONFIG_IP_SCTP |kconfig| is not set |a13xp0p0v |cut_attack_surface| FAIL: "m" CONFIG_FTRACE |kconfig| is not set |a13xp0p0v |cut_attack_surface| FAIL: "y" CONFIG_INPUT_EVBUG |kconfig| is not set |a13xp0p0v |cut_attack_surface| FAIL: "m" CONFIG_XFS_SUPPORT_V4 |kconfig| is not set |a13xp0p0v |cut_attack_surface| FAIL: "y" CONFIG_TRIM_UNUSED_KSYMS |kconfig| y |a13xp0p0v |cut_attack_surface| FAIL: "is not set" CONFIG_COREDUMP |kconfig| is not set | clipos | harden_userspace | FAIL: "y" CONFIG_ARCH_MMAP_RND_BITS |kconfig| 32 |a13xp0p0v | harden_userspace | FAIL: "28" CONFIG_X86_USER_SHADOW_STACK |kconfig| y |a13xp0p0v | harden_userspace | FAIL: is not found */ }