Secure your Linux infrastructure with this security guide. Learn essential hardening techniques from my working notes including intrusion detection and defense strategies for: Ubuntu, CentOS, RHEL and Debian servers. This guide covers many facets from basic setup to advanced threat protection.
Linux server security is critical for protecting your infrastructure from cyber threats, data breaches, and unauthorised access. This comprehensive guide covers essential security practices, from basic hardening to advanced threat protection, ensuring your Linux servers remain secure and compliant.
Whether you’re managing Ubuntu, CentOS, RHEL, or Debian servers, these security principles apply across distributions and will help you build a robust foundational defense against modern cyber threats in cloud and Kubernetes workloads.
The first step in securing any Linux server is disabling direct root login via SSH:
# Edit SSH configuration
sudo nano /etc/ssh/sshd_config
# Add or modify these lines
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
# Restart SSH service
sudo systemctl restart sshd
Always use a dedicated administrative user with sudo privileges:
# Create new user
sudo adduser adminuser
# Add to sudo group
sudo usermod -aG sudo adminuser
# Test sudo access
su - adminuser
sudo whoami
SSH key authentication is significantly more secure than password-based login:
# Generate SSH key pair (on client machine)
ssh-keygen -t ed25519 -C "your_email@example.com"
# Copy public key to server
ssh-copy-id adminuser@your-server-ip
# Verify key-based login works
ssh adminuser@your-server-ip
Configure password complexity requirements:
# Install password quality library
sudo apt install libpam-pwquality # Ubuntu/Debian
sudo yum install libpwquality # CentOS/RHEL
# Edit PAM configuration
sudo nano /etc/pam.d/common-password
# Add password complexity rules
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
Prevent brute force attacks with account lockout:
# Edit PAM auth configuration
sudo nano /etc/pam.d/common-auth
# Add account lockout
auth required pam_tally2.so deny=5 unlock_time=900
# Check locked accounts
sudo pam_tally2 --user=username
# Unlock account
sudo pam_tally2 --user=username --reset
Implement 2FA for critical accounts:
# Install Google Authenticator
sudo apt install libpam-google-authenticator
# Configure for user
google-authenticator
# Edit SSH PAM configuration
sudo nano /etc/pam.d/sshd
# Add 2FA requirement
auth required pam_google_authenticator.so
UFW provides an intuitive interface for managing iptables:
# Enable UFW
sudo ufw enable
# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow specific services
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Check status
sudo ufw status verbose
Create more sophisticated firewall rules:
# Rate limiting for SSH
sudo ufw limit ssh
# Allow specific IP ranges
sudo ufw allow from 192.168.1.0/24 to any port 22
# Block specific countries (using ipset)
sudo apt install ipset
sudo ipset create blocklist hash:net
sudo iptables -I INPUT -m set --match-set blocklist src -j DROP
Install and configure fail2ban:
# Install fail2ban
sudo apt install fail2ban
# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Edit configuration
sudo nano /etc/fail2ban/jail.local
# Enable SSH protection
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
# Start service
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Security Tip: Always test firewall rules on a separate connection before applying them to your primary SSH session to avoid locking yourself out.
Implement the principle of least privilege:
# Critical system files
sudo chmod 600 /etc/shadow
sudo chmod 600 /etc/gshadow
sudo chmod 644 /etc/passwd
sudo chmod 644 /etc/group
# SSH configuration
sudo chmod 600 /etc/ssh/ssh_host_*_key
sudo chmod 644 /etc/ssh/ssh_host_*_key.pub
sudo chmod 644 /etc/ssh/sshd_config
Use AIDE (Advanced Intrusion Detection Environment):
# Install AIDE
sudo apt install aide
# Initialise database
sudo aideinit
# Move database
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Run check
sudo aide --check
# Create daily cron job
echo "0 2 * * * root /usr/bin/aide --check" | sudo tee -a /etc/crontab
Fine-grained file permissions:
# Enable ACL on filesystem
sudo mount -o remount,acl /
# Set ACL for specific user
sudo setfacl -m u:username:rw /path/to/file
# Set default ACL for directory
sudo setfacl -d -m u:username:rwx /path/to/directory
# View ACLs
getfacl /path/to/file
Set up rsyslog for centralised log management:
# Edit rsyslog configuration
sudo nano /etc/rsyslog.conf
# Enable remote logging
*.* @@log-server.example.com:514
# Configure log rotation
sudo nano /etc/logrotate.d/rsyslog
/var/log/syslog {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 syslog adm
}
Deploy OSSEC for host-based intrusion detection:
# Download and install OSSEC
wget https://github.com/ossec/ossec-hids/archive/master.zip
unzip master.zip
cd ossec-hids-master
sudo ./install.sh
# Start OSSEC
sudo /var/ossec/bin/ossec-control start
# Configure rules
sudo nano /var/ossec/rules/local_rules.xml
Monitor system resources and performance:
# Install monitoring tools
sudo apt install htop iotop nethogs
# Set up system monitoring with cron
cat << 'EOF' | sudo tee /usr/local/bin/system-monitor.sh
#!/bin/bash
DATE=$(date)
LOAD=$(uptime | awk '{print $10,$11,$12}')
MEMORY=$(free -m | awk 'NR==2{printf "%.2f%%\t", $3*100/$2}')
DISK=$(df -h | awk '$NF=="/"{printf "%s\t", $5}')
echo "$DATE - Load: $LOAD Memory: $MEMORY Disk: $DISK" >> /var/log/system-resources.log
EOF
sudo chmod +x /usr/local/bin/system-monitor.sh
echo "*/5 * * * * root /usr/local/bin/system-monitor.sh" | sudo tee -a /etc/crontab
Automate security updates for Ubuntu/Debian:
# Install unattended-upgrades
sudo apt install unattended-upgrades
# Configure automatic updates
sudo dpkg-reconfigure unattended-upgrades
# Edit configuration
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
# Enable security updates only
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
# Configure email notifications
Unattended-Upgrade::Mail "admin@example.com";
Create scripts to monitor and report security updates:
cat << 'EOF' | sudo tee /usr/local/bin/security-updates.sh
#!/bin/bash
UPDATES=$(apt list --upgradable 2>/dev/null | grep -i security | wc -l)
if [ $UPDATES -gt 0 ]; then
echo "Security updates available: $UPDATES"
apt list --upgradable 2>/dev/null | grep -i security
echo "Run 'sudo apt update && sudo apt upgrade' to install updates"
fi
EOF
sudo chmod +x /usr/local/bin/security-updates.sh
Enable mandatory access controls:
# For Ubuntu (AppArmor)
sudo apt install apparmor-utils
# Check status
sudo aa-status
# Create custom profile
sudo aa-genprof /usr/bin/application
# For CentOS/RHEL (SELinux)
sudo yum install policycoreutils-python-utils
# Check status
sestatus
# Set enforcing mode
sudo setenforce 1
sudo nano /etc/selinux/config
SELINUX=enforcing
Secure Docker containers:
# Install Docker with security considerations
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Configure Docker daemon security
sudo nano /etc/docker/daemon.json
{
"userns-remap": "default",
"no-new-privileges": true,
"seccomp-profile": "/etc/docker/seccomp.json"
}
# Restart Docker
sudo systemctl restart docker
Harden kernel parameters:
# Edit sysctl configuration
sudo nano /etc/sysctl.d/99-security.conf
# Network security
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# Memory protection
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.yama.ptrace_scope = 1
# Apply changes
sudo sysctl -p /etc/sysctl.d/99-security.conf
Warning: Always test kernel parameter changes in a non-production environment first, as incorrect settings can cause system instability.
Perform regular security audits:
# Install security audit tools
sudo apt install lynis chkrootkit rkhunter
# Run Lynis audit
sudo lynis audit system
# Check for rootkits
sudo chkrootkit
sudo rkhunter --check
# Generate compliance reports
sudo lynis audit system --pentest --report-file /tmp/security-audit.report
Regular vulnerability assessments:
# Install OpenVAS
sudo apt install openvas
# Setup OpenVAS
sudo gvm-setup
# Create scan configuration
gvm-cli socket --xml "<create_config><name>Full and fast</name><copy>085569ce-73ed-11df-83c3-002264764cea</copy></create_config>"
# Start vulnerability scan
gvm-cli socket --xml "<create_task><name>Scan localhost</name><config id='config-id'/><target id='target-id'/></create_task>"
Set up automated incident detection:
cat << 'EOF' | sudo tee /usr/local/bin/security-monitor.sh
#!/bin/bash
# Check for suspicious login attempts
FAILED_LOGINS=$(grep "Failed password" /var/log/auth.log | wc -l)
if [ $FAILED_LOGINS -gt 50 ]; then
echo "High number of failed logins detected: $FAILED_LOGINS" | mail -s "Security Alert" admin@example.com
fi
# Check for privilege escalation
SUDO_FAILURES=$(grep "sudo.*FAILED" /var/log/auth.log | wc -l)
if [ $SUDO_FAILURES -gt 10 ]; then
echo "Multiple sudo failures detected: $SUDO_FAILURES" | mail -s "Security Alert" admin@example.com
fi
# Check system integrity
if ! aide --check > /dev/null 2>&1; then
echo "File integrity check failed" | mail -s "Security Alert" admin@example.com
fi
EOF
sudo chmod +x /usr/local/bin/security-monitor.sh
Document incident response procedures:
# Create incident response script
cat << 'EOF' | sudo tee /usr/local/bin/incident-response.sh
#!/bin/bash
echo "Incident Response Activated"
echo "Timestamp: $(date)"
# Isolate affected system
echo "1. Isolating system..."
sudo ufw deny in
sudo ufw deny out
# Preserve evidence
echo "2. Preserving evidence..."
sudo dd if=/dev/sda of=/backup/forensic-image-$(date +%Y%m%d).img bs=4096
# Document system state
echo "3. Documenting system state..."
ps aux > /tmp/processes-$(date +%Y%m%d).log
netstat -tulpn > /tmp/network-$(date +%Y%m%d).log
lsof > /tmp/open-files-$(date +%Y%m%d).log
echo "Initial response complete. Contact security team."
EOF
sudo chmod +x /usr/local/bin/incident-response.sh
Linux server security requires a multi-layered approach combining preventive measures, detection capabilities, and response procedures. Regular security assessments, timely updates, and continuous monitoring are essential for maintaining a secure infrastructure.
Key security principles include:
By implementing these security measures and maintaining them consistently, you’ll significantly reduce your Linux servers’ attack surface and improve your overall security posture.
Remember that security is an ongoing process, not a one-time setup. Regular reviews, updates, and improvements to your security configuration are essential for staying ahead of evolving threats.
Expert Linux and Cloud Security Resources
Visit Chris Binnie - Linux Server and Cloud Security for expert insights and practical guides on cybersecurity, container security, and infrastructure hardening. Also see my AWS Security and Hardening page for all things relating to AWS security best practices. And, for all things K8s security, see my Kubernetes Security Hardening page.
Author of container security and Linux hardening books, with extensive experience in enterprise security implementations.
Linux® is the registered trademark of Linus Torvalds. Use the information from my notes found on these pages at your own risk.
Related Topics: Ubuntu Security, Linux Hardening, Debian Security, SSH Configuration, Firewall Setup, Intrusion Detection, Container Security, DevSecOps, AWS, Amazon Web Services, Cloud Security.