服务只要发布到公网,一定会被试探、暴力破解甚至漏洞利用,从无例外,所以建立自己的一套防御策略尤为重要。这次试从几个常见服务入手,探讨一下攻击威胁的分析和防御实现。

Linux平台有一个现成的监控和防护工具,叫fail2ban,可以用yum/apt直接安装。设定好监控目标、匹配规则、阈值后,即可自动进行防护,屏蔽攻击源。现在借ssh和nginx两个服务的防护粗浅地介绍一下fail2ban的入门(也可以不借助这个软件,而是自己用脚本或者其它工具对日志进行监控,并采取相应的动作)。

SSHD服务

照例放截图

一周时间记录了4万多次失败的登录尝试,这还是在开了防护(3次失败封禁IP)的情况下,如果关闭防护,这个数字将更为恐怖。

sshd防护比较简单,无需手工添加监控目标和匹配规则,只要按自己的需求修改maxretry、bantime、findtime即可(sshd防护的这三个配置继承了DEFAULT小节的配置值,如果要修改,可以对DEFAULT小节的内容进行调整);也可以不做任何修改,在软件安装以后,确认sshd小节的配置项包含enable=true,直接启动fail2ban服务。

状态查看命令:

# 查看当前的监控项总览
fail2ban-client status
# 查看指定服务的状态
fail2ban-client status 服务名

此外,在/etc/fail2ban/filter.d中,可以找到软件预置的针对ssh、nginx、apache、mysql等常见服务进行防护的几十条策略,供用户按需取用,免去了手动配置的麻烦。

root@df-www:/etc/fail2ban# fail2ban-client status
Status
|- Number of jail:      3
`- Jail list:   ddns-login, nginx-defend-phpenv, sshd
root@df-www:/etc/fail2ban# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 160
|  |- Total failed:     73949
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 1214
   |- Total banned:     1214
   `- Banned IP list:   218.75.207.11 34.68.200.168 (略)

nginx

这儿介绍的nginx防护并不是预设的ngnix策略,而是针对nginx日志自己撰写规则。在nginx配置vhost时,其中会有一个access_log项专门指定用户访问网站的请求记录存放位置(其实从server层级到location层级都可以配置日志,如果当前层级没有配置,会沿用上一个层级的设定)。

  • 如果一个网站并不是php写的,那所有针对php文件的请求一定是非法访问;
  • 如果没有phpmyadmin,那所有对phpmyadmin的访问都是非法访问;
  • 针对.git目录的访问,一定是非法访问;
    ……诸如此类,不一而足。

这就是封堵思路,看上去非常简单,但是想一步到位制定出一个完善的防护策略是不可能的,因为攻击方式五花八门,自www诞生到现在,各类web服务器、语言、框架的漏洞数不胜数,作为网站维护者,能做的只有被动防御。安全防护最重要的要求就是对自己的网站有足够的了解,能够去分辨哪些是正常访问,哪些是异常访问。攻击者手里有大量肉鸡资源,有大量漏洞库,拿这个作为武器发起进攻,防守方只能从零开始,这种情况下就更需要不断收集日志中的异常信息,建立并完善自己的策略库,才能使自己不会过于被动。

策略收集完成后,开始为fail2ban添加配置(以一个asp.net站点举例):

#/etc/fail2ban/failter.d/nginx-defend-non-phpenv.conf

[Definition]
failregex = <HOST>.*(\\x|phpstorm|<php>|wp-json|nmap|admin|shell|/config|wget|mstshash=|wordpress-database-reset|\.php|ajax_multi_upload/readme\.txt|explicit_not_exist_path|phpMyAdmin|phpmyadmin|action=register|\.jsp|\.asp|author-sitemap\.xml|/wcm/|/adminer-|/thinkphp/|/TP/|\.git|/solr)
ignoreregex =
#/etc/fail2ban/jail.conf


[nginx-defend-non-phpenv]
enabled = true
filter = nginx-defend-non-phpenv
port = http, https
logpath = /var/log/nginx/access.log
maxretry = 1
findtime = 2d
bantime = 2w
banaction = iptables-allports

额外的一些小提示

  • fail2ban,findtime,bantime不宜过长,因为大多数人没有固定公网ip,持有同一ip的时间不会太久。为黑名单设置有效期可以缓解服务器压力;
  • ssh尽量关闭密码登录,改用证书登录。