Skip to main content
⚡ Calmops

Linux Security Hardening: A Comprehensive Guide

Introduction

Linux powers critical infrastructure across the globe, from web servers to cloud platforms to embedded systems. While Linux’s open-source nature promotes security through transparency, default installations include numerous services and configurations optimized for usability rather than security. This creates a responsibility for system administrators to implement security hardening measures that protect against modern threats.

Security hardening involves systematically reducing a system’s attack surface by disabling unnecessary services, configuring secure defaults, implementing access controls, and continuously monitoring for vulnerabilities. This comprehensive guide covers practical Linux security hardening techniques applicable to production systems in 2026, from kernel parameter tuning to network protection mechanisms.

The goal isn’t absolute security - which is impossible - but rather raising the bar for attackers, limiting blast radius if compromise occurs, and detecting suspicious activity before it escalates. These measures work together in a defense-in-depth strategy that assumes breach and minimizes impact.

Kernel Parameter Hardening with sysctl

The Linux kernel provides numerous tunable parameters that control network behavior, memory management, and security features. The sysctl command modifies these parameters, with settings typically stored in /etc/sysctl.conf or /etc/sysctl.d/ for persistence across reboots.

Network Hardening Parameters

Network-related sysctl settings form the first line of defense against network-based attacks:

# Disable IP forwarding - prevent acting as router
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Disable packet source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Disable ICMP redirect acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Disable send redirects
net.ipv4.conf.all.send_redirects = 0

# Enable TCP SYN cookies for SYN flood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2

# Ignore ICMP ping requests
net.ipv4.icmp_echo_ignore_all = 1

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Disable IPv6 if not needed
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

These settings protect against common network attacks including IP spoofing, man-in-the-middle attacks, and denial of service attempts. Always test network settings in a staging environment before production deployment to ensure legitimate traffic isn’t blocked.

Memory Protection Parameters

Kernel memory protections prevent exploitation techniques that attackers use to escalate privileges or escape containers:

# Enable address space layout randomization (ASLR)
kernel.randomize_va_space = 2

# Disable kernel debug symbolic links
kernel.dmesg_restrict = 1

# Restrict access to /proc/<pid> directories
fs.proc_can_see_other_uid = 1

# Disable core dumps (may contain sensitive data)
kernel.core_uses_pid = 1
kernel.core_pattern = |/usr/bin/core_pattern_helper %e %p %t

# Protect hardlinks and symlinks
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

The ASLR setting randomizes memory addresses, making exploitation significantly harder. The hardlink and symlink protections prevent attackers from exploiting world-writable directories to gain access to sensitive files.

User Namespace Restrictions

User namespaces, while useful for containerization, can provide escape vectors if misconfigured:

# Restrict user namespace creation (requires careful consideration for containers)
kernel.unprivileged_userns_clone = 0

# Restrict BPF JIT compilation (can be used for kernel exploits)
net.core.bpf_jit_enable = 0

Applying these restrictions requires balancing security with functionality - containers typically need user namespace access. Evaluate your specific requirements before enabling these options.

Applying sysctl Changes

Apply changes temporarily or persistently:

# Apply changes immediately (test before persistence)
sudo sysctl -p /etc/sysctl.conf

# Apply specific file
sudo sysctl -p /etc/sysctl.d/99-security.conf

# Check current values
sysctl net.ipv4.tcp_syncookies
sysctl -a | grep net.ipv4.conf

For persistent changes, create a dedicated configuration file in /etc/sysctl.d/ with a high number prefix to ensure it loads after other configurations.

Service Hardening

Disabling Unnecessary Services

Every running service represents potential attack surface. Audit and disable unnecessary services:

# List all enabled services
systemctl list-unit-files --state=enabled

# Check for listening ports - suspicious services
sudo ss -tulpn
sudo netstat -tulpn

# Disable unnecessary services (example)
sudo systemctl disable --now bluetooth.service
sudo systemctl disable --now cups.service
sudo systemctl disable --now avahi-daemon.service
sudo systemctl mask avahi-daemon.service

# Disable on boot but keep current running
sudo systemctl disable nginx.service

Common services to review:

  • bluetooth: Often unnecessary on servers
  • cups: Print services rarely needed on production servers
  • avahi-daemon: Network discovery - disable on isolated systems
  • rpcbind: RPC portmapper - potential vulnerability
  • telnet.socket: Never enable - unencrypted protocol

Service Sandboxing

Modern services can often run with improved isolation:

# Enable systemd sandboxing options in service files
[Service]
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
NoNewPrivileges=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictRealtime=yes
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM

These options provide defense-in-depth:

  • PrivateTmp: Isolates /tmp between services
  • ProtectSystem: Restricts filesystem access
  • ProtectHome: Hides user home directories
  • NoNewPrivileges: Prevents privilege escalation
  • PrivateDevices: Blocks access to physical devices

SSH Hardening

SSH is frequently targeted - secure its configuration:

# /etc/ssh/sshd_config hardening

# Disable root login
PermitRootLogin no

# Disable password authentication (use keys)
PasswordAuthentication no
PermitEmptyPasswords no

# Use strong key exchange
KexAlgorithms curve25519-sha256,ecdh-sha2-nistp256

# Disable unused authentication methods
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no

# Use strong ciphers
Ciphers [email protected],[email protected],[email protected]

# MAC selection
MACs [email protected],[email protected]

# Disable unused features
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PrintMotd no
AcceptEnv LANG LC_*

# Session timeouts
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 60

# Limit access by user/group
AllowUsers deployer [email protected]/24
AllowGroups sshusers

After changes, test SSH access before logging out:

# Test configuration
sudo sshd -t

# Reload configuration
sudo systemctl reload sshd

User and Authentication Security

Password Policies

Implement strong password requirements:

# Install libpam-pwquality
sudo apt install libpam-pwquality

# Configure in /etc/pam.d/common-password
password requisite pam_pwquality.so retry=3 minlen=16 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1

Parameters:

  • minlen=16: Minimum 16 characters
  • difok=3: At least 3 characters different from old password
  • ucredit=-1: At least one uppercase letter
  • lcredit=-1: At least one lowercase letter
  • dcredit=-1: At least one digit
  • ocredit=-1: At least one special character

Account Lockout Policies

Prevent brute force attacks through account locking:

# Configure in /etc/pam.d/common-auth
auth required pam_tally2.so onerr=fail deny=5 unlock_time=1800

This locks accounts after 5 failed attempts for 30 minutes.

Sudo Configuration

Limit sudo access carefully:

# Edit sudoers with visudo
sudo visudo

# Example: specific commands only
deployer ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx, /bin/ls /var/log/nginx/

# Require password for dangerous commands
%admin ALL=(ALL) ALL
%sudo ALL=(ALL) ALL

SSH Key Management

Enforce SSH key security:

# Generate strong keys
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519

# Add passphrase to existing keys
ssh-keygen -p -f ~/.ssh/id_ed25519

# Restrict key permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

File System Security

Mount Options

Secure mount options in /etc/fstab:

# /tmp with noexec, nosuid, nodev
/tmp tmpfs defaults,noexec,nosuid,nodev 0 0

# Separate partitions with secure options
/var    ext4    defaults,nosuid,nodev,noexec  0 2
/var/log ext4   defaults,nosuid,nodev,noexec  0 2
/var/log/audit ext4 defaults,nosuid,nodev,noexec 0 2

These options:

  • noexec: Prevents execution of binaries on partition
  • nosuid: Ignores setuid/setgid bits
  • nodev: Prevents device file creation

File Permissions

Implement the principle of least privilege:

# World-readable files that should be restricted
chmod 600 /etc/shadow
chmod 600 /etc/gshadow
chmod 644 /etc/passwd
chmod 644 /etc/group

# Restrict SSH keys
chmod -R 700 ~/.ssh
chmod 600 ~/.ssh/*

# Audit SUID/SGID files
find / -perm /6000 -type f 2>/dev/null

# Audit world-writable directories
find / -perm -002 -type d 2>/dev/null

Audit System

Enable Linux audit for security monitoring:

# Install auditd
sudo apt install auditd

# Configure rules in /etc/audit/audit.rules
# Monitor sensitive files
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/ssh/sshd_config -p wa -k ssh
-w /usr/bin/ -p x -k exec

# Monitor privilege escalation
-w /usr/bin/sudo -p x -k sudo
-w /usr/bin/su -p x -k su

# Monitor network configuration
-w /etc/iptables/ -p wa -k firewall
-w /etc/sysctl.conf -p wa -k kernel

# Search audit logs
sudo ausearch -k identity
sudo aureport -f

Network Protection

Firewall Basics with iptables/nftables

Configure restrictive firewall rules:

# Basic iptables ruleset
# Flush existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

# Default policies - deny everything
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow loopback
iptables -A INPUT -i lo -j ACCEPT

# Allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow SSH (change port if non-standard)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Allow HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Rate limiting for SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP

Fail2ban Installation

Install Fail2ban for automated attack prevention:

# Install Fail2ban
sudo apt install fail2ban

# Configure in /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
destemail = [email protected]
sender = [email protected]
action = %(action_mwl)s

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400

[nginx-http-auth]
enabled = true

# Enable and start
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Continuous Security Monitoring

Tripwire Installation

Set up file integrity monitoring:

# Install tripwire
sudo apt install tripwire

# Initialize database
sudo tripwire --init

# Check integrity
sudo tripwire --check

# Update database after legitimate changes
sudo twadmin --create-cfgfile -S /etc/tripwire/site.key /etc/twcfg.txt
sudo twadmin --create-polfile -S /etc/tripwire/site.key /etc/twpol.txt
sudo tripwire --init

Rootkit Detection

Install rkhunter and chkrootkit:

# Install and run rkhunter
sudo apt install rkhunter
sudo rkhunter --update
sudo rkhunter --check --sk

# Install and run chkrootkit
sudo apt install chkrootkit
sudo chkrootkit

Log Monitoring

Centralize and monitor logs:

# Configure rsyslog for remote logging
# /etc/rsyslog.conf
*.* @@logserver.example.com:514

# Set up logwatch for daily summaries
sudo apt install logwatch
sudo cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/

Automation with Ansible

Hardening becomes scalable with automation:

# ansible-playbook hardening.yml
---
- name: Linux Security Hardening
  hosts: all
  become: yes
  vars:
    ssh_port: 22
    admin_users:
      - admin
      - deployer
    
  tasks:
    - name: Apply sysctl hardening
      sysctl:
        name: "{{ item.name }}"
        value: "{{ item.value }}"
        state: present
        reload: yes
        sysctl_file: /etc/sysctl.d/99-security.conf
      loop:
        - { name: 'net.ipv4.tcp_syncookies', value: '1' }
        - { name: 'kernel.randomize_va_space', value: '2' }
        - { name: 'fs.protected_hardlinks', value: '1' }
        - { name: 'fs.protected_symlinks', value: '1' }
    
    - name: Disable unnecessary services
      systemd:
        name: "{{ item }}"
        state: stopped
        enabled: no
      loop:
        - bluetooth
        - cups
        - avahi-daemon
    
    - name: Configure SSH hardening
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      loop:
        - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
        - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' }

Best Practices Summary

Immediate Actions

  • Disable unused services and ports
  • Implement strong password policies
  • Configure firewall rules (default deny)
  • Enable SSH key authentication
  • Apply sysctl kernel hardening
  • Set up automated security monitoring

Regular Maintenance

  • Patch systems promptly
  • Review and update firewall rules
  • Audit user accounts and permissions
  • Monitor security logs
  • Test backups and disaster recovery
  • Review service configurations

Continuous Improvement

  • Implement defense-in-depth
  • Automate hardening with Ansible
  • Conduct security audits
  • Monitor CVE announcements
  • Train on security best practices
  • Document security configurations

Conclusion

Linux security hardening is not a one-time activity but an ongoing process of assessment, implementation, and monitoring. The techniques covered in this guide provide a solid foundation for securing production Linux systems against common threats. Start with the changes that have the lowest impact and highest security benefit, then progressively implement more comprehensive hardening measures.

Remember that security hardening must balance protection with functionality - overly restrictive configurations can impede legitimate operations. Test all changes in development environments before production deployment, maintain documentation of all modifications, and establish procedures for responding to security events. With systematic application of these practices, you significantly reduce your systems’ vulnerability to attack.

Resources

Comments