A practical, step-by-step guide covering SSH hardening, firewalls, updates, WAF, malware scanning, monitoring, and auditing. Every step includes real commands you can copy and run.
Every Linux server connected to the internet is under attack. This is not hypothetical — it is measurable. Botnets continuously scan the entire IPv4 address space, probing for open SSH ports, exposed databases, unpatched web applications, and default credentials.
The majority of these attacks are fully automated. Bots do not care about your website traffic, your company size, or your content. They probe every IP looking for low-hanging fruit: default passwords, known CVEs, and misconfigured services. A fresh VPS on DigitalOcean or any other provider will already have SSH brute force attempts in its auth log within minutes.
The good news: most attacks are preventable with a few hours of hardening. This guide walks through every step, from SSH lockdown to continuous monitoring. Each step includes the exact commands for Ubuntu/Debian and RHEL/Rocky/AlmaLinux. For a condensed version, see the VPS security checklist.
SSH is the most attacked service on any Linux server. Brute force bots try thousands of username/password combinations per hour. The first step is to reduce your SSH attack surface to near zero.
Root is the most commonly targeted username. Disabling direct root login forces attackers to guess both a username and a password.
PermitRootLogin no
SSH keys are cryptographically stronger than any password. Once you have your SSH key set up, disable password authentication entirely.
PasswordAuthentication no
PubkeyAuthentication yes
Changing the SSH port from 22 to a non-standard port reduces noise from automated scanners. It is not a security measure — a targeted attacker will find your SSH port in seconds. But it does reduce log noise by 90%+, making it easier to spot real threats. If you use it, pick a port above 1024:
Port 2222
# Restart SSH to apply changes
$ sudo systemctl restart sshd
# Rate limit SSH with iptables (manual approach)
$ sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name SSH
$ sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
The iptables rules above limit new SSH connections to 3 per minute per IP. For more comprehensive protection, install a dedicated tool:
$ sudo apt install fail2ban -y
$ sudo systemctl enable fail2ban
$ curl -fsSL https://defensia.cloud/install.sh | sudo bash
Defensia detects 15 SSH attack patterns including failed passwords, invalid users, pre-auth disconnects, PAM failures, and kex negotiation drops. See all SSH detection patterns →
A firewall controls which ports accept connections. The principle is simple: deny everything by default, then allow only the ports you need.
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow 22/tcp # SSH
$ sudo ufw allow 80/tcp # HTTP
$ sudo ufw allow 443/tcp # HTTPS
$ sudo ufw enable
$ sudo ufw status verbose
$ sudo systemctl enable --now firewalld
$ sudo firewall-cmd --permanent --add-service=ssh
$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --permanent --set-default-zone=drop
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
$ sudo iptables -P INPUT DROP
$ sudo iptables -P FORWARD DROP
$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Defensia note: Defensia manages its own iptables/ipset rules for dynamic IP blocking. It never modifies your existing firewall rules (UFW, firewalld, or manual iptables). They work at different layers and complement each other.
Unpatched software is one of the top attack vectors. When a CVE is published, exploit code often follows within hours. Automated scanners then sweep the internet for vulnerable versions. The window between disclosure and exploitation is shrinking — in 2025 it averaged under 5 days for critical CVEs.
$ sudo apt update
$ sudo apt upgrade -y
$ sudo dnf update -y
$ sudo apt install unattended-upgrades -y
$ sudo dpkg-reconfigure -plow \
unattended-upgrades
$ sudo dnf install dnf-automatic -y
$ sudo systemctl enable --now \
dnf-automatic-install.timer
Defensia note: Defensia's CVE scanner reads your installed packages and matches them against the NVD (National Vulnerability Database) daily. Each CVE is scored with EPSS (exploit probability) and flagged if it appears in the CISA Known Exploited Vulnerabilities catalog. You get alerted before an attacker finds the vulnerability.
If you run nginx or Apache, your web server is the second-most attacked surface after SSH. Hardening it involves two layers: configuration hardening and a web application firewall.
Add these headers to protect against common browser-based attacks:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
server_tokens off;
ServerTokens Prod
ServerSignature Off
A WAF detects and blocks application-level attacks: SQL injection, XSS, path traversal, remote code execution, and more. There are two main approaches:
Industry standard, but requires compiling modules, maintaining YAML config files, tuning hundreds of rules to avoid false positives, and restarting your web server for every change. Typical setup time: 4-8 hours.
Reads nginx/Apache access logs and detects 15+ OWASP attack types automatically. No inline proxy, no module compilation, no rule files. The WAF runs as a separate Go process — zero impact on web server performance. Learn more →
Even with SSH hardening and a firewall, web application vulnerabilities can lead to uploaded web shells, cryptominers, and backdoors. Regular malware scanning catches what preventive measures miss.
$ sudo apt install clamav clamav-daemon -y
$ sudo freshclam # Update signatures
$ sudo clamscan -r /var/www --infected # Scan web directories
ClamAV is effective for known malware but slow on large directories and does not detect obfuscated PHP web shells or encoded backdoors well.
$ sudo apt install rkhunter chkrootkit -y
$ sudo rkhunter --update
$ sudo rkhunter --check --skip-keypress
$ sudo chkrootkit
These tools check for known rootkit files, hidden processes, and modified system binaries. Run them weekly via cron.
Defensia combines all three approaches into a single scanner: 64,000+ hash signatures, 684 dynamic detection patterns (obfuscated PHP, encoded backdoors, suspicious eval chains), rootkit checks (ld.so.preload, hidden processes, /tmp executables), credential scanning (.env exposure, .git directories, world-readable SSH keys), and WordPress database scanning (malicious posts, rogue admin accounts).
Scans run on schedule and results appear in the dashboard with one-click quarantine. No separate tools to install, no cron jobs to configure.
Prevention is only half the equation. You need visibility into what is happening on your server right now. Without monitoring, you will not know about attacks until the damage is done.
| Log file | Purpose |
|---|---|
| /var/log/auth.log | SSH login attempts, sudo usage (Ubuntu/Debian) |
| /var/log/secure | SSH login attempts (RHEL/CentOS) |
| /var/log/nginx/access.log | Web requests, attack patterns |
| /var/log/apache2/access.log | Web requests (Apache) |
| /var/log/syslog | System events, kernel messages |
| /var/log/mail.log | Postfix/Dovecot authentication events |
| /var/log/fail2ban.log | Ban events (if fail2ban installed) |
Sends daily email summaries of log activity. Good for small servers but not real-time.
Real-time web log analyzer with terminal and HTML output. Great for traffic analysis, but not security-focused.
Host-based intrusion detection system with log analysis and file integrity monitoring. Powerful but complex to configure.
Real-time web dashboard showing every attack, ban, and security event across all your servers. Live charts, event feed, ban timeline, geographic distribution, and Slack/email/Discord alerts. All logs in one place, no terminal required.
Databases are high-value targets. An exposed MySQL or PostgreSQL instance can be discovered, brute-forced, and dumped in minutes. The fix is simple: never expose database ports to the internet.
bind-address = 127.0.0.1
listen_addresses = 'localhost'
mysql> DROP USER IF EXISTS ''@'localhost';
mysql> DROP DATABASE IF EXISTS test;
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'strong_password_here';
mysql> FLUSH PRIVILEGES;
# Make sure these ports are NOT open in your firewall:
# 3306 (MySQL), 5432 (PostgreSQL), 27017 (MongoDB), 6379 (Redis)
$ sudo ufw deny 3306
$ sudo ufw deny 5432
$ sudo ufw deny 27017
$ sudo ufw deny 6379
If you need remote database access, use SSH tunnels instead of exposing ports. Full database security guide →
Security is not a one-time task. Run audits regularly to catch configuration drift, new vulnerabilities, and misconfigurations that accumulate over time.
$ sudo apt install lynis -y
$ sudo lynis audit system
Lynis scans your system configuration and outputs a hardening index from 0-100 with specific recommendations. Run it monthly.
$ sudo apt install libopenscap8 -y # Ubuntu/Debian
$ sudo dnf install openscap-scanner -y # RHEL/Rocky
$ sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml
OpenSCAP checks your system against CIS benchmarks and produces compliance reports. Ideal for regulated environments.
Defensia alternative: Defensia's security posture score (0-100, A-F grade) continuously checks SSH configuration, firewall state, file permissions, credential exposure, and system integrity. No manual scans needed — the score updates automatically and shows up in your dashboard.
The 8 steps above take 2-4 hours to implement manually, and they require ongoing maintenance: updating rules, reviewing logs, running scans, and checking for new CVEs. If you manage multiple servers, multiply that time accordingly.
Defensia automates steps 1, 5, 6, 7, and 8 completely, and enhances steps 2, 3, and 4 with automated detection and alerts. One command installs everything:
Quick reference: every hardening step with the manual command and whether Defensia covers it automatically.
| Step | Manual command | Defensia |
|---|---|---|
| Disable root SSH login | PermitRootLogin no | Manual |
| Use SSH keys only | PasswordAuthentication no | Manual |
| Configure firewall (UFW/firewalld) | ufw enable | Manual |
| Update all packages | apt upgrade / dnf update | Manual |
| Enable automatic updates | unattended-upgrades / dnf-automatic | Manual |
| Block SSH brute force | fail2ban / iptables rules | ✓ |
| Add security headers | nginx/Apache config | Manual |
| Hide server version | server_tokens off | Manual |
| Install WAF | ModSecurity + CRS | ✓ |
| Scan for malware | ClamAV + rkhunter + cron | ✓ |
| Monitor logs | Logwatch / OSSEC | ✓ |
| Secure database ports | bind-address = 127.0.0.1 | ✓ |
| Scan for CVE vulnerabilities | Manual apt audit | ✓ |
| Run security audit | Lynis / OpenSCAP | ✓ |
| Set up alerts | Custom scripts | ✓ |
Three things immediately: (1) Update all packages with apt upgrade or dnf update. (2) Disable root SSH login and switch to SSH keys. (3) Enable a firewall (UFW or firewalld) and allow only ports 22, 80, and 443. These three steps eliminate the majority of your attack surface. After that, install intrusion detection (fail2ban or Defensia), set up automatic updates, and configure a WAF if you run a web server.
Linux has strong security fundamentals: user permissions, file system permissions, process isolation, and SELinux/AppArmor mandatory access controls. However, a default installation is not hardened. SSH accepts password login as root, no firewall rules are active, no intrusion detection is running, and services bind to all interfaces. Linux provides the tools for security — you still need to configure them.
Security updates should be applied as soon as possible — ideally automatically via unattended-upgrades (Ubuntu) or dnf-automatic (RHEL). For non-security updates, a weekly or biweekly schedule is reasonable. The median time between CVE disclosure and active exploitation was under 5 days in 2025 for critical vulnerabilities, so delays matter.
If you run a web server (nginx, Apache, or any application on ports 80/443), yes. A firewall blocks ports but cannot inspect HTTP request content. SQL injection, XSS, and path traversal attacks arrive on port 443 — your firewall allows them through. A WAF inspects the request payload and blocks malicious content. Options include ModSecurity (complex), Defensia (zero-config), or cloud WAFs like Cloudflare (DNS change required).
It depends on what you need. For SSH brute force protection: fail2ban (requires jail config) or Defensia free tier (zero config). For malware scanning: ClamAV. For rootkit detection: rkhunter + chkrootkit. For security auditing: Lynis. For a combination of SSH protection, dashboard, and bot detection with zero configuration: Defensia free plan (1 server). No single tool covers everything — which is why tools like Defensia that combine multiple layers are increasingly popular.
Look for: (1) Unexpected CPU spikes, especially during off-hours (cryptominers). (2) Unknown processes in /tmp or /dev/shm. (3) New SSH authorized_keys entries you did not add. (4) Unexpected cron jobs. (5) Outbound connections to unknown IPs (check with ss -tnp or netstat -tnp). (6) Modified system binaries (verify with dpkg -V on Debian or rpm -Va on RHEL). (7) PHP files in upload directories. Defensia checks all of these continuously and surfaces them in a security posture score.
15 essential hardening steps in a scannable checklist.
15 detection patterns, ipset blocking.
OWASP attack detection from server logs.
Full comparison: fail2ban vs Defensia.
Automated protection for all Linux distros.
Ubuntu-specific hardening guide.
Debian-specific hardening guide.
RHEL-family distribution guide.
Protect MySQL, PostgreSQL, MongoDB, Redis.
Docker, Swarm, and Kubernetes native.
Postfix and Dovecot brute force protection.
CrowdSec vs Defensia comparison.
One command. Under 30 seconds. Free for one server.
No credit card required.