Skip to content

Ubuntu Server Security Hardening Guide

Firewall Configuration

Enable and Configure UFW (Uncomplicated Firewall)

bash
# Install UFW if not installed
sudo apt install ufw

# Reset UFW to default settings
sudo ufw reset

# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow specific services
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https

# Allow specific ports
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Allow from specific IP or subnet
sudo ufw allow from 192.168.1.0/24 to any port 22

# Enable rate limiting for SSH (prevent brute force)
sudo ufw limit ssh

# Enable the firewall
sudo ufw enable

# Check firewall status
sudo ufw status verbose

Advanced iptables Rules

bash
# Basic protection against SYN flood attacks
sudo iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT

# Drop invalid packets
sudo iptables -A INPUT -m state --state INVALID -j DROP

# Drop null packets
sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# Block ping (ICMP)
sudo iptables -A INPUT -p icmp -j DROP

# Save iptables rules
sudo apt install iptables-persistent
sudo netfilter-persistent save

SSH Hardening

Secure SSH Configuration

bash
# Edit SSH configuration
sudo nano /etc/ssh/sshd_config

Make these changes to /etc/ssh/sshd_config:

# Disable root login
PermitRootLogin no

# Use SSH Protocol 2
Protocol 2

# Restrict to SSH key authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no

# Limit user access
AllowUsers user1 user2

# Change default port (optional)
Port 2222

# Disable empty passwords
PermitEmptyPasswords no

# Set idle timeout interval
ClientAliveInterval 300
ClientAliveCountMax 2

# Disable X11 forwarding
X11Forwarding no
bash
# Restart SSH service
sudo systemctl restart ssh

SSH Key-Based Authentication

bash
# Generate SSH key pair on client
ssh-keygen -t ed25519 -a 100

# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# Secure permissions on server
sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/authorized_keys

System Updates and Patch Management

Automated Security Updates

bash
# Install unattended-upgrades package
sudo apt install unattended-upgrades apt-listchanges

# Configure automatic updates
sudo dpkg-reconfigure -plow unattended-upgrades

# Edit configuration
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Add to configuration:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";
    "${distro_id}:${distro_codename}-updates";
};
bash
# Enable automatic updates
sudo nano /etc/apt/apt.conf.d/20auto-upgrades

Add to file:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

Regular System Updates

bash
# Update package list
sudo apt update

# Upgrade packages
sudo apt upgrade -y

# Remove unnecessary packages
sudo apt autoremove -y

DDoS Protection

Install and Configure Fail2ban

bash
# Install Fail2ban
sudo apt install fail2ban

# Create a local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Add or modify in jail.local:

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

[http-get-dos]
enabled = true
port = http,https
filter = http-get-dos
logpath = /var/log/apache2/access.log
maxretry = 300
findtime = 300
bantime = 600
action = iptables[name=HTTP, port=http, protocol=tcp]

Create a custom filter for HTTP DoS:

bash
sudo nano /etc/fail2ban/filter.d/http-get-dos.conf

Add to the file:

[Definition]
failregex = ^<HOST> -.*"(GET|POST).*
ignoreregex =
bash
# Restart Fail2ban
sudo systemctl restart fail2ban

Mitigate SYN Flood Attacks

bash
# Edit sysctl configuration
sudo nano /etc/sysctl.conf

Add these lines:

# TCP SYN flood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

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

# Block SYN attacks
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
bash
# Apply changes
sudo sysctl -p

Install DDoS Deflate

bash
# Clone the repository
cd /usr/local/src/
sudo git clone https://github.com/jgmdev/ddos-deflate.git

# Install
cd ddos-deflate
sudo ./install.sh

# Configure
sudo nano /usr/local/ddos/ddos.conf

Port Security and Service Hardening

Scan for Open Ports

bash
# Scan for open ports
sudo nmap -sT -O localhost

# Find listening services
sudo ss -tulpn

Disable Unnecessary Services

bash
# List all running services
sudo systemctl list-units --type=service --state=running

# Stop and disable unnecessary services
sudo systemctl stop service_name
sudo systemctl disable service_name

Secure Apache

bash
# Install Apache if needed
sudo apt install apache2

# Secure Apache configuration
sudo nano /etc/apache2/conf-available/security.conf

Modify these settings:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
bash
# Enable security configurations
sudo a2enmod headers
sudo a2enmod ssl
sudo systemctl restart apache2

Secure Nginx

bash
# Install Nginx if needed
sudo apt install nginx

# Edit Nginx configuration
sudo nano /etc/nginx/nginx.conf

Add security headers:

http {
    # ...existing settings...
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
    # ...more settings...
}
bash
# Restart Nginx
sudo systemctl restart nginx

System Hardening

Secure Shared Memory

bash
# Edit fstab
sudo nano /etc/fstab

Add:

none     /run/shm     tmpfs     defaults,noexec,nosuid,nodev     0     0

Harden the Network Stack

bash
# Edit sysctl.conf
sudo nano /etc/sysctl.conf

Add:

# IP Forwarding
net.ipv4.ip_forward = 0

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

# Prevent IP spoofing
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

# Ignore ICMP broadcasts
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore bogus ICMP responses
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
bash
# Apply changes
sudo sysctl -p

Enable Process Accounting

bash
# Install process accounting
sudo apt install acct

# Enable it
sudo systemctl enable acct
sudo systemctl start acct

Audit and Intrusion Detection

Install and Configure Auditd

bash
# Install auditd
sudo apt install auditd

# Configure auditd
sudo nano /etc/audit/auditd.conf

Configure audit rules:

bash
sudo nano /etc/audit/rules.d/audit.rules

Add basic security rules:

# Delete all rules
-D

# Buffer Size
-b 8192

# Monitor for changes to users and groups
-w /etc/passwd -p wa -k user-modify
-w /etc/group -p wa -k group-modify
-w /etc/shadow -p wa -k shadow-modify
-w /etc/sudoers -p wa -k sudoers-modify

# Monitor for changes to system configuration
-w /etc/sysctl.conf -p wa -k sysctl-modify

# Monitor sensitive directories
-w /etc/security/ -p wa -k security-modify
-w /etc/ssh/ -p wa -k ssh-modify

# Monitor command execution
-a always,exit -F arch=b64 -S execve -k exec
bash
# Restart auditd
sudo systemctl restart auditd

Install AIDE (Advanced Intrusion Detection Environment)

bash
# Install AIDE
sudo apt install aide

# Initialize AIDE database
sudo aideinit

# Move database to proper location
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Regular checks
sudo aide --check

Enable System Logging

bash
# Install rsyslog if not installed
sudo apt install rsyslog

# Configure rsyslog
sudo nano /etc/rsyslog.conf

# Restart rsyslog
sudo systemctl restart rsyslog

Additional Security Measures

Password Policies

bash
# Install libpam-pwquality
sudo apt install libpam-pwquality

# Edit common-password
sudo nano /etc/pam.d/common-password

Update the pam_pwquality.so line:

password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 reject_username enforce_for_root

Set Account Lockout Policies

bash
# Edit login.defs
sudo nano /etc/login.defs

Add or update:

PASS_MAX_DAYS 90
PASS_MIN_DAYS 7
PASS_WARN_AGE 14

Restrict Access to Cron

bash
# Restrict cron access
sudo touch /etc/cron.allow
sudo chmod 600 /etc/cron.allow
sudo echo "admin_username" > /etc/cron.allow

# Remove cron.deny
sudo rm -f /etc/cron.deny

Disk Encryption

During installation or for new disks:

bash
# Install cryptsetup
sudo apt install cryptsetup

# Create encrypted volume
sudo cryptsetup luksFormat /dev/sdX

# Open the encrypted volume
sudo cryptsetup luksOpen /dev/sdX secure_disk

# Create a filesystem
sudo mkfs.ext4 /dev/mapper/secure_disk

# Mount the filesystem
sudo mount /dev/mapper/secure_disk /mnt/secure

Disable USB Storage (if needed)

bash
# Create a blacklist file
sudo nano /etc/modprobe.d/blacklist-usb.conf

Add:

blacklist usb-storage
bash
# Update initramfs
sudo update-initramfs -u

Security Monitoring

Install and Configure OSSEC HIDS

bash
# Install prerequisites
sudo apt install build-essential libssl-dev

# Download OSSEC
wget https://github.com/ossec/ossec-hids/archive/3.6.0.tar.gz
tar -xzf 3.6.0.tar.gz
cd ossec-hids-3.6.0/

# Install
sudo ./install.sh

# Start OSSEC
sudo /var/ossec/bin/ossec-control start

Security Scanning with Lynis

bash
# Install Lynis
sudo apt install lynis

# Run a system audit
sudo lynis audit system

# Review Lynis report
less /var/log/lynis.log

Regular Security Checks

bash
# Create a security check script
sudo nano /usr/local/bin/security_check.sh

Script content:

bash
#!/bin/bash
# Security check script

echo "=== Security Check Report ==="
date
echo ""

echo "=== Open Ports ==="
netstat -tuln
echo ""

echo "=== Active Services ==="
systemctl list-units --type=service --state=running
echo ""

echo "=== Failed Login Attempts ==="
grep "Failed password" /var/log/auth.log | tail -n 10
echo ""

echo "=== Disk Space ==="
df -h
echo ""

echo "=== Last 10 Installed Packages ==="
grep "install " /var/log/dpkg.log | tail -n 10
bash
# Make script executable
sudo chmod +x /usr/local/bin/security_check.sh

# Add to cron to run weekly
echo "0 0 * * 0 root /usr/local/bin/security_check.sh > /var/log/security_check.log 2>&1" | sudo tee -a /etc/crontab

Regular Maintenance

Create a Security Maintenance Checklist

  1. Update system regularly: sudo apt update && sudo apt upgrade
  2. Check for open ports: sudo netstat -tulpn
  3. Review auth logs: sudo cat /var/log/auth.log | grep Failed
  4. Check running services: sudo systemctl list-units --type=service --state=running
  5. Check user accounts: sudo cat /etc/passwd | grep -v nologin | grep -v false
  6. Check for malware: sudo rkhunter --check
  7. Verify file integrity: sudo aide --check
  8. Review firewall rules: sudo ufw status verbose
  9. Check for unusual processes: ps auxf | less
  10. Backup critical configuration files