linux 安全
fail2ban 安装与配置
sudo apt updatesudo apt install fail2ban
基本配置
fail2ban 的主要配置文件位于:
/etc/fail2ban/jail.conf - 主配置文件(不建议直接修改) /etc/fail2ban/jail.local - 用户自定义配置(推荐在此修改)
fail2ban 常用命令
启动/停止/重启服务
sudo systemctl start fail2ban # 启动服务sudo systemctl stop fail2ban # 停止服务sudo systemctl restart fail2ban # 重启服务sudo systemctl enable fail2ban # 设置开机自启
查看服务状态
sudo systemctl status fail2ban
查看 fail2ban-client 的状态,如启用了对哪些服务的保护
sudo fail2ban-client status// 默认情况下只开启了对 ssh 的保护Status|- Number of jail: 1`- Jail list: sshd
查看被封禁的 IP
sudo fail2ban-client status sshd
解封特定 IP
sudo fail2ban-client set sshd unbanip 192.168.1.100
手动封禁 IP
sudo fail2ban-client set sshd banip 192.168.1.100
常见filter及其位置
ls /etc/fail2ban/filter.d
查看日志
tail -f /var/log/fail2ban.log
添加自定义filter,注意filter 的名字不能太长
遇到的一个filter 长度问题
iptables v1.8.7 (nf_tables): chain name `f2b-nginx-botsearch-oneinstack' too long (must be under 29 chars)
如自定义filter 名称为 nginx-404vim /etc/fail2ban/filter.d/nginx-404.conf填入如下,表示匹配 404 的访问[Definition]failregex = ^<HOST> - - \[.*\] "(GET|POST|HEAD) /.* HTTP/\d\.\d" 404ignoreregex =然后编辑, 表示 5分钟内有10次 404 的访问即禁止访问 一个小时vim /etc/fail2ban/jail.local[nginx-404]enabled = truefilter = nginx-404logpath = /data/wwwlogs/*_nginx.logbackend = pollingport = http,httpsmaxretry = 10findtime = 120bantime = 3600然后重启sudo systemctl restart fail2ban查看自定义filter nginx-404 的状态sudo fail2ban-client status nginx-404
针对wordpress 的filter
Block XML-RPC brute force
vim /etc/fail2ban/filter.d/wordpress-xmlrpc.conf[Definition]failregex = ^<HOST> .*"POST\s+/{1,}xmlrpc\.phpvim /etc/fail2ban/jail.local[wordpress-xmlrpc]enabled = truefilter = wordpress-xmlrpclogpath = /data/wwwlogs/*_nginx.logbackend = pollingmaxretry = 3findtime = 300bantime = 3600action = iptables[name=wordpress-xmlrpc, port=http, protocol=tcp]
wordpress-login (Protect /wp-login.php)
vim /etc/fail2ban/filter.d/wordpress-login.conf[Definition]failregex = <HOST> -.*"(GET|POST) \/*wp-login\.phpignoreregex =vim /etc/fail2ban/jail.local[wordpress-login]enabled = truefilter = wordpress-loginlogpath = /data/wwwlogs/*_nginx.logbackend = pollingmaxretry = 5findtime = 600bantime = 3600action = iptables[name=wordpress-login, port=http, protocol=tcp]常见问题:如果设置了具体的 logpath需要设置backend = polling使其生效backend = polling — this disables the systemd journal reading and enables direct file reading
针对频繁请求的filter
Create the filtervim /etc/fail2ban/filter.d/nginx-req-limit.conf[Definition]# Match any GET/POST request from an IPfailregex = ^<HOST> -.*"(GET|POST|HEAD) .* HTTP/1\.[01]" \d+ .*$ignoreregex =# Add the jail invim /etc/fail2ban/jail.local[nginx-req-limit]enabled = trueport = http,httpsfilter = nginx-req-limitlogpath = /data/wwwlogs/*_nginx.logmaxretry = 100findtime = 60bantime = 3600# Escalation: each repeat offense multiplies ban timebantime.increment = truebantime.multiplier = 2bantime.maxtime = 604800
Apply CPU Quota to PHP-FPM
- Find your PHP-FPM service name
systemctl list-units | grep fpm// it will show services like:// php-fpm-83.service
- Create a systemd override file
sudo systemctl edit php-fpm-83.service
- This opens an empty override file in your editor. Add:
[Service]CPUAccounting=trueCPUQuota=160%
CPUAccounting=true enables CPU tracking.
CPUQuota=160% caps PHP-FPM at 1.6 cores worth of CPU.
- Reload systemd and restart PHP-FPM
sudo systemctl daemon-reexecsudo systemctl restart php-fpm-83.service
- Verify Quota is Active
systemd-cgtop
restart services if load or memory usage is too high
vim /usr/local/bin/server-watchdog.sh#!/bin/bash# Simple watchdog for high load or memory usage# Logs to /var/log/watchdog.logLOG_FILE="/var/log/watchdog.log"MAX_LOAD=5 # if load avg > 10 , 1 core:2-3, 2 cores: 4-5, 4 cores: 8-10, 8 cores: 15-20MAX_MEM=85 # if memory usage > 85%, 1–2 GB: 80, 4 GB: 85, 8+ GB: 90SERVICES=("nginx" "mysql" "php-fpm-84" "php-fpm-83" "php-fpm-82")# Ensure log file exists and has correct permissionsif [ ! -f "$LOG_FILE" ]; thentouch "$LOG_FILE"chmod 644 "$LOG_FILE"fiwhile true; doLOAD=$(awk '{print int($1)}' /proc/loadavg)MEM=$(free | awk '/Mem:/ {printf("%.0f", $3/$2 * 100)}')if [ "$LOAD" -gt "$MAX_LOAD" ] || [ "$MEM" -gt "$MAX_MEM" ]; thenecho "$(date '+%Y-%m-%d %H:%M:%S') - ⚠️ High load detected (Load=$LOAD, Mem=$MEM%)" >> "$LOG_FILE"# Restart critical servicesfor svc in "${SERVICES[@]}"; doif systemctl is-active --quiet "$svc"; thensystemctl restart "$svc"echo "$(date '+%Y-%m-%d %H:%M:%S') - Restarted service: $svc" >> "$LOG_FILE"fidonesleep 60# Recheck load after restartLOAD_NOW=$(awk '{print int($1)}' /proc/loadavg)if [ "$LOAD_NOW" -gt "$MAX_LOAD" ]; thenecho "$(date '+%Y-%m-%d %H:%M:%S') - ❗ Load still high after restart, rebooting..." >> "$LOG_FILE"/sbin/rebootfifisleep 30doneMake it executable:sudo chmod +x /usr/local/bin/server-watchdog.shvim /etc/systemd/system/server-watchdog.service[Unit]Description=Simple watchdog for high load recoveryAfter=network.target[Service]Type=simpleExecStart=/usr/local/bin/server-watchdog.shRestart=alwaysRestartSec=30[Install]WantedBy=multi-user.target
Then reload and start the service:
sudo systemctl daemon-reloadsudo systemctl enable server-watchdogsudo systemctl start server-watchdog
查看pid程序是由哪个php文件开始执行的
sudo lsof -p pid | grep "\.php"sudo lsof -p 340314 | grep "\.php"
使用nginx 和 GeoIP2 阻止某地区ip访问
Install GeoIP2 for Nginx
// 争对如下系统级安装的nginx,如果是使用nginx 安装的,需要另外编译geoip2模块sudo apt updatesudo apt install nginx libnginx-mod-http-geoip2
Download MaxMind GeoLite2 database
如果没有 MaxMind GeoLite2 账号,创建license-keyCreate an account at MaxMind and get a license key.https://www.maxmind.com/en/accounts/current/license-keymkdir -p /usr/share/GeoIPcd /usr/share/GeoIPwget -O GeoLite2-Country.tar.gz \"https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_KEY&suffix=tar.gz"tar -xzf GeoLite2-Country.tar.gz会得到文件夹如:GeoLite2-Country_20260102里面会有GeoLite2-Country.mmdb将其移到/usr/share/GeoIP下mv /usr/share/GeoIP/GeoLite2-Country_20260102/GeoLite2-Country.mmdb /usr/share/GeoIP
Configure GeoIP2 in Nginx
编辑总nginx 配置文件,具体位置视情况而定vim /usr/local/nginx/conf/nginx.confInside http {} add:geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {$geoip2_country_code country iso_code;}
Block China only for a.com
位置视情况而定vim /usr/local/nginx/conf/vhost/a.com做如下修改map $geoip2_country_code $block_china {default 0;CN 1;}server {server_name a.com www.a.com;if ($block_china) {return 403;}...}