Table of Contents
- CISS.2024.vps.bookworm.hardening
- Key Words
- Quick start
- Background of this script
- Upcoming Features
- Features of the script
- Main Hardening Features
- Extended Full Disk Encryption Routine including /boot encryption
- Ephemeral Swap Encryption
- Ephemeral /tmp Encryption
- LVM on RAID on dm-integrity encrypted High Availability Setup
- Boot parameters
- Enables known mitigations for CPU vulnerabilities
- Kernel self-protection
- Certain Kernel modules are disabled and blacklisted
- Disable Uncommon Network Protocols
- Disable Uncommon Filesystems
- Disable Uncommon Network Filesystems
- Network Hardening Settings
- Restrictive mount options
- Further Hardening
- Main Installation
- ! Warnings !
- Prerequisites
- Tested and recommended VPS Provider
- sha512 Hashes
- Server Preparation and Setup
- .conf file values
- ADDUSER
- ADDSHORTCUTS
- ANSIBLE
- ARCHITECTURE
- BOOTENCRYPTION
- BOOTENCRYPTION_FORMAT
- CURRENTTIMEZONE
- EPHEMERAL_SWAP
- EPHEMERAL_SWAP_PARTITION
- EPHEMERAL_TMP
- EPHEMERAL_TMP_PARTITION
- GRUB_PSSWD
- FQDN
- IPV4
- IPV6
- JUMPHOST
- JUMPHOST_IPV4
- JUMPHOST_IPV6
- KERNELUPDATE
- LOGROTATE_CHANGE
- LOGROTATE_COUNT
- LUKSITERATION
- LVM_RAID_INTEGRITY
- OPENSSL_SECLEVEL
- OVERWRITEPROTECTION
- QEMUREMOVAL
- SECEXTENSIONS
- SELFCHECK
- SELFCHECKDL
- SSHKEYROUNDS
- SSHPORT
- TRUSTKEY
- TRUSTLEVEL
- UFW_OUT_POLICY
- USERNAME
- USERSSHPUBKEY
- VPSPROVIDER
- ZSH_INST
- Using ./restart_*.sh scripts
- Resources
- Acknowledgements
- Changelog
- Screenshots
- Security Policy
- Troubleshooting
CISS.2024.vps.bookworm.hardening
Centurion Intelligence Consulting Agency Information Security Standard 2024
Debian Bookworm Hardening Script
Mainline Version 5.0
V5.0.768.2024.08.14
This is a digitally signed, self-verifying shell script for setting up a hardened Debian Bookworm Server environment that relies on the latest best practices in server and service hardening, incl. LUKS2 /boot encryption, Ephemeral SWAP encryption, Ephemeral /tmp encryption and LVM on RAID on dm-crypt incl. dm-integrity HA setup.
Check out more CenturionNet Services | CenturionDNS Resolver | CenturionNet Status | CenturionMeet | Contact the author
Please note: All my signing keys are contained in a HSM and the signing environment is air gapped. Next step: move to a room gapped environment ^^
Please read carefully before installation!
Key Words
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14], [RFC2119], [RFC8174] when, and only when, they appear in all capitals, as shown here.
Quick start
- Check Prerequisites, Tested and recommended VPS Provider and Troubleshooting for known issues before installation.
- Please note the warning.
- For further preparations refer to the following Tutorial on how to install a fresh Debain Bookworm Server: CISS.2024.bookworm.installation.
- A detailed Tutorial for this script is available at: CISS.2024.vps.bookworm.hardening.
- If you are installing Debian GNU/Linux from a minimal CD by using the network, you will need to install
wgetpackage before you can use the hardening script. - Make sure that you are root.
apt install wget --no-install-recommends -y
mkdir /root/server-scripts
cd /root/server-scripts
wget --https-only https://cendev.eu/marc.weidner/CISS.2024.vps.bookworm.hardening/raw/branch/main/hardening.sh
wget --https-only https://cendev.eu/marc.weidner/CISS.2024.vps.bookworm.hardening/raw/branch/main/hardening.conf
wget --https-only https://cendev.eu/marc.weidner/CISS.2024.vps.bookworm.hardening/raw/branch/main/password.txt
chmod 0700 hardening.sh && chmod 0600 hardening.conf && chmod 0600 password.txt
Edit hardening.conf, and if you are using the LVM on RAID on dm-integrity HA setup also the ./password.txt file. Then run:
./hardening.sh
or
./hardening.sh debug
for detailed debugging information logged in /root/hardening/log/debug_log_$SCRIPT_START.log.
- Select the NIC if applicable and you will be prompted to edit hardening.conf to suit your needs if you have not already done so, in which case simply quit nano with
CTRL-X. - For detailed installation instructions for Contabo, Hetzner, Netcup and Proxmox installations, please see Main Installation
Background of this script
A short summary for the existence of the script as it is. You will notice - and this is obvious - that I trust Netcup, Hetzner and Contabo, and when it comes to hypervisors, I strongly recommend using Proxmox. Surely it can be argued that in the political situation and the ever shrinking space to express one's opinion it is a good choice to choose Germany as the location of the VPS / Bare Metal provider. But that is another discussion.
Also, when it comes to setting up servers, I am focused on Debian due to the vast community that supports this distro.
Stating this, I was looking to automate all my running and still to come services in a way that I could easily handle these three different types of Hosters and the Proxmox case in a reliable and smoothless way to secure the freshly installed server setups to a very high level and the trade off that many of the services to be installed later will not break or at least require a minimum of maintencane and tweaks.
Upcoming Features
- Work in progress as of 08.08.2024:
- More granular selection of which modules to install and harden.
- Implementation of new partitioning scheme
LVMonRAIDon dm-crypt including dm-integrity. Support of adding spare disks to be implemented. - arm64 support. Still issues to address.
- Tutorials: Update to new V5 Mainline in progress.
- Modularisation.
- 2FA integration.
Features of the script
- The script and all modules and assets downloaded by my scripts are cryptographically signed with my private OpenPGP key, see the public key fingerprint here, which resides in an HSM. All signing operations are performed on an air-gapped system. Help me move to the next level of security: a room-gapped signing environment. All cryptographic verification operations can be disabled for easy and convenient script editing. A comprehensive list of all my keys and certificates in use is available here via DANE/TLSA and DNSSEC secured
https onlyandhttps preloadedwebsite. - Self verification of all downloaded assets. Can be disabled for easy and convenient script editing.
- If there are any errors in the verification process of cryptographically signed scripts, assets and modules, the script will automatically fail immediately.
- Advanced error and signal and debug trap functions. Returns exit code, line number, executed command, module name and PID both on screen and in the respective log files:
/root/hardening/log/debug_log_$SCRIPT_START.log./root/hardening/log/error_log_$SCRIPT_START.log./root/hardening/log/install_log_$SCRIPT_START.log.
- Further detailed logs available in `/root/hardening/log', including logging of user input (without logging of credentials, for clarity) and coloured log file.
- Debug mode can be invoked with `./hardening.sh debug'.
- You will be prompted and the SSH hardening module will pause to check that you have access via the new SSH settings. A rollback capability is offered.
- Double-checking of the grub password settings (if selected), the fstab hardening feature, the root password change module and the
/bootencryption module (if selceted). - All files touched by the script are copied
/root/hardening/backup/*.bak. No files are overwritten: see bash environment settings below. - Select the trust level of the signing key I have provided.
- For security reasons, the bash history is also deleted and cleared after the setup routine.
- Take advantage of the following bash error handling options:
set -o errexit # Exit script when a command exits with non-zero status, same as "set -e".
set -o errtrace # Any trap on ERR are inherited in a subshell environment.
set -o functrace # Any trap on DEBUG and RETURN are inherited in a subshell environment.
set -o nounset # Exit script on use of an undefined variable, same as "set -u".
set -o pipefail # Makes pipeline return the exit status of the last command in the pipe that failed.
set -o noclobber # Prevent overwriting.
set +o history # Temporarily turn off history, to avoid sensitive information leakage.
Main Hardening Features
See the Tutorial for a more detailed overview of the implemented hardening settings.
Extended Full Disk Encryption Routine including /boot encryption
- Optional full disk encryption, including
/boot- Unlocking LUKS devices from GRUB. So called "full disk encryption" is often a misnomer, because there is typically a separate plaintext partition holding/boot. For instance the Debian Installer does this in its "encrypted LVM" partitioning method. Since not all bootloaders are able to unlock LUKS devices, a plaintext/bootis the only solution that works for all of them. However, GRUB2 is (since Jessie) able to unlock LUKS devices with itscryptomountcommand, which therefore enables encryption of the/bootpartition as well: using that feature reduces the amount of plaintext data written to disk. Works on UEFI and BIOS environments.
Ephemeral Swap Encryption
- Optional ephemeral encryption of the SWAP area. In this scenario, the encrypted swap area will be initialised with a random new key every boot time to maximise security considerations. https://wiki.archlinux.org/title/dm-crypt/Swap_encryption
Ephemeral /tmp Encryption
- Optional ephemeral encryption of the
/tmppartition. In this scenario, the encrypted/tmppartition is initialised with a new random key at boot time to maximise security. The permissions are also set to1777at boot time.
LVM on RAID on dm-integrity encrypted High Availability Setup
- Optional module to set up a complete LVM on mdadm on dm-crypt, including dm-integrity setup. Just specify the disks, RAID level and other variables in a separate section of the
hardening.conffile, and set a password for the setup process inpassword.txt. The script will do the rest. Please note that dm-integrity needs to wipe the entire disk to initialise the integrity checksum, so depending on the size and speed of your disks, this can take up to several hours. Therefore, each operation is done in parallel by the script, so that you only have to wait once to initialise the disks.
Boot parameters
-
Slab merging is disabled which significantly increases the difficulty of heap exploitation by preventing overwriting objects from merged caches and by making it harder to influence slab cache layout.
GRUB_CMDLINE_LINUX="slab_nomerge" -
Memory zeroing at allocation and free time is enabled to mitigate some use-after-free vulnerabilities and erase sensitive information in memory.
GRUB_CMDLINE_LINUX="init_on_alloc=1 init_on_free=1" -
Page allocator freelist randomization is enabled.
GRUB_CMDLINE_LINUX="page_alloc.shuffle=1" -
Kernel Page Table Isolation is enabled to mitigate Meltdown and increase KASLR effectiveness.
GRUB_CMDLINE_LINUX="pti=on" -
vsyscalls are disabled as they are obsolete, are at fixed addresses and thus, are a potential target for ROP.
GRUB_CMDLINE_LINUX="vsyscall=none" -
The kernel panics on oopses to thwart certain kernel exploits.
GRUB_CMDLINE_LINUX="oops=panic" -
Enables randomisation of the kernel stack offset on syscall entries (introduced in kernel 5.13).
GRUB_CMDLINE_LINUX="randomize_kstack_offset=on" -
Enable a subset of known mitigations for CPU vulnerabilities and disable SMT.
GRUB_CMDLINE_LINUX="mitigations=auto,nosmt" -
Enables strict enforcement of IOMMU TLB invalidation so devices will never be able to access stale data contents.
GRUB_CMDLINE_LINUX="iommu=force iommu.passthrough=0 iommu.strict=1" -
Enables IOMMU to prevent DMA attacks.
GRUB_CMDLINE_LINUX="intel_iommu=on amd_iommu=force_isolation" -
Disable the busmaster bit on all PCI bridges during very early boot to avoid holes in IOMMU.
GRUB_CMDLINE_LINUX="efi=disable_early_pci_dma" -
Restrict access to debugfs since it can contain a lot of sensitive information.
GRUB_CMDLINE_LINUX="debugfs=off" -
Distrusts the bootloader for initial entropy at boot.
GRUB_CMDLINE_LINUX="random.trust_bootloader=off" -
Entropy collection improvements.
/usr/lib/modules-load.d/30_security-misc.confjitterentropy_rng
Enables known mitigations for CPU vulnerabilities
-
Enable mitigations for both Spectre Variant 2 (indirect branch speculation) and Intel branch history injection (BHI) vulnerabilities.
GRUB_CMDLINE_LINUX="spectre_v2=on spectre_bhi=on" -
Disable Speculative Store Bypass (Spectre Variant 4).
GRUB_CMDLINE_LINUX="spec_store_bypass_disable=on" -
Enable mitigations for the L1TF vulnerability through disabling SMT and L1D flush runtime control.
GRUB_CMDLINE_LINUX="l1tf=full,force" -
Enable mitigations for the MDS vulnerability through clearing buffer cache and disabling SMT.
GRUB_CMDLINE_LINUX="mds=full,nosmt" -
Patches the TAA vulnerability by disabling TSX and enables mitigations using TSX Async Abort along with disabling SMT.
GRUB_CMDLINE_LINUX=tsx=off tsx_async_abort=full,nosmt" -
Mark all huge pages in the EPT as non-executable to mitigate iTLB multihit.
GRUB_CMDLINE_LINUX="kvm.nx_huge_pages=force" -
Force disable SMT as it has caused numerous CPU vulnerabilities. The only full mitigation of cross-HT attacks is to disable SMT.
GRUB_CMDLINE_LINUX="nosmt=force" -
Enables the prctl interface to prevent leaks from L1D on context switches.
GRUB_CMDLINE_LINUX=l1d_flush=on" -
Mitigates numerous MMIO Stale Data vulnerabilities and disables SMT.
GRUB_CMDLINE_LINUX="mmio_stale_data=full,nosmt" -
Enable mitigations for RETBleed (Arbitrary Speculative Code Execution with Return Instructions) vulnerability and disable SMT.
GRUB_CMDLINE_LINUX="retbleed=auto,nosmt"
Kernel self-protection
-
Kernel reboot scripts to choose which presets to load 'default' or 'hardened' preset to avoid installation problems of future upgrades.
-
Disable loading new modules. Be careful with using this option.
kernel.modules_disabled=1 -
Restricting access to kernel pointers.
kernel.kptr_restrict=2 -
Restricting access to kernel logs.
kernel.dmesg_restrict=1 -
Despite the value of dmesg_restrict, the kernel log will still be displayed in the console during boot. This option prevents those information leaks.
kernel.printk=3 3 3 3 -
Restricting eBPF to the CAP_BPF capability
kernel.unprivileged_bpf_disabled=1
net.core.bpf_jit_harden=2 -
Restricting loading TTY line disciplines to the CAP_SYS_MODULE capability
dev.tty.ldisc_autoload=0 -
The userfaultfd() syscall is often abused to exploit use-after-free flaws. 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. This functionality can be abused to load a malicious kernel and gain arbitrary code execution in kernel mode, so this sysctl disables it.
kernel.kexec_load_disabled=1 -
The SysRq key exposes a lot of potentially dangerous debugging functionality to unprivileged users. You can simply set the value to 0 to disable SysRq completely.
kernel.sysrq=0 -
Randomise memory space.
kernel.randomize_va_space=2 -
These prevent creating files in potentially attacker-controlled environments, such as world-writable directories.
fs.protected_fifos=2fs.protected_regular=2 -
This only permits symlinks to be followed when outside of a world-writable sticky directory, when the owner of the symlink and follower match or when the directory owner matches the symlink's owner.
fs.protected_symlinks=1fs.protected_hardlinks=1 -
ptrace is a system call that allows a program to alter and inspect another running process, which allows attackers to trivially modify the memory of other running programs.
kernel.yama.ptrace_scope=2 -
Use filename based on core_pattern value.
kernel.core_uses_pid=1 -
Performance events add considerable kernel attack surface and have caused abundant vulnerabilities. Be careful, performance might be affected. Deactivated by default.
#kernel.perf_event_paranoid=2 -
ASLR is a common exploit mitigation which randomises the position of critical parts of a process in memory. This can make a wide variety of exploits harder to pull off, as they first require an information leak. The above settings increase the bits of entropy used for mmap ASLR, improving its effectiveness. The values of these sysctls must be set in relation to the CPU architecture. The values are compatible with x86, but other architectures may differ.
vm.mmap_rnd_bits=32vm.mmap_rnd_compat_bits=16 -
Deactivation of Core Dumps via
sysctl.
kernel.core_pattern=|/bin/false
Certain Kernel modules are disabled and blacklisted
- Deactivates Netfilter's connection tracking helper - this module increases kernel attack surface by enabling superfluous functionality such as IRC parsing in the kernel. Hence, this feature is disabled.
- The vivid kernel module is only required for testing and has been the cause of multiple vulnerabilities so it is disabled.
Disable Uncommon Network Protocols
- DCCP - Datagram Congestion Control Protocol
- SCTP - Stream Control Transmission Protocol
- RDS - Reliable Datagram Sockets
- TIPC - Transparent Inter-process Communication
- HDLC - High-Level Data Link Control
- AX25 - Amateur X.25
- NetRom
- X25
- ROSE
- DECnet
- Econet
- af_802154 - IEEE 802.15.4
- IPX - Internetwork Packet Exchange
- AppleTalk
- PSNAP - Subnetwork Access Protocol
- p8023 - Novell raw IEEE 802.3
- p8022 - IEEE 802.2
- CAN - Controller Area Network
- ATM
Disable Uncommon Filesystems
- cramfs
- fat # Not disabled in case of UEFI setup
- freevxfs
- jffs2
- hfs
- hfsplus
- squashfs
- udf
Disable Uncommon Network Filesystems
- cifs
- nfs
- nfsv3
- nfsv4
- ksmbd
- gfs2
Network Hardening Settings
-
ICMP redirect acceptance, ICMP redirect sending, source routing and IPv6 router advertisements are disabled to prevent man-in-the-middle attacks.
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 -
The kernel is configured to ignore all ICMP requests to avoid Smurf attacks, make the device more difficult to enumerate on the network and prevent clock fingerprinting through ICMP timestamps.
net.ipv4.icmp_echo_ignore_all=1 -
RFC1337 is enabled to protect against time-wait assassination attacks by dropping RST packets for sockets in the time-wait state.
net.ipv4.tcp_rfc1337=1 -
TCP syncookies are enabled to prevent SYN flood attacks.
net.ipv4.tcp_syncookies=1 -
IP source routing is disabled, we are not a router:
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 -
Ignoring broadcasts request.
net.ipv4.icmp_echo_ignore_broadcasts=1 -
Ssource validation of packets received from all interfaces of the machine enabled. This protects against IP spoofing, in which an attacker sends a packet with a fraudulent IP address.
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1 -
Logging martian packets, which is a packet with a source address which is obviously wrong - nothing could possibly be routed back to that address.
net.ipv4.conf.all.log_martians=1
net.ipv4.conf.default.log_martians=1
Restrictive mount options
- Further hardening of the already recommended CISS Partition scheme, incl. apt preparation to handle updates to the fact that the mounted /tmp is hardened:
proc /proc proc nosuid,nodev,noexec,hidepid=2 0 0
tmpfs /dev/shm tmpfs rw,nodev,nosuid,noexec,relatime,size=1G 0 0
/boot ext4 defaults,nodev,nosuid,noexec 0 2
/home ext4 defaults,rw,nosuid,nodev,relatime 0 2
/tmp ext4 defaults,rw,nodev,nosuid,noexec 0 0
/usr ext4 defaults,rw,nodev 0 2
/var ext4 defaults,rw,nosuid,nodev,relatime 0 2
/var/log ext4 defaults,rw,nodev,nosuid,noexec 0 2
/var/tmp ext4 defaults,rw,nodev,nosuid,noexec 0 2
/var/log/audit ext4 defaults,rw,nodev,nosuid,noexec 0 2
/etc/apt/apt.conf.d/50apthardening
Dir::Cache::Archives "/etc/hardening/aptcache";
Dir::State::status "/etc/hardening/varlibdpkg/status";
DPkg::Pre-Install-Pkgs {"mount -o remount,exec /tmp";};
DPkg::Post-Invoke {"mount -o remount /tmp";};
APT::ExtractTemplates::TempDir "/etc/hardening/tmp";
Further Hardening
Additional Kernel Hardening
- Kernel update to zabbly project if selected. Warning !!! As those kernels aren't signed by a trusted distribution key, you may need to turn off Secure Boot on your system in order to boot this kernel.
- Coredumps are disabled as they may contain important information such as encryption keys or passwords. See also Kernel self protection
Apt Hardening
- Enabling "apt-get --error-on=any" which makes apt exit non-zero for transient failures.
/etc/apt/apt.conf.d/40error-on-any - Enabling APT seccomp-BPF sandboxing.
/etc/apt/apt.conf.d/40sandbox - Changing
sources.listto use only Debian https sources.
DNS Server
- The following free DNS-Server are used, to not rely on standard ISP non-free server: coresecret.eu DNS)
IPv4: 135.181.207.105
IPv4: 89.58.62.53
IPv6: 2a01:4f9:c012:a813:135:181:207:105
IPv6: 2a0a:4cc0:1:e6:89:58:62:53
Entropy collection improvements
- The jitterentropy_rng kernel module is loaded as early as possible during boot to gather more entropy via:
/usr/lib/modules-load.d/30_security-misc.confjitterentropy_rng - Distrusts the CPU for initial entropy at boot as it is not possible to audit, may contain weaknesses or a backdoor.
- Gathers more entropy during boot if using the linux-hardened kernel patch.
- Installation of haveged 'Linux entropy source using the HAVEGE algorithm'.
Permissions, Authentication
- Adding a sudoer user.
- Further hardening such as umask 077 (not for root: because then configuration files created in /etc by the system administrator would be unreadable by "others" and break applications.) This means, files created by non-root users cannot be read by other non-root users by default.
- Setting up a cron.allow file to restrict access to cron to authorised users.
- Hardening of files like grub, cron and many more, replaced issue, issue.net, banner with generic text.
- Overwrite protection module to opt in. In each case of redirection, copying, moving the goal is to add an extra hurdle when the operation may have the side effect of erasing some existing data, even though erasing existing data is not the primary goal of the operation.
- Hardening the grub bootloader with password protection to increase the security of your full disk encrypted setup ( this is not a big burden to overcome if someone has direct access to the server, therefore the
/bootencryption is recommended ). - Changing the machine ID to the whonix ID.
- Change the login.defs and the pam module to
yescrypt, including a costfactor of '8'. - Preparation for the Google Authenticator 2FA module. This step must be performed after setup and a reboot.
Software tools installation
- Ansible preparation either as control or managed node.
- Lynis integration.
- htop installation.
- makepasswd installation.
- mtr installation.
- neofetch installation.
- pwgen installation.
- zsh installation.
Security Extensions installation
- SELinux or AppArmor installation and setup, select which security extensions you want to prepare in the .conf file.
- Installation of a SELinux policy generator script.
SSH, ufw, fail2ban
- SSH hardening, choose your port, choose whether to use a bastion or jump host, restrict KEX, ciphers, MACs to the most secure options available, restrict access via allow user policy. Your added sudoer will automatically be added to the SSH allow users list.
- ufw hardening,
default deny incominganddefault deny outgoingif selected in .conf file, incl. preset of selected outgoing ports to open to ensure smooth operation of freshly hardened server. - fail2ban incl. better-than-honeypot hardening: Anyone who touches the server on a port that is not open will be immediately banned for 24 hours. Be careful not to ban yourself. If you are using a Bastion or Jump server, the designated IPv4 and IPv6 /64 subnet will be added to the default fail2ban ignore-ip list. Otherwise the touching Server will be banned after the 16th attempt.
- Also the fail2ban service itself is hardened via systemd
/etc/systemd/system/fail2ban.service.d/override.confpolicy file.
QEMU Guest Agent Hardening
- Removal of the QEMU guest agent: if you are using a VM with full disk encryption, there is still a chance to gain access to the VM via password reset. Therefore the QEMU guest agent will be removed. Also consider using a Netcup Root VPS: they are using memory encryption, so this gives you a bit more security.
Several other hardening setting
- Hardening of the ntp servers so that the PTB NTPSec server are selected, therefore chrony is installed and NTPSec is requried to retrieve the timestamps.
- Preparation of SSL hardening to accept only TLSv1.3 AES256 bit ciphers.
- Retrieval of an auditd ruleset, preparation of auditd, aide and debsums.
Main Installation
! Warnings !
- MUST: This script is considered to be run after a fresh Debian Bookworm installation.
- MUST: Never run it on an active server - data loss, damage and / or malfunction may occur. You have been warned.
- MUST: If you are installing Debian GNU/Linux from a minimal CD by using the network, you will need to install
wgetpackage before you can use the hardening script. - Only x86_64 architectures are supported (arm64 support is still under development).
- GRUB uses the US keyboard layout by default, it is strongly RECOMMENDED to choose your password/passphrase accordingly. Keep this in mind when setting the password for GRUB and/or `/boot' encryption.
- You MAY upgrade the kernel to the zabbly project if selected. As these kernels aren't signed by a trusted distribution key, you MUST disable secure boot on your system to boot this kernel.
- As of
ML5.0.512, this script is not idempotent. Although the script has been thoroughly tested against the advancedERRandSIGNALtraps and any apparent false positives have been mitigated, if your specific configuration fails at the first attempt and you can rule out that neither the recommendations and/or requirements have been violated, it is up to you to decide if you want to rely on a setup that hasn't been run successfully. It is therefore highly recommended that you thoroughly analyse any errors that have occurred.
Prerequisites
- Root Server (RECOMMENDED [netcup Root VPS RS Series G11 | Hetzner shared AMD VPS CPXnn Series | Hetzner dedicated VPS CCXnn Series | own Proxmox installation]).
- AMD 7003 and later CPU are strongly RECOMMENDED for their RAM encyrption features:
- Secure Memory Encryption (SME): Encrypts the entire physical memory to protect data from attacks such as cold boot attacks.
- Secure Encrypted Virtualisation (SEV): Extends storage encryption to virtual machines so that each VM has its own encryption key.
- SEV-ES (Secure Encrypted Virtualisation - Encrypted State): Additionally encrypts the CPU registers when a VM is paused or hibernated, providing additional protection.
- SEV-SNP (Secure Encrypted Virtualisation - Secure Nested Paging): Adds additional protection against hypervisor-based attacks and provides an even higher level of security for VMs. It protects the integrity of the pages used by the VM and prevents tampering by the hypervisor.
- AMD 7003 and later CPU are strongly RECOMMENDED for their RAM encyrption features:
- MUST: Fresh Debian Bookworm installation. For further preparations refer to CISS.2024.bookworm.installation Tutorial.
- MUST: This script has to be run as
root. - MUST: SSH public key for
rootMUST be provided before starting the script. - MUST: SSH public key for the sudoer user to create, if selected, MUST be provided before starting the script.
- All variables in
hardening.confMUST be enclosed in double quotes. The detailed naming scheme in the description section MUST be strictly followed.
Partition Scheme
To minimise the attack surface, make sure that your freshly installed Debian Bookworm server is set up with RECOMMENDED full disk encryption and you SHOULD follow best practices that /boot, /, /tmp, /home, /var, /usr, /var/log, /var/log/audit, /var/tmp and swap are on separate partitions:
BIOS mode (Standard scheme)
Please install a fresh instance of Debian Bookworm using the netinstaller, and partition the harddrive using the following scheme, where ext4 fs is RECOMMENDED:
sda disk
+-sdaN part /boot
+ sth
+ sth
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-swap lvm [SWAP]
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
After encryption of /boot the parttion scheme would look like:
sda disk
+-sdaN part
| +-boot_crypt crypt /boot
+ sth
+ sth
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-swap lvm [SWAP]
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
UEFI mode (Standard scheme)
Please install a fresh instance of Debian Bookworm using the netinstaller, and partition the harddrive using the following scheme, where ext4 fs is RECOMMENDED:
sda disk
+-sdaN part
+-sdaN part /boot/efi
+-sdaN part /boot
+ sth
+ sth
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-swap lvm [SWAP]
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
After encryption of /boot the parttion scheme would look like:
sda disk
+-sdaN part
+-sdaN part /boot/efi
+-sdaN part
| +-boot_crypt crypt /boot
+ sth
+ sth
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-swap lvm [SWAP]
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
UEFI mode (Ephemeral Swap scheme)
Please install a fresh instance of Debian Bookworm using the netinstaller, and partition the harddrive using the following scheme, where ext4 fs is RECOMMENDED:
sda disk
+-sdaN part
+-sdaN part /boot/efi
+-sdaN part /boot
+-sth
+-sdaN part
| +-swap crypt [SWAP]
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
After encryption of /boot the parttion scheme would look like:
sda disk
+-sdaN part
+-sdaN part /boot/efi
+-sdaN part
| +-boot_crypt crypt /boot
+-sth
+-sdaN part
| +-swap crypt [SWAP]
+ sth
+-sdaN part
| +-sdaN_crypt crypt
| +-label--vg-root lvm /
| +-label--vg-home lvm /home
| +-label--vg-tmp lvm /tmp
| +-label--vg-usr lvm /usr
| +-label--vg-var lvm /var
| +-label--vg-var_log lvm /var/log
| +-label--vg-var_tmp lvm /var/tmp
| +-label--vg-var_log_audit lvm /var/log/audit
+ sth
+ sth
+ sth
Full Example Configuration
- UEFI mode
- Full-Disk-Encryption
- LUKS2
/bootencryption - Ephemeral
SWAPencryption - Ephemeral
/tmpencryption LVM on RAID6 on dm-integrity on dm-cryptHA setup
sda disk
+-sda1 part
+-sda2 part /boot/efi
+-sda3 part
| +-crypt_boot crypt /boot
+-sda4 part
| +-crypt_ephemeral_swap crypt [SWAP]
+-sda5 part
| +-crypt_ephemeral_tmp crypt /tmp
+-sda6 part
+-sda6_crypt_system crypt
+-vg00-home lvm /home
+-vg00-root lvm /
+-vg00-var_log lvm /var/log
+-vg00-var_log_audit lvm /var/log/audit
+-vg00-usr lvm /usr
+-vg00-var_tmp lvm /var/tmp
+-vg00-var lvm /var
sdb disk
+-sdb1 part
+-crypt_raid_sdb1_dif crypt
+-crypt_raid_sdb1 crypt
+-md127 raid6
+-vg_data-vl_data lvm /mnt/point
sdc disk
+-sdc1 part
+-crypt_raid_sda1_dif crypt
+-crypt_raid_sda1 crypt
+-md127 raid6
+-vg_data-vl_data lvm /mnt/point
sdd disk
+-sdd1 part
+-crypt_raid_sdd1_dif crypt
+-crypt_raid_sdd1 crypt
+-md127 raid6
+-vg_data-vl_data lvm /mnt/point
sde disk
+-sde1 part
+-crypt_raid_sde1_dif crypt
+-crypt_raid_sde1 crypt
+-md127 raid6
+-vg_data-vl_data lvm /mnt/point
Tested and recommended VPS Provider
Latest: Tested and recommended VPS Provider
| Tested & Recommended VPS Provider | Date | Version tested | Notes | Lynis Score |
|---|---|---|---|---|
| Hetzner Shared vCPU (AMD64) CPXn | 14.08.2024 | V5.0.768 | B) E) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 16) **) +) | 92 |
| Netcup Root-Server Generation 11 | 08.08.2024 | V5.0.768 | U) E) 2) 3) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) *) +) #) | 94 |
History: Tested and recommended VPS Provider
| Tested & Recommended VPS Provider | Date | Version tested | Notes | Lynis Score |
|---|---|---|---|---|
| Contabo Cloud VPS | 26.05.2024 | V4.4.256 | 1) 5) 6) 7) 8) 9) 10) 11) | 92 |
| Contabo Storage VPS | 27.05.2024 | V4.4.256 | 1) 5) 6) 7) 8) 9) 10) 11) | 92 |
| Hetzner Shared vCPU (AMD64) CPXn | 14.08.2024 | V5.0.768 | B) E) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 16) **) +) | 92 |
| Hetzner Shared vCPU (x86) | 30.06.2024 | V4.7.512 | B) E) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) | 94 |
| Hetzner Dedicated vCPU | tba | |||
| Netcup vServer ARM64 Generation 11 | tba | P) U) E) | ||
| Netcup Root-Server Generation 11 | 08.08.2024 | V5.0.768 | U) E) 2) 3) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) *) +) #) | 94 |
| Netcup Root-Server Generation 11 | 07.08.2024 | V5.0.512 | U) E) 2) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) *) +) #) | 94 |
| Netcup Root-Server Generation 11 | 05.08.2024 | V5.0.256 | U) E) 2) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) *) +) #) | 94 |
| Netcup Root-Server Generation 11 | 04.08.2024 | V5.0.128 | U) E) 2) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) *) +) | 94 |
| Netcup Root-Server Generation 11 | 03.08.2024 | V5.0.128 | U) E) 2) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) *) | 94 |
| Generic Proxmox 8.2.4 based VM | 22.06.2024 | V4.7.128 | B) G) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) | 94 |
Notes
B) BIOS Boot Setup tested.
U) UEFI Boot Setup tested.
E) Locale en_US.UTF-8 tested.
G) Locale de_DE.UTF-8 tested.
P) No disk encryption applied at all due to password input problems in the web console.
1) No KVM or Webconsole available.
2) Grub Password Installation: checked.
3) Full Disk Enryption: checked.
4) /boot encryption LUKS1: checked.
5) journalctl --boot=0: checked.
6) systemctl status -- failed: checked.
7) Reboot scripts: checked.
8) Network - mtr, ping (-4 && -6): checked.
9) fail2ban-client status: checked.
10) chronyc: NTPSec: checked.
11) No Lynis warnings.
12) spectre-meltdown-checker: not vulnerable.
13) Ephemeral SWAP encryption: tested.
14) Full Disk Enryption LUKS2: checked.
15) LVM on RAID6 on dm-crypt incl. dm-integrity: checked.
16) Ephemeral `/tmp` encryption: tested.
+) Run with debug mode enabled.
#) All modules tested.
*) Tested against: 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1
**) Tested against: 6.9.7+bpo-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.9.7-1
sha512 Hashes
b3a3f188bd09e9f18a181544eff7a8f453cf5f434d4b3727adf85697a55dfd99474e45d7213b60e85d4fced0de596c0dfe3526c3ac02530c7165af036542672a *hardening.conf
43eedf3123c86954277215ff425149f772dfe637f374fac32830f9fb6439eb814ebe15cb50d340eea7dcbdfd52acdde0931f23e4380880b902d3ff659f639f5b *hardening.sh
Server Preparation and Setup
A detailed Tutorial is available at CISS.2024.vps.bookworm.hardening Tutorial.
.conf file values
All variables MUST be entered in double quotes.
#!/bin/bash
###########################################################################################
# Debian Bookworm VPS Hardening Setup Script Config File V5.0.768.2024.08.14 #
###########################################################################################
# Copyright (c) 2019 - 2024, Marc Weidner, Centurion Intelligence Consulting Agency #
# https://coresecret.eu/ #
# Licensed under the EUROPEAN UNION PUBLIC LICENCE v. 1.2 https://eupl.eu/1.2/en/ #
###########################################################################################
# https://keys.openpgp.org/vks/v1/by-fingerprint/A6D46A56AE17A185AB0F6DB77095A8A13CBE0FA3 #
# Fingerprint A6D4 6A56 AE17 A185 AB0F 6DB7 7095 A8A1 3CBE 0FA3 ## valid till: 01.01.2031 #
###########################################################################################
# Please change the variables according to your needs #
###########################################################################################
###########################################################################################
# Encryption related #
###########################################################################################
BOOTENCRYPTION="Yes"
BOOTENCRYPTION_FORMAT="LUKS2"
EPHEMERAL_SWAP="Yes"
EPHEMERAL_SWAP_PARTITION="sda4" # https://coresecret.eu/tutorials/ciss-2024-bookworm/
EPHEMERAL_TMP="Yes"
EPHEMERAL_TMP_PARTITION="sda5" # https://coresecret.eu/tutorials/ciss-2024-bookworm/
GRUB_PSSWD="Yes"
LUKSITERATION="2097152"
###########################################################################################
# Script related #
###########################################################################################
SELFCHECK="Yes"
SELFCHECKDL="Yes"
TRUSTKEY="Yes"
TRUSTLEVEL="5"
###########################################################################################
# Server related #
###########################################################################################
ANSIBLE="Managed"
ARCHITECTURE="AMD64"
CURRENTTIMEZONE="Europe/Lisbon"
FQDN="fully.qualified.domain.name"
IPV4="123.123.123.123"
IPV6="AAAA:BBBB:CCCC:DDDD:EEEE:FFFF::1"
JUMPHOST="Yes"
JUMPHOST_IPV4="123.123.123.123"
JUMPHOST_IPV6="AAAA:BBBB:CCCC:DDDD:EEEE:FFFF:9999:1111"
KERNELUPDATE="Yes"
LOGROTATE_CHANGE="Yes"
LOGROTATE_COUNT="90"
OPENSSL_SECLEVEL="2"
QEMUREMOVAL="Yes"
SECEXTENSIONS="selinux"
UFW_OUT_POLICY="deny"
VPSPROVIDER="Netcup"
###########################################################################################
# SSH related #
###########################################################################################
SSHKEYROUNDS="768"
SSHPORT="64000"
USERSSHPUBKEY="ssh-ed25519 BBBBC3NzaC1lZDI1NTE5DDDDIFNRPjNUxyfCE5LYZArxx/u/RdMfGz4uTxiiPAziIhel 2024_255.255.255.255_user"
###########################################################################################
# User related #
###########################################################################################
ADDUSER="Yes"
ADDSHORTCUTS="Yes"
OVERWRITEPROTECTION="Yes"
USERNAME="testuser"
ZSH_INST="Yes"
###########################################################################################
# LVM on mdadm on dm-crypt incl. dm-integrity related #
###########################################################################################
# ! Important ! - Also change the password in the password.txt file !
LVM_RAID_INTEGRITY="Yes"
DISK_01="/dev/sdb"
DISK_02="/dev/sdc"
DISK_03="/dev/sdd"
DISK_04="/dev/sde"
#DISK_05="/dev/sdf"
#DISK_06="/dev/sdg"
# Just uncomment or add more disks to the .conf file. The script will auto-iterate through
# all the device-variables. Follow the naming scheme of the disk-variables.
DISK_USAGE_PERCENTAGE="99"
NAME_RAID="md_data"
NAME_VG="vg_data"
NAME_VOLUME="vl_data"
NAME_MOUNTPOINT="point"
RAID_LEVEL="6"
###########################################################################################
# ! No changes below this line ! #
###########################################################################################
CONFVERS="V5.0.768.2024.08.14"
DETECTED_LOCALE="$(grep LANG= /etc/default/locale | cut -d'=' -f2- | tr -d '"')"
SLEEPTIMER="1"
TARGET_DIR="/root/hardening"
UBUNTU_CODENAME="jammy"
USERPASSWD="$(pwgen -n 32 -B -c -s -1)"
ZSH_PROMPT="PROMPT='\$USER_COLOR%D%f|\$USER_COLOR%n%f@%F{005}%M%f:%F{006}%d%f/>>%(?.%F{002}%?.%F{001}%?)%f|~%#> '"
ZSH_RPROMPT="RPROMPT='%h|[\$USER_COLOR%*%f]'"
ADDUSER
Please select if you would like to add a Sudoer User as well. Allowed values are:
"Yes" or "No"
ADDSHORTCUTS
Please specify if you want to add few shortcuts. Allowed values are:
"Yes" or "No"
ANSIBLE
Please select if you want to install the Ansible Server Controle or the Managed Node or if you want to Skip the installation at all. Allowed values are:
"Controle" or "Managed" or "Skip"
ARCHITECTURE
Please select the architecture of the CPU. Allowed values are:
"AMD64" or "INTEL64" or "arm64"
BOOTENCRYPTION
Please specify if you want to encrypt the /boot partition to further harden your system. Note that GRUB will load the US keyboard layout by default unless you change it. So choose your /boot password carefully in the interactive dialog. Allowed values are:
"Yes" or "No"
BOOTENCRYPTION_FORMAT
Please specify the format version for /boot encryption. For LUKS2 /boot encryption the following backported package will also be installed: grub-common (2.12-1~bpo12+1). Note that GRUB will load the US keyboard layout by default unless you change it. So choose your /boot password carefully in the interactive dialog. Allowed values are:
"LUKS2" or "LUKS1"
CURRENTTIMEZONE
Allowed values are:
"Europe/Lisbon" or any other specified Timezone (TZ) identifier: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
EPHEMERAL_SWAP
Please indicate if you have prepared the Debian Bookworm server for the ephemeral SWAP partition. In this scenario, the SWAP area will be initialised with a random new key every boot time to maximise security considerations. Allowed values are:
"Yes" or "No"
EPHEMERAL_SWAP_PARTITION
If you opt in to the ephemeral SWAP setup, please specify the prepared dedicated partition here.
EPHEMERAL_TMP
Please indicate if you have prepared the Debian Bookworm server for the ephemeral /tmp partition. In this scenario, the /tmp area will be initialised with a random new key every boot time to maximise security considerations. Allowed values are:
"Yes" or "No"
EPHEMERAL_TMP_PARTITION
If you opt in to the ephemeral /tmp setup, please specify the prepared dedicated partition here.
GRUB_PSSWD
Please select if you want to harden the Grub Booloader with a password. Please note that you will need KVM capabilities to be able to enter the password before the server has booted into the system. This feature is only tested on Netcup VPS servers 2024 and later and on Hetzner VPS 2024 and later and on own Proxmox Servers. Allowed values are:
"Yes" or "No"
FQDN
Please specify the desired FQDN ot the server. Allowed values are:
any valid FQDN: https://en.wikipedia.org/wiki/Fully_qualified_domain_name
IPV4
Please provide the IPv4 of the server in question.
IPV6
As a good practice, it is recommended that you have entered a PTR record that matches the FQDN that you have set up in the DNS section of your DNS service provider, stating that the following IPv6 convention is used and suggested:
Consider your IPv4 to be: 123.123.123.123
Consider your IPv6 Prefix to be: 2a10:ABCD:1111:FFFF::1/64
Then the server IPv6 is as follows: 2a10:ABCD:1111:FFFF:123:123:123:123/128
For Contabo: Please enter the IPv6 you have entered in the PTR Record section.
For Hetzner: Please enter the IPv6 you have entered in the Networking tab.
For Netcup: Please enter the IPv6 you have specified in the Netcup Server Control Panel.
JUMPHOST
Please specify if your new server is reachable via a Bastion / Jump Server. Allowed values are:
"Yes" or "No"
JUMPHOST_IPV4
Please provide the IPv4 of the server in question. In case you are using a Jumphost, please add here the IPv4 and IPv6 of the respective Bastion / Jump Server which will be added to the fail2ban ignoreip list.
JUMPHOST_IPV6
Please provide the IPv4 of the server in question. In case you are using a Jumphost, please add here the IPv4 and IPv6 of the respective Bastion / Jump Server which will be added to the fail2ban ignoreip list.
KERNELUPDATE
Please specify if you want to change the kernel image. If you select "Yes", you will be prompted to select an available kernel during setup; if you select "No", no kernel update will be installed at all. Enter "Zabbly" to install the latest Linux kernel available from Zabbly project
Allowed values are:
"Yes" or "No" or "Zabbly"
LOGROTATE_CHANGE
Please specify if you want to change the log rotation frequency of the fail2ban and ufw logs from weekly to daily. Allowed values are:
"Yes" or "No"
LOGROTATE_COUNT
Please specify the number of days the above logs should be kept. Allowed values are:
"96" or any other postive integer you prefer
LUKSITERATION
The PBKDF parameters are determined by benchmark when the key slot is created (or updated). Thus, they only make sense if the environment in which the LUKS device is opened matches the one in which it's formatted (same CPU, same RAM size, etc.). Unlocking from GRUB does count as an environment mismatch, because GRUB operates under tighter memory constraints and does not take advantage of all crypto-related CPU instructions. Concretely, this means that unlocking a LUKS device from GRUB can take much longer than unlocking it from the normal system. Since GRUB's LUKS implementation isn't capable of benchmarking, you'll have to do it # manually. It's easier for PBKDF2 because it has a single parameter to play with (iteration count) - while Argon2 has two (iteration count and memory) - and changing it has a linear effect on unlock time: for example, halving the iteration count would speed up unlocking by a factor of two. (And, of course, making low entropy passphrases twice as easy to brute-force. There is a trade-off here. Balancing convenience and security is the whole point of running PBKDF benchmarks). The preset of 2,097,152 rounds works well enough on the systems tested. Allowed values are:
"2097152" or any other postive integer you prefer
LVM_RAID_INTEGRITY
Please specify if you want to setup an LVM on mdadm on dm-crypt incl. dm-integrity cluster. Allowed values are:
"Yes" or "No"
If so, please also specify the following variables:
- DISK_01="/dev/sdb"
- DISK_02="/dev/sdc"
- and so forth
- DISK_USAGE_PERCENTAGE="99"
- It is best practice not to use all the hard disk space for a RAID member.
- NAME_RAID="md_data"
- Desired name for the created RAID group.
- NAME_VG="vg_data"
- Desired name of the volume group to be created on top of the RAID group.
- NAME_VOLUME="vl_data"
- The name of the new volume to be created in the volume group.
- NAME_MOUNTPOINT="nc" -The new directory to mount the volume to.
- RAID_LEVEL="6"
- Supported values are "0", "1", "5", "6"
OPENSSL_SECLEVEL
SECLEVEL=2: Medium security (112-bit security).
SECLEVEL=3: High security level. Allows 128-bit security.
SECLEVEL=4: Very high security level. (192-bit security, 3840-bit RSA, SHA-384).
SECLEVEL=5: Ultra-high security level. (256-bit security, 7680-bit RSA, SHA-512).
- SECLEVEL=2
- RSA: Keys must be at least 2048 bits long.
- DHE: Diffie-Hellman Ephemeral (DHE) keys must be at least 2048 bits long.
- DH: Static Diffie-Hellman (DH) keys must be at least 2048 bits long.
- ECC: Elliptic Curve Cryptography (ECC) keys must be at least 224 bits long.
- Only hash algorithms providing at least 112 bits of security are allowed (SHA-224).
- SECLEVEL=3
- Minimum RSA, DHE, and DH key sizes: 3072 bits.
- Minimum ECC key sizes: 256 bits.
- Hash algorithms: Requires SHA-256 or better for signatures and MACs.
- Symmetric encryption key sizes: Must be at least 192 bits (e.g., AES-128).
- SECLEVEL=4
- Suitable for highly sensitive environments requiring strong cryptographic guarantees.
- Minimum RSA, DHE, and DH key sizes: 3840 bits.
- Minimum ECC key sizes: 384 bits.
- Hash algorithms: Requires SHA-384 or better for signatures and MACs.
- Symmetric encryption key sizes: Must be at least 192 bits (e.g., AES-192).
- SECLEVEL=5
- Suitable for extremely sensitive and critical applications requiring the highest level of cryptographic strength.
- Minimum RSA, DHE, and DH key sizes: 7680 bits.
- Minimum ECC key sizes: 512 bits.
- Hash algorithms: Requires SHA-512 or better for signatures and MACs.
- Symmetric encryption key sizes: Must be at least 256 bits (e.g., AES-256).
Allowed values are:
"5"or"4"or"3"or"2"
OVERWRITEPROTECTION
The following will be added to .bashrc and / or .zshrc
set -o noclobber
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
In each case (redirection, copying, moving, deleting), the goal is to add an extra hurdle when the operation may have the side effect of erasing some existing data, even though erasing existing data is not the primary goal of the operation. Allowed values are:
"Yes" or "No"
QEMUREMOVAL
This is to ensure that for a Full Disk Encryption Setup on a Netcup Root Server, the QEMU Agent Root Password Reset feature is removed. Therefore, a malicious agent must take a snapshot of the host's RAM and inspect where the Full Disk Encryption Setup key is stored. Given that Netcup also supports RAM encryption, this provides a little extra security. Allowed values are:
"Yes" or "No"
SECEXTENSIONS
Please specify if you want to install and activate AppArmor or SELinux Security Extensions. SELinux defines access controls for applications, processes and files on a system with security policies. These policies determine what users may and may not access. If no policy is defined for a process, application or directory, SELinux prohibits access to it. The system is integrated into the system's kernel. AppArmor uses profiles to determine which files and rights an application requires. Each system uses certain functions differently. Allowed values are:
"selinux" or "apparmor"
SELFCHECK
Please specify if you want the script to self-verify, or not to self-verify the script and avoid a script verification failure due to an invalid signature or for easy and convenient script editing. Allowed values are:
"Yes" or "No"
SELFCHECKDL
Please specify if you want the script to self-verify all downloaded resources, or not if you want to modify the resources and avoid a script verification failure due to an invalid signature for easy and convenient script editing. Allowed values are:
"Yes" or "No"
SSHKEYROUNDS
The provided SSH hardening module generates new SSH keys with the specified number of KDF rounds to harden the keys against brute force attacks. Please note that the higher the number of rounds you select, the longer it will take to decrypt the keys. Allowed values are:
"768" or any other postive integer you prefer
SSHPORT
This hardening mechanism is a kind of security by obscurity. However, most bots that scan your SSH port do not scan all ports every time. At the very least, your log files will be grateful to be rid of tons of SSH login attempts. Allowed values are:
any port in the range "32768" to "65535"
TRUSTKEY
Please specify if you want to trust my ed25519 Gitea Signing Key. All my used keys reside in HSM like NitroKey and signing operations are done via an airgapped system. Allowed values are:
"Yes" or "No"
TRUSTLEVEL
Please specify the trust level of the signing key. PGP Trustlevel:
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
Allowed values are:
"5" or "4" or "3"
UFW_OUT_POLICY
Specify the default outgoing policy for the uncomplicated firewall. Default deny outgoing means that outgoing traffic is generally blocked unless otherwise allowed. Therefore, specific ports such as 53/UDP for DNS and 853/UDP for DNS over Quic are opened by default by the hardening module to ensure that the freshly hardened server is working properly. Allowed values are:
"deny" or "allow"
The complete list of opened ports:
- 21/tcp comment 'Standard FTP TCP Outgoing Port'
- 22/tcp comment 'Standard SSH TCP Outgoing Port'
- 25/tcp comment 'Standard SMTP TCP Outgoing Port'
- 53/tcp comment 'Standard DNS TCP Outgoing Port'
- 80/tcp comment 'Standard HTTP TCP Outgoing Port'
- 123/tcp comment 'Standard NTP TCP Outgoing Port'
- 143/tcp comment 'Standard IMAP TCP Outgoing Port'
- 443/tcp comment 'Standard HTTPS TCP Outgoing Port'
- 465/tcp comment 'Standard SMTPS TCP Outgoing Port'
- 587/tcp comment 'Standard SMTPS TCP Outgoing Port'
- 993/tcp comment 'Standard IMAPS TCP Outgoing Port'
- 4460/tcp comment 'Standard NTS TCP Outgoing Port'
$SSHPORT/tcp comment 'Individual SSH TCP Outgoing Port'
- 53/udp comment 'Standard DNS UDP Outgoing Port'
- 123/udp comment 'Standard NTP UDP Outgoing Port'
- 443/udp comment 'Standard QUIC UDP Outgoing Port'
- 853/udp comment 'Standard DNSoverQuic UDP Outgoing Port'
USERNAME
Enter the name of the sudoer user you want the script to create.
USERSSHPUBKEY
Enter the SSH PUBLIC key of the user the script shall create.
VPSPROVIDER
Please select the VPS provider you are using. Or use "Generic" for a basic hardening of your generic server or VPS after a freshly installed Debian Bookworm environment including the CISS partition scheme. Allowed values are:
"Contabo" or "Hetzner" or "Netcup" or "Generic"
ZSH_INST
Please specify if you want to install zsh. Allowed values are:
"Yes" or "No"
SLEEPTIMER
This variable is used to set the clear screen routine after each module and is measured in seconds.
UBUNTU_CODENAME
DO NOT CHANGE. This variable is used to match the Debian Bookworm Ansible Controle Node installation.
USERPASSWD
Generated by the appropriate secure pwgen module and displayed after the setup process in the endnotes.
Using ./restart_*.sh scripts
-
restart_crontab.shwill be called by the generated cron entry at each reboot to check if the system should be booted into hardened kernel protection mode to load the/etc/sysctl.d/99-local.conf.holdsettings. If so, the settings are loaded, otherwise nothing is changed and no kernel self-protection settings are loaded. -
restart_hardening.shis a script that should be run via./restart_hardening.shin/rootto reboot the system into hardened mode with hardened/etc/fstabsettings and a hardened/etc/sysctl.d/99-local.hardenedpreset. -
restart_install.shis a troubleshooting script that should be run via./restart_install.shin/rootto run when installing or starting new software fails for whatever reason. The script will change the/etc/fstabentries generated by thehardening.shscript to the default values generated by the Debian Bookworminstallation process and will also not load the/etc/sysctl.d/99-local.hardenedpreset, so that no/etc/fstabrestrictions on the file system and no restrictions on further kernel and network stack hardening are implemented, to easily check if the hardened setup might interfere with new software components being installed. -
restart_selinux.shis a script that should be run via./restart_selinux.shin/rootto set SELinux to enforce mode while it is already in permissive mode. -
restart_ssh_hotfix.shis called by the generated cron entry each time the system is rebooted to stop and start the SSH daemon to fix common binding errors caused by SSH being loaded at boot time before the network stack has been set up. Additionally, an/etc/systemd/system/ssh.service.d/override.confis written by thehardening.shscript to provide multiple means of ensuring that the SSH daemon is properly started after a reboot.
Resources
Tutorials
- The following setup process and partitioning scheme is recommended: https://coresecret.eu/tutorials/ciss-2024-bookworm/
- Tutorial for this script: https://coresecret.eu/tutorials/debian-bookworm-hardening-script/
- A comprehensive list of all installed tools is available at: https://coresecret.eu/tutorials/debian-package-glossary/
Disk Encryption related
- https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system
- https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#Encrypted_boot_partition_(GRUB)
- https://wiki.archlinux.org/title/Dm-crypt/Device_encryption#Encryption_options_for_LUKS_mode
- https://wiki.archlinux.org/title/GRUB#Encrypted_/boot
- https://wiki.archlinux.org/title/GRUB#LUKS2
- https://wiki.archlinux.org/title/Advanced_Format
- https://packages.debian.org/bookworm-backports/grub-common
- https://www.kernel.org/doc/html/v5.5/admin-guide/device-mapper/dm-integrity.html
- https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption
- https://gitlab.com/cryptsetup/cryptsetup/-/wikis/FrequentlyAskedQuestions#2-setup
Kernel related
- https://wiki.archlinux.org/title/Kernel
- https://wiki.archlinux.org/title/Kernel_parameters
- https://www.kernel.org/
- https://github.com/anthraxx/linux-hardened
Policy related
- https://www.debian.org/doc/manuals/securing-debian-manual/
- https://www.tenable.com/audits/CIS_Debian_Linux_12_v1.0.1_L1_Server
- https://www.cisecurity.org/cis-benchmarks
- https://github.com/CISOfy/lynis
- https://github.com/lateralblast/lunar
- https://complianceascode.github.io/content-pages/guides/ssg-debian12-guide-standard.html
Security related
- https://wiki.archlinux.org/title/General_recommendations
- https://wiki.archlinux.org/title/Security
- https://wiki.archlinux.org/title/Identity_management
- https://wiki.archlinux.org/title/Capabilities
- https://privsec.dev/posts/linux/desktop-linux-hardening/
- https://wiki.archlinux.org/title/fail2ban#Service_hardenin
- https://theprivacyguide1.github.io/linux_hardening_guide
- https://github.com/zabbly/linux
Bash related
- https://www.gnu.org/software/bash/manual/
- https://www.shellcheck.net/
- https://explainshell.com/
- https://google.github.io/styleguide/shellguide.html
- https://github.com/mvdan/sh
- https://gist.github.com/Potherca/4f4ce1c8d4bcf4cd4aab
Error handling
- Use set -e - Writing Robust Bash Shell Scripts - David Pashley
- Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected? - BashFAQ/105 - Greg's Wiki
Acknowledgements
I would like to express my sincere gratitude to Mr Who-wants-to-live-forever for his gracious support and insightful and profound criticism.
Changelog
Available at: /doc/CHANGELOG.md
Screenshots
Available at: /doc/SCREENSHOTS.md
Security Policy
Available at: /doc/SECURITY.md
Troubleshooting
Available at: /doc/TROUBLESHOOTING.md
no tracking | no logging | no advertising | no profiling | no bullshit