Personal Website Security Protection
A while ago, I mentioned that after connecting log monitoring to my website, I discovered that someone was maliciously scanning it every day, resulting in a lot of 404 access records. The access logs not only waste bandwidth but also hinder my troubleshooting. The online world is treacherous; there are always malicious individuals trying to sabotage me.
Previously, I simply deployed fail2ban to prevent SSH brute-force attacks, but unfortunately, I also added log analysis.
Similarly, I can catch more than 10 malicious IPs every day.
1root@tokyo:~# cat /etc/fail2ban/filter.d/caddy-json-scan.conf
2[Definition]
3# Match requests with status=404 and URIs ending in .php, .cgi, .pl, etc.
4# Extract the IP from remote_addr (automatically ignore ports)
5failregex = ^.*"remote_ip":"<HOST>".*"uri":"[^"]*\.(?i:php|cgi|pl|asp)[^"]*".*"status":404.*
6ignoreregex =
This regular expression approach doesn't work for scanning compressed files. For example, many attacks scan .zip/.tar/.gz, etc., HEAD requests, making it tedious to rewrite the matching rules.
Furthermore, fail2ban consumes a lot of memory and has slow hit rate testing, so an alternative solution needs to be found.
I did some research and found that CrowdSec can handle this task. It's an open-source, community-collaboration-based cybersecurity tool used to detect and block malicious activities (such as brute-force attacks, scanning, and web attacks). It identifies suspicious IP addresses in real-time by analyzing log files and can share threat intelligence with users worldwide (with their consent), creating a "collective immunity" defense network. It also handles Caddy log analysis and SSH/FTP brute-force attack defense with ease, making it seem very suitable for personal use.
1. CrowdSec
Installation and usage are very simple:
1curl -s https://install.crowdsec.net | sudo bash
2sudo apt update
3sudo apt list --upgradable
4sudo apt install crowdsec -y
5sudo apt install crowdsec-firewall-bouncer-nftables -y
The crowdsec-firewall-bouncer-nftables is a bouncer (interceptor) provided by CrowdSec. It automatically adds malicious IP addresses detected by CrowdSec to the Linux nftables firewall rules, thereby achieving real-time blocking at the network layer.
During the installation process, CrowdSec automatically identifies which services your system has (such as Postgres, sshd, Nginx, etc.) and automatically loads the corresponding protection modules, which is much more convenient than manually writing regular expressions for fail2ban.
In other words, once a malicious IP is detected, its access request packets are dropped by the system and never reach the Caddy service, significantly reducing malicious scan records. Bouncers can also be implemented at the application level; for example, Caddy has a corresponding interceptor: https://github.com/hslatman/caddy-crowdsec-bouncer. This means interception at the web server level, allowing for more customized operations compared to system-level interception.
I particularly dislike these malicious scans; they're simply dropped at the system level. My hosting provider pays me on time every month; running a website without making money, trying to serve the public, and then getting attackedโnobody's happy about that.
See the output below and feel the evil of this world:
1root@tokyo:~# cscli decisions list
2โญโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโฎ
3โ ID โ Source โ Scope:Value โ Reason โ Action โ Country โ AS โ Events โ expiration โ Alert ID โ
4โโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโค
5โ 300360 โ crowdsec โ Ip:101.47.161.84 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 28 โ 3h53m54s โ 549 โ
6โ 300359 โ crowdsec โ Ip:101.47.162.19 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 27 โ 3h53m22s โ 548 โ
7โ 300358 โ crowdsec โ Ip:221.14.65.92 โ crowdsecurity/http-probing โ ban โ CN โ 4837 CHINA UNICOM China169 Backbone โ 12 โ 3h49m40s โ 546 โ
8โ 300357 โ crowdsec โ Ip:122.192.133.100 โ crowdsecurity/http-bad-user-agent โ ban โ CN โ 4837 CHINA UNICOM China169 Backbone โ 2 โ 3h45m54s โ 545 โ
9โ 300356 โ crowdsec โ Ip:198.98.57.141 โ crowdsecurity/ssh-slow-bf โ ban โ US โ 53667 PONYNET โ 14 โ 3h35m44s โ 543 โ
10โ 285355 โ crowdsec โ Ip:45.78.194.178 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 31 โ 3h3m16s โ 538 โ
11โ 285354 โ crowdsec โ Ip:92.118.39.76 โ crowdsecurity/ssh-slow-bf โ ban โ US โ 47890 Unmanaged Ltd โ 19 โ 3h2m50s โ 537 โ
12โ 285353 โ crowdsec โ Ip:45.78.219.42 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 24 โ 2h53m55s โ 535 โ
13โ 285352 โ crowdsec โ Ip:45.78.229.72 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 16 โ 2h45m33s โ 534 โ
14โ 285351 โ crowdsec โ Ip:173.249.50.59 โ crowdsecurity/ssh-slow-bf โ ban โ FR โ 51167 Contabo GmbH โ 15 โ 2h43m43s โ 533 โ
15โ 285350 โ crowdsec โ Ip:159.89.143.86 โ crowdsecurity/ssh-slow-bf โ ban โ US โ 14061 DIGITALOCEAN-ASN โ 15 โ 2h43m12s โ 532 โ
16โ 285349 โ crowdsec โ Ip:23.236.169.182 โ crowdsecurity/ssh-slow-bf โ ban โ US โ 55286 SERVER-MANIA โ 13 โ 2h40m12s โ 531 โ
17โ 285348 โ crowdsec โ Ip:103.175.206.22 โ crowdsecurity/ssh-slow-bf โ ban โ ID โ 147124 PT Hostingan Awan Indonesia โ 13 โ 2h40m0s โ 530 โ
18โ 285347 โ crowdsec โ Ip:163.61.198.41 โ crowdsecurity/http-probing โ ban โ SG โ 9664 SOUTHEAST ASIA TELECOMSG PTE. LTD. โ 13 โ 2h37m41s โ 529 โ
19โ 285346 โ crowdsec โ Ip:45.78.193.199 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 27 โ 2h34m44s โ 528 โ
20โ 285345 โ crowdsec โ Ip:101.47.163.243 โ crowdsecurity/ssh-slow-bf โ ban โ SG โ 150436 Byteplus Pte. Ltd. โ 21 โ 2h30m40s โ 527 โ
21โ 285344 โ crowdsec โ Ip:162.240.109.153 โ crowdsecurity/ssh-slow-bf โ ban โ US โ 46606 UNIFIEDLAYER-AS-1 โ 14 โ 2h22m55s โ 524 โ
22โ 285343 โ crowdsec โ Ip:181.167.144.229 โ crowdsecurity/ssh-slow-bf โ ban โ AR โ 7303 Telecom Argentina S.A. โ 18 โ 2h22m28s โ 523 โ
23โ 285342 โ crowdsec โ Ip:95.90.13.168 โ crowdsecurity/ssh-slow-bf โ ban โ DE โ 3209 Vodafone GmbH โ 12 โ 2h21m59s โ 522 โ
24โ 285341 โ crowdsec โ Ip:211.106.133.202 โ crowdsecurity/ssh-slow-bf โ ban โ KR โ 4766 Korea Telecom โ 14 โ 2h21m32s โ 521 โ
25โ 285340 โ crowdsec โ Ip:69.63.203.162 โ crowdsecurity/http-probing โ ban โ US โ 3257 GTT Communications Inc. โ 11 โ 2h9m41s โ 519 โ
26โ 285339 โ crowdsec โ Ip:49.86.41.49 โ crowdsecurity/http-bad-user-agent โ ban โ CN โ 146966 China Telecom โ 2 โ 1h54m39s โ 518 โ
27โ 285338 โ crowdsec โ Ip:43.134.66.41 โ crowdsecurity/http-probing โ ban โ SG โ 132203 Tencent Building, Kejizhongyi Avenue โ 11 โ 1h29m46s โ 515 โ
28โ 270337 โ crowdsec โ Ip:20.78.169.245 โ crowdsecurity/http-wordpress-scan โ ban โ JP โ 8075 MICROSOFT-CORP-MSN-AS-BLOCK โ 4 โ 56m13s โ 513 โ
29โ 270334 โ crowdsec โ Ip:152.42.225.101 โ crowdsecurity/http-probing โ ban โ SG โ 14061 DIGITALOCEAN-ASN โ 11 โ 21m40s โ 508 โ
30โฐโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโฏ
CrowdSec has a wealth of small features, which I won't list here. Overall, it's suitable for personal websites and worth recommending.
2. Caddy Integration with Coraza WAF and rate_limit
Larger companies typically have a WAF layer on the outermost layer of their services; rate_limit can prevent CC attacks, API breaches, brute-force attacks, etc., so we should also include it.
1CGO_ENABLED=1 \
2xcaddy build \
3 --with github.com/dunglas/caddy-cbrotli \
4 --with github.com/mholt/caddy-ratelimit \
5 --with github.com/corazawaf/coraza-caddy/v2
I compiled the above non-standard modules on my computer and then uploaded them directly to the server. The server configuration was too low, so it couldn't compile and would affect users. caddy-cbrotli adds br support; the last two are for ratelimit and WAF.
Result Verification:
1โ ~ ./caddy list-modules | tail -n 10
2
3 Standard modules: 127
4
5http.encoders.br
6http.handlers.rate_limit
7http.handlers.waf
8
9 Non-standard modules: 3
10
11 Unknown modules: 0
WAF Configuration Snippet Example:
1# --- 1. Coraza WAF Core Protection ---
2# For static sites, we mainly block abnormal scanning and malicious User-Agent
3coraza_waf {
4 directives `
5 SecRuleEngine On
6 SecRequestBodyAccess On
7 SecDebugLogLevel 0
8
9 # Block common malicious scanners
10 SecRule REQUEST_HEADERS:User-Agent "(sqlmap|grabber|cgiscan|nessus|nikto|dirbuster|pangolin)" \
11 "id:101,phase:1,deny,status:403,msg:'Malicious Scanner Detected'"
12
13 # Prevent attempts to access sensitive file paths
14 SecRule REQUEST_URI "\.(git|env|config|php|asp|aspx|jsp|cgi|exe)$" \
15 "id:102,phase:1,deny,status:404,msg:'Path Traversal Attempt'"
16 `
17}
Test verification is normal, as shown below:
1โ ~ curl -A "sqlmap" https://mephisto.cc
2Error: 403 Forbiddenโ
3โ ~ curl -I https://mephisto.cc/.env
4HTTP/2 404
5alt-svc: h3=":443"; ma=2592000
Rate Limiting Example:
1:80
2
3rate_limit {
4 distributed
5 zone static_example {
6 match {
7 method GET
8 }
9 key static
10 events 100
11 window 1m
12 }
13 zone dynamic_example {
14 key {remote_host}
15 events 2
16 window 5s
17 }
18 log_key
19}
20
21respond "I'm behind the rate limiter!"
I added rate limiting a long time ago because I was really worried about people spamming the API.
Some RSS software not only accesses the RSS source file but also frequently scrapes the full text, which defies common sense. I also dealt with these through UA identification.
3. Summary
This combination of measures can basically defend against some common attacks for personal servers without any additional cost. Small websites operate with integrity and low profile, serving the people. Since there's no profit to be made, it's probably not a target for professional attack groups.
Copyright statement:
- All content that is not sourced is original., please do not reprint without authorization (because the typesetting is often disordered after reprinting, the content is uncontrollable, and cannot be continuously updated, etc.);
- For non-profit purposes, to deduce any content of this blog, please give the relevant webpage address of this site in the form of 'source of original text' or 'reference link' (for the convenience of readers).
See Also:
- Caddy2 Vue History Mode Configuration
- Real-time Analysis of Caddy Logs Using goaccess
- Building Your Own Streaming Music Service
- MangoHud Performance Monitoring
- Solution to the problem of screen recording failure under independent window manager
- How to Smoothly Connect to Bluetooth Devices in Arch Linux
- Manage Configuration Files with Git and Ansible
- Arch Linux SSL VPN Client Configuration
- How to install and use the iNode client under Arch linux
- Raspberry Pi Running Distribution Agent