Linux Learning · Part 6 of 7

🔐 Linux Security

SSH hardening · SELinux · AppArmor · fail2ban · auditd · Interactive hardening checklist.


Users, sudo & Least Privilege

Create a non-root admin user
$ sudo useradd -m -s /bin/bash saad
$ sudo passwd saad
$ sudo usermod -aG sudo saad      # Debian/Ubuntu
$ sudo usermod -aG wheel saad     # RHEL/Fedora

# Grant only specific commands (not full sudo):
$ sudo visudo
# Add: saad ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx

# Lock / expire an account:
$ sudo usermod -L baduser         # lock
$ sudo chage -E 0 baduser         # expire immediately

# Find accounts with no password set:
$ sudo awk -F: '($2 == "") {print $1}' /etc/shadow

# List all UID 0 accounts (should ONLY be root):
$ awk -F: '($3==0) {print $1}' /etc/passwd

SSH Hardening

Edit /etc/ssh/sshd_config, then run sudo systemctl restart sshd. Keep a second session open before restarting.

/etc/ssh/sshd_config — recommended settings
Port 2222                        # Change from default 22
PermitRootLogin no               # CRITICAL — never SSH as root
PasswordAuthentication no        # Keys only — disable passwords
PubkeyAuthentication yes
AllowUsers saad deploy           # Whitelist specific users only
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
AllowTcpForwarding no            # Disable unless you need tunnels
ClientAliveInterval 300          # Disconnect idle sessions after 5 min
ClientAliveCountMax 2

# Test config before restarting:
$ sudo sshd -t
$ sudo systemctl restart sshd

SELinux (RHEL / Fedora)

SELinux status and modes
$ getenforce                        # Enforcing / Permissive / Disabled
$ sestatus                          # detailed status + policy name

$ sudo setenforce 0                 # Permissive (logs but doesn't block)
$ sudo setenforce 1                 # Back to Enforcing

# Permanent — edit /etc/selinux/config:
SELINUX=enforcing

# View denials:
$ sudo ausearch -m avc -ts recent
$ sudo tail -f /var/log/audit/audit.log | grep denied

# Generate a policy module to allow a denied action:
$ sudo ausearch -m avc -ts recent | audit2allow -M mypolicy
$ sudo semodule -i mypolicy.pp

# Fix file contexts:
$ sudo chcon -R -t httpd_sys_content_t /var/www/mysite/
$ sudo restorecon -Rv /var/www/mysite/

# Allow httpd to make network connections:
$ sudo setsebool -P httpd_can_network_connect 1

AppArmor (Debian / Ubuntu)

AppArmor status and profile management
$ sudo aa-status                   # show all profiles and their modes
$ sudo aa-complain /usr/sbin/nginx  # complain mode (log, don't block)
$ sudo aa-enforce  /usr/sbin/nginx  # enforce mode (block violations)
$ sudo dmesg | grep apparmor        # view denials

# Reload a profile after editing:
$ sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx

# Auto-generate a profile for a program:
$ sudo aa-genprof /usr/bin/myapp    # run app, press S to scan, F to finish

fail2ban — Brute-Force Protection

Install and configure fail2ban
$ sudo apt install fail2ban
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
$ sudo nano /etc/fail2ban/jail.local

# Recommended jail.local settings:
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 192.168.1.0/24   # whitelist

[sshd]
enabled = true
port    = 2222         # match your SSH port

$ sudo systemctl enable --now fail2ban

# Monitor:
$ sudo fail2ban-client status
$ sudo fail2ban-client status sshd
$ sudo fail2ban-client set sshd unbanip 1.2.3.4   # unban an IP
$ sudo tail -f /var/log/fail2ban.log

Auditing & Security Checks

auditd — kernel audit framework
$ sudo apt install auditd && sudo systemctl enable --now auditd

# Watch critical files for changes:
$ sudo auditctl -w /etc/passwd  -p wa -k passwd_changes
$ sudo auditctl -w /etc/sudoers -p wa -k sudoers_changes

# Search audit log:
$ sudo ausearch -k passwd_changes
$ sudo ausearch -m USER_LOGIN -ts today
$ sudo aureport --auth            # authentication report
$ sudo aureport --failed          # all failed events
Quick security check commands
# Find SUID files (potential privilege escalation):
$ find / -perm /4000 -type f 2>/dev/null

# World-writable directories:
$ find / -type d -perm -0002 -not -path "*/proc/*" 2>/dev/null

# Recent failed login attempts:
$ sudo lastb | head -20
$ sudo grep "Failed password" /var/log/auth.log | tail -20

# All listening ports:
$ ss -tulnp

# Unowned files (no valid user):
$ find / -nouser -o -nogroup 2>/dev/null

🛡 Interactive Hardening Checklist

Track your server hardening progress. Click each item to mark it done.

0 / 14 complete

🖥
Sponsored

Need a Linux VPS? Try DigitalOcean

Spin up a locked-down Linux droplet and apply every item on this checklist in a real environment.

Get Started →