简介

fail2ban简单来说就是通过不断读取设定的日志文件,并通过正则校验每条日志是否符合规则。一旦符合,则提取日志中的IP地址与时间戳,然后写入到fail2ban的数据库中。写库的同时进行计数,如果该IP在设定的时间间隔内被匹配的次数超过阈值,则调用iptables,将其的请求reject。

前期的准备操作请参考0007-CentOS7/8 系统安装标准。Fail2ban 结构如下:

/etc/fail2ban ## fail2ban 服务配置目录

/etc/fail2ban/action.d ## iptables 、mail 等动作文件目录

/etc/fail2ban/filter.d ## 条件匹配文件目录,过滤日志关键内容

/etc/fail2ban/jail.conf ## fail2ban 防护配置文件

/etc/fail2ban/fail2ban.conf ## fail2ban 配置文件,定义日志级别、日志、sock 文件位置等

检查防火墙

#如果您已经安装iptables建议先关闭
service iptables stop
#查看Firewalld状态
firewall-cmd --state
#启动firewalld
systemctl start firewalld
#设置开机启动
systemctl enable firewalld.service
#放行22端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
#重载配置
firewall-cmd --reload
#查看已放行端口
firewall-cmd --zone=public --list-ports

安装配置

安装

安装成功后fail2ban配置文件位于/etc/fail2ban,其中jail.conf为主配置文件,相关的匹配规则位于filter.d目录,其它目录/文件一般很少用到,如果需要详细了解可自行搜索。

配置jail

cp jail.conf jail.local
vim jail.local


banaction = firewallcmd-ipset
action = %(action_mwl)s
#将默认的执行动作由iptables改为firewallcmd-ipset
[waf-blockip]
enabled = true
filter = waf-blockip
port = http,https
logpath = /tmp/2019*_waf.log
blocktype = DROP
action          = %(action_mwl)s
datapattern = %Y-%m-%d %H:%M:%S
bantime = 120
maxretry = 1
findtime = 1

[nginx-cc]
enabled = true
filter = nginx-cc
port = http,https
logpath = /tmp/cc.log
blocktype = DROP
action          = %(action_mwl)s
bantime = 120
maxretry = 1
findtime = 1

以上每行内容的大致意义如下:

[nginxx-cc]:定义jail名称

  • enabled:是否启用该jail,默认的所有规则都没有该项,需要手动添加
  • port:指定封禁的端口,默认为0:65535,也就是所有端口,但可以在jail中设定
  • filter:指定过滤器名称
  • logpath:日志路径
  • action:达到阈值后的动作
  • maxretry:阈值
  • findtime:时间间隔
  • bantime:封禁时长
  • ignoreip:忽略的IP

注意

logpath与action可以有多行,如action中的设定:调用iptables-multiport封禁目标IP访问的多个端口,调用sendmail发送告警邮件

findtime不是检查日志的时间间隔,日志的检查是实时的。因为fail2ban自带数据库,所以可以在设定的时间内统计匹配次数

ignoreip添加后端服务器的IP或CDN的IP

配置filter

vim waf-blockip.conf
[Definition]
failregex = \"<HOST>\",\"rule_tag\"
ignoreregex =

日志内容如下所示:

{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 11:59:45","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"ApacheBench\/2.3"}
{"local_time":"2019-06-18 12:00:13","client_ip":"192.168.13.215","rule_tag":"-","attack_method":"CC_Attack","server_name":"status.myj.com.cn","req_url":"\/","req_data":"-","user_agent":"curl\/7.29.0"}

vim nginx-cc.conf
[Definition]
failregex =  <HOST> - - \[.*\] .*GET \/\?=*
#failregex = <HOST> - - \[.*\] \".*(403|400).*\"		#匹配403或404的错误
ignoreregex =

47.52.195.189 - - [13/Jun/2019:18:18:47 +0800] "GET /?=18566 HTTP/1.1" 403 552 "https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; Linux x86_64)AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
47.52.195.189 - - [13/Jun/2019:18:18:47 +0800] "GET /?=18566 HTTP/1.1" 403 552 "https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; Linux x86_64)AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
47.52.195.189 - - [13/Jun/2019:18:18:47 +0800] "GET /?=18566 HTTP/1.1" 403 552 "https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; Linux x86_64)AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
47.52.195.189 - - [13/Jun/2019:18:18:47 +0800] "GET /?=18566 HTTP/1.1" 403 552 "https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; Linux x86_64)AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
50.195.104.171 - - [13/Jun/2019:18:18:47 +0800] "GET /?=13253 HTTP/1.1" 504 905"https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; U; NetBSD amd64; en-US; rv:1.9.2.15) Gecko/20110308 Namoroka/3.6.15"
47.52.195.189 - - [13/Jun/2019:18:18:47 +0800] "GET /?=18566 HTTP/1.1" 403 552 "https://www.google.com/search?q=120.79.35.33/" "Mozilla/5.0 (X11; Linux x86_64)AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24"
192.168.13.43 - - [06/Jun/2019:18:25:58 +0800] "GET /ngx_status HTTP/1.1" 301 16"-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"

常用配置

#查看被ban IP,其中ssh-iptables为名称,比如上面的[ssh-iptables]和[nginx-dir-scan]
fail2ban-client status ssh-iptables
#添加白名单
fail2ban-client set ssh-iptables addignoreip IP地址
#删除白名单
fail2ban-client set ssh-iptables delignoreip IP地址
#查看状态
fail2ban-client status
#查看日志
tail /var/log/fail2ban.log
#查看规则
firewall-cmd --direct --get-all-rules
ipset list

定时清理日志

vi /root/del_waf_log.sh
#! /bin/bash
cat /dev/null > /tmp/`date +"%Y-%m-%d"`-waf.log
chmod +x /root/del_waf_log.sh
crontab -e
30 3 * * 0 sh /root/del_waf_log.sh

1002-Linux常用指令中有介绍crontab的用法。

内核优化

针对TIME_WAIT的问题,可以通过调整内核的方式进行优化。

#修改超时时间为30秒,某些情况可以进一步降低该值
net.ipv4.tcp_fin_timeout = 30
#将keepalive的发送频率降低为20分钟一次
net.ipv4.tcp_keepalive_time = 1200
#开启SYN Cookies,当SYN队列溢出时启用Cookies
net.ipv4.tcp_syncookies = 1
#开启TIME-WAIT sockets重用功能
net.ipv4.tcp_tw_reuse = 1
#开启TIME-WAIT sockets快速回收功能
net.ipv4.tcp_tw_recycle = 1
#加大SYN队列
net.ipv4.tcp_max_syn_backlog = 8192
#最大TIME_WAIT保持数,超过将全部清除
net.ipv4.tcp_max_tw_buckets = 5000

过滤规则

nginx的验证

fail2ban-regex /tmp/2019-07-10_waf.log /etc/fail2ban/filter.d/waf-blockip.conf
failregex = ^ \[error\] \d+#\d+: \*\d+ user "\S+":? (password mismatch|was not found in ".*"), client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$
^ \[error\] \d+#\d+: \*\d+ no user/password was provided for basic authentication, client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$

检查fail2ban启动问题

fail2ban-client -x start

modsecurity 日志过滤

利用 modsecurity 结合 nginx 并整合到 微服务网关实现 web 安全防护。1212-kong 增加 WAF 功能 

kong 网关结合 modsecurity 输出的日志格式如下

112.119.33.91 - - [18/Dec/2020:09:21:58 +0800] "GET /socket.io/?__sails_io_sdk_version=0.13.8&__sails_io_sdk_platform=browser&__sails_io_sdk_language=javascript&EIO=3&transport=polling&t=NPpS75x&sid=o6ZI8VoIHqBUgvFMAACb HTTP/2.0" 200 4 "https://dashboard.waringid.me/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
2020/12/18 09:23:10 [error] 25142#0: *659 [client 113.78.65.148] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/owasp-modsecurity-crs-3.2.0/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "79"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "172.19.0.5"] [uri "/.env"] [unique_id "1608254590"] [ref ""], client: 113.78.65.148, server: kong, request: "GET /.env HTTP/1.1", host: "dashboard.waringid.me"
113.78.65.148 - - [18/Dec/2020:09:23:10 +0800] "GET /.env HTTP/1.1" 403 150 "-" "curl/7.29.0"
51.159.23.43 - - [18/Dec/2020:09:28:46 +0800] "GET / HTTP/1.1" 404 48 "-" "-"
89.97.157.10 - - [18/Dec/2020:09:43:52 +0800] "GET / HTTP/1.1" 404 48 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"

注意2种不同的日志格式类型,2中不同日志类型匹配不同的正则式。

同时注意不同日志时间格式也不一样。

frp 的 RDP 规则

内容描述
操作系统ubuntu 22
frp 0.60

frps.toml

bindPort = 8003
kcpBindPort = 8003

webServer.addr = "127.0.0.1"
webServer.port = 8002
webServer.user = "admin"
webServer.password = "admin"

log.to = "/tmp/frps.log"
log.level = "info"
log.maxDays = 30

log.disablePrintColor = false
detailedErrorsToClient = true

auth.method = "token"
auth.token = "token"

vhostHTTPPort = 8004

subdomainHost = "XXX.com"

allowPorts = [{ start = 20000, end = 20010 }, { single = 3001 },{ single = 3003 },{ start = 4000, end = 50000 }]

maxPortsPerClient = 5
udpPacketSize = 1500
natholeAnalysisDataReserveHours = 168

frps.toml

[common]
server_addr = frps.XXXX.com
server_port = 8003
protocol = kcp
tls_enable = true
authenticate_heartbeats = true
authenticate_new_work_conns = true
authentication_method = token
token = 52gqTvPh1gPM
log_file = ./frpc.log

[RDP-20001]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 20001

/etc/fail2ban/filter.d/frps-rdp-ban.conf

[Definition]
failregex = ^.*\[.*rdp.*\] get a user connection \[<HOST>:[0-9]*\]
ignoreregex =

这个用来匹配 frps 的日志文件,其日志文件的输出内容如下所示:

2024-09-23 08:14:41.412 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:63981]
2024-09-23 08:14:44.308 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [211.21.123.115:63136]
2024-09-23 08:14:44.588 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:53202]
2024-09-23 08:14:47.247 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:57434]
2024-09-23 08:14:47.849 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [79.124.56.98:55196]
2024-09-23 08:14:47.966 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [82.156.52.66:60816]
2024-09-23 08:14:49.950 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:61851]
2024-09-23 08:14:51.278 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [79.124.56.98:57478]
2024-09-23 08:14:52.579 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:49965]
2024-09-23 08:14:55.397 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:54936]
2024-09-23 08:14:58.689 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:60820]
2024-09-23 08:15:01.047 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [60.22.145.91:58053]
2024-09-23 08:15:01.392 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:65291]
2024-09-23 08:15:03.807 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [103.246.244.75:52594]
2024-09-23 08:15:04.531 [I] [proxy/proxy.go:204] [21534afeadc68513] [rdp] get a user connection [116.148.225.90:64580]

/etc/fail2ban/jail.conf

[frps-rdp-ban]
enabled = true
findtime = 10m
maxretry = 3
bantime = 8h
filter = frps-rdp-ban
logpath = /tmp/frps.log
protocol = all
port = all
chain = all
action = iptables-allports[name=frps,protocol=tcp]
systemctl restart fail2ban
fail2ban-client status frps-rdp-ban

  • 无标签