The Setup
Deployed SafeLine Community Edition on a $10/month VPS in front of 3 small websites: a WordPress blog, a Node.js SaaS app, and a static portfolio. Let it run for 30 days, blocking nothing — pure observation mode. Here's what showed up.
Day 1-3: The Welcome Party
Within 3 hours of DNS propagation, automated scanners found the server.
| Attack type | Count (Day 1) | Source |
| WordPress path scans | 847 | /wp-admin, /xmlrpc.php, /wp-content/uploads/* |
| SSH brute force probes | 312 | (Not via HTTP — separate, but logged by fail2ban) |
| .env file grabs | 156 | GET /.env targeting Laravel apps |
| PHP unit exploit scans | 89 | /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php |
Lesson: A new server is discovered by scanners within hours, not days. If you deploy a site without a WAF, you're already under attack before you finish configuring it.
Day 4-10: The Pattern Emerges
After the initial flood, attacks settled into patterns:
Peak attack hours: 2-5 AM UTC (when most US/EU admins are asleep)
Top attacking countries (by IP):
- Russia — 23%
- China — 18%
- United States — 14% (mostly compromised VPS)
- Netherlands — 9% (hosting/datacenter IPs)
- Vietnam — 7%
Most targeted pages:
/wp-login.php — 38% of all attacks
/.env — 12%
/admin — 8%
/api/graphql — 5% (even on the WordPress site!)
/vendor/* — 4%
Day 11-20: The Persistent Ones
Some attacks didn't give up. One IP from a Russian VPS range attempted /wp-login.php with different credentials 4,287 times over 11 days — an average of 390 attempts per day. Without rate limiting, that's a brute force that will eventually succeed if your password is in any dictionary.
Three different IPs tried the same Log4j payload against every URL path they scanned. They didn't know the tech stack — they just spray and pray.
Day 21-30: What Changed
After 3 weeks of observation, I enabled blocking mode:
| Attack type | Before (daily avg) | After (daily avg) |
| WordPress scans | 847 | 0 |
| .env grabs | 156 | 0 |
| SQL injection probes | 203 | 0 (blocked at WAF) |
| XSS attempts | 98 | 0 |
| Total blocked | — | ~1,300/day |
1,300 attacks per day, blocked silently. No CPU spent in application code handling them. No log noise from PHP or Node.js. They hit the WAF, get blocked, and the app never sees them.
What the Attackers Never Found
- My Node.js app's real vulnerabilities (they got blocked at the WAF before reaching Express)
- My database credentials (
.env was blocked at the path level)
- Any valid WordPress user (rate limiting stopped the brute force before it made progress)
FAQ
Is a WAF really necessary for a small site?
If you have a domain name and an IP, scanners will find you. The question isn't whether you'll be attacked — it's whether those attacks reach your app or get blocked at the proxy. My small portfolio site saw 300+ attack attempts per day. It had no login, no database, and nothing to steal — but the scanners don't know that.
Do all these attacks actually work?
Most don't, if your software is up to date. But "most" isn't 100%. A WAF catches the 1% that would work, plus the 99% that just add noise. The real value is that your application doesn't have to deal with any of it.
What's the first thing I should block?
Rate limit your login page. Always. Every site has one. Every attacker tries it. One rule stops the #1 attack vector instantly.
Try SafeLine Community Edition — free, self-hosted, and takes 5 minutes to deploy:
bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/manager.sh)" -- --en
Dashboard: https://<your-server-ip>:9443 | Docs
What do you think your server handles every day that you don't see?