如何在Linux上使用Fail2ban保护Nginx

・14 分钟阅读

当我在Linux上使用Nginx部署一个ASP.NET核心应用程序时,我发现在Nginx日志中有很多流氓和垃圾邮件的网络流量,大多数是轻度的入侵尝试和大量的php请求,它大部分是噪音,也不友好,但是,我想要一种禁止这些ip地址的方法,这就是我如何使用Fail2ban的方法。

什么是Fail2ban?

简而言之,它是一种基于定义的正则表达式扫描日志文件的工具,如果它匹配,它将执行一个操作,Fail2ban可以扫描许多不同类型的日志,比如,Nginx,Apache和ssh日志,根据匹配,它能够在配置的时间段内禁止IP地址。

如果你熟悉Linux生态系统,安装Fail2ban并不需要太长时间,它可能需要一些时间来设置和调整您的规格。一切取决于你的需要。

摘要

  • 安装Fail2ban ,
  • 配置Fail2ban默认值,
  • 添加我们的第一个jail规则,以便它可以监视Nginx日志,
  • 测试所有工作,

安装Fail2Ban

  1. 运行以下命令更新Ubuntu上的软件包列表,
 
sudo apt-get update

 
  1. 安装Fail2Ban

sudo apt-get install fail2ban

做完了, 这很容易。现在是配置它的时候了。

配置Fail2ban默认值

  1. 复制原始jail.conf,以便修改它,

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

  1. 现在,让我们修改文件:

nano /etc/fail2ban/jail.local

  1. 修改ignoreip,使它忽略你的主机ip地址,这应该是你的外部ip地址,

[DEFAULT]

#
# MISCELLANEOUS OPTIONS
#

# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be
# defined using space separator.
ignoreip = 127.0.0.1/8 your-ip-address-here


如果你的外部ip地址是54.15.55.01,那么它应该类似于下面这样:


ignoreip = 127.0.0.1/8 54.15.55.01

  1. 修改默认bantimefindtimemaxretry ,我已经将它设置为永久重试时间,如下所示:

# "bantime" is the number of seconds that a host is banned.
bantime = -1 # this is permanant

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 1

# "maxretry" is the number of failures before a host get banned.
maxretry = 1

在Fail2ban中配置jail,以便它可以监视Docker Nginx日志,

在文件/etc/fail2ban/jail.local中有一个名为Jails的节,这就是为Fail2ban设置预定义规则的地方,以便它知道要应用哪种筛选器以及监视日志文件,首先,我们需要了解docker文件的记录方式和位置。

如何查找Docker日志所在的位置

Docker日志文件通常记录为json,以便查找Docker日志文件的位置,只需运行下面的docker inspect [containername]命令,


docker inspect nginx-web

结果将是如下所示:


...
"HostsPath": "/var/lib/docker/containers/94dc5a3**/hosts",
"LogPath": "/var/lib/docker/containers/94dc5a3**/94dc5a3**-json.log",
"Name": "/nginx-web"
...

注意,LogPath是Docker日志文件用于特定容器的地方。

创建我们的第一个监狱

现在我们得到了logpath,我们可以创建第一个jail ,
下面的监狱为Nginx拒绝任何尝试请求类型, 比如.exe等类型的请求。


[nginx-noscript]
enabled = true
port = http,https
filter = nginx-noscript
logpath = /var/lib/docker/containers/*/*-json.log 

注意,enabled标志设置为true,并且已设置logpath,但是,Docker日志的通配符路径为,现在你可以特定,但是要注意,每次Docker容器重新启动时,它将位于containers的不同文件夹中。

创建相应的筛选器

现在,如果一个文件不存在,则创建一个文件,/etc/fail2ban/filter.d/nginx-noscript.conf 文件名必须与在jail中指定的filter名称匹配。


nano /etc/fail2ban/filter.d/nginx-noscript.conf

下面是正则表达式,请注意,它有一个^{"log"前缀,这样做的原因是,Docker以json格式记录。


[Definition]

failregex = ^{"log":" -.*GET.*(.php|.asp|.exe|.pl|.cgi|.scgi)

ignoreregex =

重新启动Fail2ban

jail.local中进行的任何更改都需要重新启动Fail2ban ,以下是将重新启动服务的命令。

service fail2ban restart

fail2ban-client reload

如果失败或过滤器出现错误,将报告错误。

测试过滤器

为了确保过滤器按照定义的正则表达式按预期工作,Fail2ban提供两种测试它们是否工作的方法。

选项1-指定日志文件和筛选文件

fail2ban-regex命令行工具提供了一种测试正规表达式是否正常工作的方法。

你可以按如下方式使用它:


fail2ban-regex  

这里有一个使用的样品。


fail2ban-regex /var/lib/docker/containers/7c2442*/*-json.log /etc/fail2ban/filter.d/nginx-noscript.conf

下面显示了一个示例输出报告。


Running tests
=============

Use failregex filter file : nginx-noscript, basedir: /etc/fail2ban
Use log file : /var/lib/docker/containers/94dc5*/94dc5*-json.log
Use encoding : UTF-8


Results
=======

Failregex: 233 total
|- #) [# of hits] regular expression
| 1) [233] ^{"log":" -.*GET.*(.php|.asp|.exe|.pl|.cgi|.scgi)
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
| [724] Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:.Microseconds)?(?: Zone offset)?
`-

Lines: 724 lines, 0 ignored, 233 matched, 491 missed
[processed in 0.10 sec]

注意到报告的结尾 233 matched, 491 missed 这意味着筛选器能够匹配233行和491不适用,这表明正规表达式正在匹配和工作。

选项2-指定内联

fail2ban-regex还提供了一种测试内联而不是指定日志文件的方法。

下面是如何使用它的语法。


fail2ban-regex '' ''

下面是一个真实的例子。


fail2ban-regex '{"log":"111.22.333.444 47.95.1.195 - - [05/Jul/2018:21:42:40 +0000] "GET /phpMyadmin_bak/index.php HTTP/1.1" 503 213 "-" "Mozilla/5.0"n","stream":"stdout","time":"2018-07-05T21:42: 40.24318153Z"}' '{"log":".*GET.*.php.*'

下面的示例指定一个日志文件条目:


'{"log":"111.22.333.444 47.95.1.195 - - [05/Jul/2018:21:42:40 +0000] "GET /phpMyadmin_bak/index.php HTTP/1.1" 503 213 "-" "Mozilla/5.0"n","stream":"stdout","time":"2018-07-05T21:42:40.24318153Z"}' 

还有正规表达式 {"log":".*GET.*.php.*' 用于验证是否有效。

下面是示例报告:


Running tests
=============

Use failregex line : {"log":".*GET.*.php.*
Use single line : {"log":"111.22.333.444 47.95.1.195 - - [05/Jul/201...


Results
=======

Failregex: 1 total
|- #) [# of hits] regular expression
| 1) [1] {"log":".*GET.*.php.*
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
| [1] Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:.Microseconds)?(?: Zone offset)?
`-

Lines: 1 lines, 0 ignored, 1 matched, 0 missed
[processed in 0.03 sec]

验证所有工作

你可以不时运行status命令来验证fail2ban是否确实正在被禁止和工作。


sudo fail2ban-client status

你将获得以下输出:


Status
|- Number of jail: 2
`- Jail list: nginx-noscript, sshd

注意,监狱列表有两个,nginx-noscriptsshd ,你现在可以通过指定jail来运行附加状态命令,例如:


sudo fail2ban-client status nginx-noscript

下面是输出。


Status for the jail: nginx-noscript 
|- Filter 
| |- Currently failed: 0 
| |- Total failed: 0 
| `- File list: /var/lib/docker/containers/**-json.log 
`- Actions 
 |- Currently banned: 0 
 |- Total banned: 0 
 `- Banned IP list: 

从上面,你可以看到有多少被禁止的摘要。

一个有用的监狱列表

下面是我个人使用的jail及它各自过滤器的列表,欢迎使用和修改。

Nginx x00请求

阻止潜在的恶意x03x00请求。

示例恶意请求


77.72.83.87 - - _ [28/Dec/2018:14:13:14 +0000] "x03x00x00/*xE0x00x00x00x00x00Cookie: mstshash=Administr" 400 150 "-" "-"


[nginx-x00] 
enabled = true 
port = http,https 
filter = nginx-x00
logpath = /var/lib/docker/containers/*/*-json.log

筛选
文件名: /etc/fail2ban/filter.d/filter.d/nginx-x00.conf


[Definition] 

failregex = ^{"log":" .* .*x.*$

ignoreregex =

Php请求

阻止php攻击

示例恶意请求


106.12.127.143 - - 209.97.142.137 [28/Dec/2018:14:27:46 +0000] "GET /cmd.php HTTP/1.1" 503 190 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0"


[php-custom] 
enabled = true
port = http,https
filter = php-custom 
logpath = /var/lib/docker/containers/*/*-json.log

筛选
文件名: /etc/fail2ban/filter.d/filter.d/php-custom.conf


[Definition]

failregex = {"log":".*(GET|POST).*(.php).*$

ignoreregex = 

Git

试图获取git文件时的阻止请求,这是一个有趣的阅读:
https://slashcrypto.org/2018/11/28/eBay-source-code-leak/


[git-bad]
enabled = true 
port = http,https 
filter = git-bad
logpath = /var/lib/docker/containers/*/*-json.log 

筛选
文件名: /etc/fail2ban/filter.d/filter.d/git-bad.conf


[Definition]

failregex = {"log":". *(GET|POST).*(/.git).*$

ignoreregex =


摘要

在文章中我演示了如何在Linux机器上安装Fail2ban,并且配置它,以便你可以保护服务器和Nginx,防止潜在的恶意http请求。

参考:

Zhongy0410 profile image