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
- CIS Benchmarks for Linux
- Linux Kernel Documentation
- NSA Linux Hardening Guide
- OpenSCAP Security Guides
- Linux Hardening Guide - Arch Wiki
Comments