6. Server Hardening
6.1. Setting the Correct Timezone
Section titled “6.1. Setting the Correct Timezone”Setting the correct timezone on your server is important for accurate logging, scheduled tasks, and ensuring that timestamps in your applications are consistent with your local time.
6.1.1. Checking and Setting the Timezone
Section titled “6.1.1. Checking and Setting the Timezone”First, check your current timezone configuration:
# Display the current timezonesudo timedatectlTo find and set the appropriate timezone:
# List all available timezonessudo timedatectl list-timezones
# Search for a timezone related to a specific citysudo timedatectl list-timezones | grep city
# Example: Search for Paris timezonesudo timedatectl list-timezones | grep Paris
# Set the timezone to Europe/Parissudo timedatectl set-timezone Europe/Paris
# Verify the timezone changesudo timedatectlExample output after setting the timezone:
Local time: Sun 2025-03-02 14:29:40 CET Universal time: Sun 2025-03-02 13:29:40 UTC RTC time: Sun 2025-03-02 13:29:40 Time zone: Europe/Paris (CET, +0100)System clock synchronized: yes NTP service: active RTC in local TZ: no6.2. Configuring Swap Space
Section titled “6.2. Configuring Swap Space”Swap space is a portion of the hard drive that the system can use as virtual memory when physical RAM is fully utilized. Properly configured swap space can prevent system crashes during high memory usage.
6.2.1. Recommended Swap Size
Section titled “6.2.1. Recommended Swap Size”The following table provides recommendations for swap size based on your server’s RAM:
| RAM | No Hibernation | With Hibernation | Maximum |
|---|---|---|---|
| 256MB | 256MB | 512MB | 512MB |
| 512MB | 512MB | 1024MB | 1024MB |
| 1024MB | 1024MB | 2048MB | 2048MB |
| 2GB | 1GB | 3GB | 4GB |
| 4GB | 2GB | 6GB | 8GB |
| 8GB | 3GB | 11GB | 16GB |
| 16GB | 4GB | 20GB | 32GB |
| 32GB | 6GB | 38GB | 64GB |
Source: Ubuntu SwapFaq
6.2.2. Checking Current Swap Status
Section titled “6.2.2. Checking Current Swap Status”Before creating a new swap file, check if swap is already enabled:
# Verify current swap statussudo swapon -s
# If no output appears, swap is not enabled
# You can also check with htop, which will show:# Swp[ 0K/0K] when swap is not enabled6.2.3. Removing Existing Swap (If Needed)
Section titled “6.2.3. Removing Existing Swap (If Needed)”If you need to change an existing swap file:
# Deactivate the swap filesudo swapoff /swapfile
# Backup fstab before editingsudo cp /etc/fstab /etc/fstab.bak
# Edit fstab to remove the swap entrysudo nano /etc/fstab
# Delete the swap filesudo rm /swapfile6.2.4. Creating a New Swap File
Section titled “6.2.4. Creating a New Swap File”Choose the appropriate size for your server based on the table above:
# Create a 2 GiB swap filesudo dd if=/dev/zero of=/swapfile bs=1024 count=2097152
# For 4 GiB swap filesudo dd if=/dev/zero of=/swapfile bs=1024 count=4194304
# For 6 GiB swap filesudo dd if=/dev/zero of=/swapfile bs=1024 count=6291456
# For 8 GiB swap filesudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608Example output for a 4 GiB swap file:
4194304+0 records in4194304+0 records out4294967296 bytes (4.3 GB, 4.0 GiB) copied, 8.81315 s, 487 MB/sUnderstanding the dd Command:
Section titled “Understanding the dd Command:”sudo: Runs the command with administrative privilegesdd: A low-level command to copy and convert dataif=/dev/zero: Uses/dev/zeroas input, which provides unlimited zero bytesof=/swapfile: Sets the output file to/swapfilebs=1024: Sets the block size to 1024 bytes (1 KB)count=4194304: Specifies the number of blocks to write (4194304 blocks × 1024 bytes = 4 GiB)
6.2.5. Setting Up the Swap File
Section titled “6.2.5. Setting Up the Swap File”After creating the swap file, configure it for use:
# Navigate to root directorycd /
# Set the correct permissions for the swap file (prevents other users from reading it)sudo chmod 600 /swapfile
# Set up the file as a Linux swap areasudo mkswap /swapfile
# Activate the new swap filesudo swapon /swapfile
# Verify swap statussudo swapon -s
# Make swap permanent after reboot by editing fstabsudo vim /etc/fstab
# Add this line to the fstab file:/swapfile swap swap defaults 0 06.2.6. Optimizing Swap Settings
Section titled “6.2.6. Optimizing Swap Settings”To improve system performance, you can adjust how aggressively the system uses swap:
# Check current swappiness and cache pressure settingssudo sysctl -a | grep -e vm.swappiness -e vm.vfs_cache_pressure
# Navigate to sysctl.d directorycd /etc/sysctl.d/
# Create or edit custom_overrides.confsudo vim custom_overrides.confAdd the following configuration:
# SWAP Customizationvm.swappiness = 1vm.vfs_cache_pressure = 50These settings:
vm.swappiness = 1: Minimizes swap usage by prioritizing RAM, using swap only as a last resortvm.vfs_cache_pressure = 50: Balances memory use by keeping cached file metadata longer, improving file access speed
Apply the changes:
# Reboot to apply changessudo reboot
# After reboot, verify the settingssudo sysctl -a | grep -e vm.swappiness -e vm.vfs_cache_pressureExpected output:
vm.swappiness = 1vm.vfs_cache_pressure = 506.3. Hardening Shared Memory
Section titled “6.3. Hardening Shared Memory”Shared memory (/dev/shm) is a temporary filesystem used for inter-process communication. By default, it may have security vulnerabilities that could be exploited by attackers.
6.3.1. Checking Current Shared Memory Settings
Section titled “6.3.1. Checking Current Shared Memory Settings”First, check the current configuration of your shared memory:
# Confirm current settingsmount | grep shm
# Example output:# tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,inode64)6.3.2. Hardening Shared Memory Configuration
Section titled “6.3.2. Hardening Shared Memory Configuration”To secure shared memory, you need to modify the /etc/fstab file:
# Back up the fstab file before making changescd /etcsudo cp fstab fstab.bak
# Edit the fstab filesudo vim /etc/fstabAdd the following line to the end of the file:
# HARDEN SHARED MEMORYnone /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0This configuration:
noexec: Prevents execution of binaries in the shared memory areanosuid: Blocks privilege escalation viasetuid/setgidbitsnodev: Disallows creation of device files in shared memory
6.3.3. Verifying the Configuration
Section titled “6.3.3. Verifying the Configuration”After saving the changes, you can either reboot or remount the shared memory to apply the changes:
# Remount /dev/shm with the new settingssudo mount -o remount /dev/shm
# Verify the new settingsmount | grep /dev/shmExpected output:
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,inode64)The presence of noexec, nosuid, and nodev in the output confirms that the hardening has been successfully applied.
6.4. Disabling IPv6
Section titled “6.4. Disabling IPv6”IPv6 is the next-generation Internet Protocol, but if you’re not using it, disabling IPv6 can reduce your server’s attack surface and simplify your network configuration.
6.4.1. Method 1: Disabling IPv6 via GRUB
Section titled “6.4.1. Method 1: Disabling IPv6 via GRUB”For systems using GRUB bootloader, you can disable IPv6 at the kernel level:
# Open the GRUB configuration filesudo nano /etc/default/grubModify the GRUB_CMDLINE_LINUX line to include the IPv6 disable parameter:
GRUB_CMDLINE_LINUX="ipv6.disable=1"If the line already contains other parameters, add the IPv6 parameter with a space separator:
GRUB_CMDLINE_LINUX="existing_parameters ipv6.disable=1"Update GRUB and reboot to apply the changes:
# Update GRUB configurationsudo update-grub
# Reboot the systemsudo reboot6.4.2. Method 2: Disabling IPv6 Using Sysctl
Section titled “6.4.2. Method 2: Disabling IPv6 Using Sysctl”Alternatively, you can disable IPv6 using the sysctl configuration:
# Edit the sysctl configuration filesudo vim /etc/sysctl.d/99-sysctl.confAdd the following lines to disable IPv6:
# Disable IPv6net.ipv6.conf.all.disable_ipv6 = 1net.ipv6.conf.default.disable_ipv6 = 1Apply the changes without rebooting:
# Reload sysctl configurationsudo sysctl -p6.4.3. Verifying IPv6 is Disabled
Section titled “6.4.3. Verifying IPv6 is Disabled”To confirm that IPv6 has been successfully disabled:
# Check for any IPv6 addressesip a | grep inet6If no output is displayed, IPv6 is successfully disabled. If you still see IPv6 addresses, you may need to reboot the system or check your configuration.
6.5. Hardening and Optimizing the Network Layer
Section titled “6.5. Hardening and Optimizing the Network Layer”Optimizing your network configuration can improve both security and performance. The following settings help protect against common network attacks and optimize network performance.
6.5.1. Network Security and Performance Settings
Section titled “6.5.1. Network Security and Performance Settings”Navigate to the sysctl configuration directory:
# Go to sysctl configuration directorycd /etc/sysctl.d/
# Create or edit the custom overrides filesudo vim custom_overrides.confAdd the following network hardening directives:
# IP Spoofing Protectionnet.ipv4.conf.default.rp_filter = 1net.ipv4.conf.all.rp_filter = 1
# SYN Flood Protectionnet.ipv4.tcp_syncookies = 1net.ipv4.tcp_max_syn_backlog = 2048net.ipv4.tcp_synack_retries = 2net.ipv4.tcp_syn_retries = 5
# Source Packet Routingnet.ipv4.conf.all.accept_source_route = 0net.ipv6.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0net.ipv6.conf.default.accept_source_route = 0
# Increase the Number of Usable Portsnet.ipv4.ip_local_port_range = 1024 65535
# Increase File Handles & Restrict Core Dumpsfs.file-max = 2097152fs.suid_dumpable = 0
# Number of Incoming Connections/Backlognet.core.somaxconn = 65535net.core.netdev_max_backlog = 262144
# Increase Maximum Memory Buffersnet.core.optmem_max = 25165824
# Send/Receive Buffer Sizesnet.core.rmem_default = 31457280net.core.rmem_max = 67108864net.core.wmem_default = 31457280net.core.wmem_max = 671088646.5.2. Understanding the Network Hardening Settings
Section titled “6.5.2. Understanding the Network Hardening Settings”These settings enhance your server’s security and performance:
-
IP Spoofing Protection:
rp_filter = 1enables source validation of packets, preventing IP spoofing attacks where attackers forge the source address.
-
SYN Flood Protection:
tcp_syncookies = 1protects against SYN flood attacks by validating connection requests without using connection queue entries.tcp_max_syn_backlog = 2048increases the SYN backlog queue to handle more connection requests.tcp_synack_retries = 2andtcp_syn_retries = 5optimize TCP connection establishment.
-
Source Packet Routing:
- Disabling
accept_source_routeprevents attackers from specifying the route that packets take through the network.
- Disabling
-
Usable Ports:
ip_local_port_range = 1024 65535increases the range of available local ports for outgoing connections.
-
File Handles & Core Dumps:
fs.file-max = 2097152increases the maximum number of file handles.fs.suid_dumpable = 0prevents setuid programs from dumping core, which could expose sensitive information.
-
Connection Handling:
somaxconn = 65535increases the maximum number of pending connections.netdev_max_backlog = 262144increases the maximum length of the processor input queue.
-
Memory Buffers and Socket Buffers:
- The
optmem_max,rmem_*, andwmem_*settings optimize memory allocation for network operations.
- The
6.5.3. Applying and Verifying the Settings
Section titled “6.5.3. Applying and Verifying the Settings”Apply the changes by rebooting the system:
# Reboot to apply all changessudo rebootAfter rebooting, verify that the settings have been applied:
# Check a specific setting (example)sudo sysctl -a | grep net.core.optmem_max
# Expected output:# net.core.optmem_max = 25165824You can check other settings similarly by replacing net.core.optmem_max with the specific parameter you want to verify.
6.6. Optimizing TCP Congestion Control
Section titled “6.6. Optimizing TCP Congestion Control”TCP congestion control algorithms manage network traffic to prevent congestion collapse. Google’s BBR (Bottleneck Bandwidth and RTT) algorithm can significantly improve network performance compared to traditional algorithms.
6.6.1. Checking Current Congestion Control Settings
Section titled “6.6.1. Checking Current Congestion Control Settings”First, check which congestion control algorithms are available and which one is currently active:
# Check available congestion control algorithmssudo sysctl net.ipv4.tcp_available_congestion_control
# Check the currently active algorithmsudo sysctl net.ipv4.tcp_congestion_control6.6.2. Activating the BBR Algorithm
Section titled “6.6.2. Activating the BBR Algorithm”To enable the BBR congestion control algorithm:
# Load the BBR modulesudo modprobe tcp_bbr
# Ensure BBR loads at boot timesudo bash -c 'echo "tcp_bbr" > /etc/modules-load.d/bbr.conf'
# Verify BBR is now availablesudo sysctl net.ipv4.tcp_available_congestion_control6.6.3. Setting BBR as the Default Algorithm
Section titled “6.6.3. Setting BBR as the Default Algorithm”Edit the custom overrides configuration file:
# Edit the sysctl configuration filesudo vim /etc/sysctl.d/custom_overrides.confAdd the following lines to set BBR as the default congestion control algorithm:
# Activate BBR Algorithmnet.ipv4.tcp_congestion_control = bbrnet.core.default_qdisc = fqThe fq (Fair Queuing) packet scheduler works well with BBR to reduce bufferbloat and improve latency.
6.6.4. Verifying the Configuration
Section titled “6.6.4. Verifying the Configuration”After saving the changes, you can apply them immediately and verify:
# Apply the changessudo sysctl -p /etc/sysctl.d/custom_overrides.conf
# Confirm BBR is now the active algorithmsudo sysctl net.ipv4.tcp_congestion_controlExpected output:
net.ipv4.tcp_congestion_control = bbr6.7. Optimizing File Access Times
Section titled “6.7. Optimizing File Access Times”By default, Linux updates the access time (atime) of a file every time it is read, which can cause unnecessary disk I/O operations. Disabling this feature can improve performance, especially for busy servers.
6.7.1. Checking Current Mount Options
Section titled “6.7.1. Checking Current Mount Options”First, check your current filesystem mount options:
# View mounted filesystems with human-readable sizesdf -h
# View detailed mount optionscat /proc/mountsExample output from /proc/mounts:
/dev/vda1 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0or
/dev/sda1 / ext4 rw,relatime,discard,errors=remount-ro,commit=30 0 0Note that most systems use relatime by default, which is a compromise that only updates access times if they’re older than the modify time. While better than the default atime, using noatime provides even better performance.
6.7.2. Modifying the File System Table (fstab)
Section titled “6.7.2. Modifying the File System Table (fstab)”To disable access time updates permanently, edit the /etc/fstab file:
# Edit the filesystem tablesudo vim /etc/fstabFind the line for your root filesystem (/) and add the noatime option:
Before (example):
UUID=8ce122bd-f39c-45ae-b129-9650cfc67567 / ext4 errors=remount-ro 0 1After (example):
UUID=8ce122bd-f39c-45ae-b129-9650cfc67567 / ext4 errors=remount-ro,noatime 0 1If your fstab uses a different format, ensure you add noatime to the mount options:
/dev/sda1 / ext4 rw,noatime,discard,errors=remount-ro,commit=30 0 06.7.3. Applying and Verifying the Changes
Section titled “6.7.3. Applying and Verifying the Changes”You can either reboot your system or remount the filesystem to apply the changes:
# Remount the root filesystem with the new optionssudo mount -o remount /
# Verify the changescat /proc/mountsExpected output (note the noatime option is now present):
/dev/vda1 / ext4 rw,noatime,errors=remount-ro,data=ordered 0 0This confirms that the filesystem is now mounted with the noatime option, which will improve disk I/O performance.
6.8. Increasing Open File Limits
Section titled “6.8. Increasing Open File Limits”Linux systems have limits on the number of files a process can open simultaneously. For busy servers, especially those running databases or web servers, the default limits may be too restrictive.
6.8.1. Checking Current File Limits
Section titled “6.8.1. Checking Current File Limits”First, check your current open file limits:
# Check hard limit (maximum allowed)ulimit -Hn
# Check soft limit (current setting)ulimit -SnDefault values are typically 1024 for soft limits and 4096 for hard limits, which can be insufficient for busy servers.
6.8.2. Increasing File Limits System-Wide
Section titled “6.8.2. Increasing File Limits System-Wide”To increase the limits for all users, create a configuration file in the limits.d directory:
# Navigate to the limits.d directorycd /etc/security/limits.d/
# Create or edit the custom overrides filesudo vim custom_overrides.confAdd the following configuration to increase the limits:
# <domain> <type> <item> <value>* soft nofile 120000* hard nofile 120000root soft nofile 120000root hard nofile 120000This configuration:
- Sets both soft and hard limits to 120,000 open files
- Applies to all users (
*) and specifically to the root user - The value 120,000 is sufficient for most server workloads, but can be increased if needed
6.8.3. Enabling PAM Limits
Section titled “6.8.3. Enabling PAM Limits”For the limits to take effect, you need to ensure that the PAM (Pluggable Authentication Modules) system is configured to apply them. Edit the PAM session configuration files:
# Add pam_limits.so to common-sessionsudo bash -c 'echo "session required pam_limits.so" >> /etc/pam.d/common-session'
# Add pam_limits.so to common-session-noninteractivesudo bash -c 'echo "session required pam_limits.so" >> /etc/pam.d/common-session-noninteractive'Alternatively, you can edit these files directly:
# Edit common-sessionsudo vim /etc/pam.d/common-session
# Edit common-session-noninteractivesudo vim /etc/pam.d/common-session-noninteractiveAdd the following line to each file if it’s not already present:
session required pam_limits.so6.8.4. Verifying the Changes
Section titled “6.8.4. Verifying the Changes”After making these changes, you’ll need to log out and log back in for them to take effect. Then verify the new limits:
# Check the new hard limitulimit -Hn
# Check the new soft limitulimit -SnThe output should show the new limits (120000) that you configured.