ip-blacklist-cloud插件使用小结

3,077 views

日前为了屏蔽外部对登录页面的恶意访问,于是安装了插件ip-blacklist-cloud,WordPress项目主页GitHub项目主页

经过一段时间的试用,观察到几个现象:

  1. 异常登录的邮件变少了,从每天几百封到每天几封,说明大部分恶意访问被插件屏蔽了,这个感觉不错;
  2. 有天闲来无事,在家里登录管理后台,发现众登录页面跳转时浏览器报错500;然后查看SAE的应用控制面板,提示说数据库访问流量超标,百思不得其解;
  3. 刷微博的时候发现SAE提供了MySQL数据库访问面板,于是顺手打开瞄了一眼,惊讶的发现有张表居然占用了500MB的容量;仔细一看,表名是xap_IPBLC_login_failed,查了下表的内容,基本上是登录失败时记录的信息,于是使用清空该表的数据,Jackie的家的博客后台又可以正常登录了;
  4. 登录Jackie的家的博客后台,检查ip-blacklist-cloud记录的IP黑名单,发现相同IP有相当多的重复记录,检查表xap_IPBLC_blacklist里的数据,确实和界面看到的情况一致,相同IP存在重复记录;
  5. SAE提供了一些图表,用来呈现小站的资源使用情况,其中监控了MySQL的使用情况。Jackie的小站没有多少文章,一天也没多少朋友来看,印象里这张图表的线之前都是趴在水平线上的;但检查MySQL的使用量图表,发现各项指标完全超出我的想像,流入流量 1.4 G,流出流量 10.8 G,CPU时间 0 ms,请求数 14.45万次,这数据太让人惊讶,很不可思议;
  6. 在日志中心,检查共享型MySQL的慢日志,发现大量的SELECT * FROM xap_IPBLC_login_failed;,感觉越来越不正常了。
    1. 为什么对这张表作查询?
    2. 查询时没有带上条件,相当于是获取全表数据,什么场景下需要全表的数据?
  7. 在日志中心,之前的记录基本是空的,但最近可以看到访问外网的记录,如下。

    [ 2016-04-18 22:00:31 ] 10.67.15.180 – – [18/Apr/2016:22:00:31 +0800] “POST / HTTP/1.1” 0.426 “http://www.ip-finder.me/lastUpdate.php?website=http%3A%2F%2Fjackieathome.sinaapp.com” 403 531 401 “http://jackieathome.sinaapp.com” “SAE/fetchurl-ykx3l1l0ol PHP/5.6.14” 10.67.15.48 50.87.180.41:80 “0.425” yq214

于是忍不住走读了ip-blacklist-cloud的代码,有如下发现:


插件创建了三张表,分别是(xap_是表名前缀,创建博客时需要在wp-config.php中指定)

  • xap_IPBLC_login_failed,用来记录用户登录失败的历史;
  • xap_IPBLC_blacklist,记录黑名单里的IP;
  • xap_IPBLC_usernames,记录黑名单里的用户名;

表的字符集为utf8_general_ci,。存储器类型为MyISAM,导致WordPress对这三张表的访问不支持事务处理,对数据的变更操作会锁表,阻塞其它访问请求。


创建表的语句写在create_sql方法中,三张表的创建方式近似,因此这里只举一个例子,如下

if(!($wpdb->query("SELECT * FROM ".$wpdb->prefix."IPBLC_login_failed"))) 
{

    $sql = "CREATE TABLE ".$wpdb->prefix."IPBLC_login_failed (
    id INT(60) UNSIGNED NOT NULL AUTO_INCREMENT,
    IP VARCHAR(25) NOT NULL, 
    useragent VARCHAR( 225 ) NOT NULL, 
    variables TEXT NOT NULL, 
    timestamp INT(30) NOT NULL,
    UNIQUE KEY id (id)
    );";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}

建表SQL中规中矩,没什么特别之处。但是作者使用读取全表数据的方法来判断表是否存在,这就有点夸张了,比如如下场景:

  1. 表已创建好;
  2. 表内数据量比较大;

那么每做一次表是否存在的检查,就需要把表内全部数据都获取出来,这显然不是一种低碳的实现方案。


检查create_sql的使用位置,发现使用如下方式注册了事件。

add_action('admin_init', 'create_sql');

咨询了度娘,WordPress加载管理界面前执行该动作函数,即当管理员登录WordPress管理面板时,create_sql方法就会被主动调用。如果有爬虫或者类似的工具不停的访问管理面板的登录页面的话,create_sql方法将会被反复调用;而在前述的场景下,create_sql方法将会是一个极其耗费资源的行为,Jackie的家前几日被SAE平台禁用应该和这里的代码有一定关系。


如下代码让人不能恭维。

$IP_in_DP=$wpdb->get_var($wpdb->prepare("SELECT id FROM ".$wpdb->prefix."IPBLC_blacklist WHERE IP=%s",$IP));
if($IP_in_DP)
{
    $visits=$wpdb->get_var($wpdb->prepare("SELECT visits FROM ".$wpdb->prefix."IPBLC_blacklist WHERE id=%d",$IP_in_DP));
    $visits=$visits+1;

    $t=time();

    $wpdb->query($wpdb->prepare("UPDATE ".$wpdb->prefix."IPBLC_blacklist SET `visits`=%d WHERE id=%d",array($visits,$IP_in_DP)));
    $wpdb->query($wpdb->prepare("UPDATE ".$wpdb->prefix."IPBLC_blacklist SET `lastvisit`=%d WHERE id=%d",array($t,$IP_in_DP)));

这段代码做了几件事:

  1. 使用IP查询,IPBLC_blacklist内是否存在相关的记录;
  2. 如果记录存在,则提取该IP对应的访问数量visits
  3. visits变量自增;
  4. 修改原记录中visits变量的值;
  5. 修改原记录中上一次访问时间lastvisit为当前时间;

按我的理解,这样的代码实现在高并发场景下,效率不高,而且无法保证准确性。

总结一下,插件ip-blacklist-cloud有几个特点:

  1. 插件的页面效果不错;
  2. 拦截的基本功能具备,但不那么可靠;
  3. 代码格式的美感不足;
  4. 代码实现不是很理想,细节上欠缺考虑;

Jackie通过微博向SAE客服反馈了当前遇到的问题,客服的意见是开启应用防火墙,直接在平台层面屏蔽恶意访问。官网对应用防火墙的介绍:

应用防火墙是应用级别的防护,可用在防抓站、防刷单等场景,保护云豆不被恶意消耗。工作在负载均衡层,可以针对自己的业务自定义规则,请求一旦匹配规则,就不会再向后转发。

按照SAE平台当前的计费规则,对于月访问量低于15万次的应用来说,包月费只有1元/月,还算能接受吧。

最后,Jackie做了两件事:

  1. 修改插件ip-blacklist-cloud的代码,注释掉create_sql中检查表是否存在、创建表相关的代码;
  2. 开启了应用防火墙,把插件收集到的恶意访问来源的IP加到黑名单里,如下列表,还是蛮壮观的

    89.161.131.223 波兰
    103.49.205.15 新西兰
    149.62.170.40 西班牙
    177.185.196.31 巴西
    185.26.122.224 俄罗斯
    185.26.122.99 俄罗斯
    185.69.233.116 荷兰
    187.17.109.90 巴西
    188.132.129.19 土耳其
    194.213.5.204 德国
    198.57.209.183 美国
    202.57.16.84 印尼
    205.134.241.45 美国
    208.113.153.225 美国
    212.63.209.201 瑞典
    213.251.182.107 法国
    213.251.182.111 法国
    213.251.182.115 法国
    216.12.194.43 新加坡
    217.70.180.225 法国
    217.79.179.163 德国
    45.32.147.210 荷兰
    5.77.61.129 英国
    31.41.43.1 俄罗斯
    50.116.69.40 美国
    62.128.51.151 以色列
    72.167.190.4 美国
    64.90.48.104 美国
    85.111.52.8 土耳其
    85.17.232.207 荷兰
    85.252.49.19 挪威
    89.161.231.28 波兰
    91.234.146.97 波兰
    94.138.212.114 土耳其
    94.73.148.228 土耳其
    95.128.114.50 瑞典
    97.74.232.207 美国



若非注明,均为原创,欢迎转载,转载请注明来源:ip-blacklist-cloud插件使用小结

关于 JackieAtHome

基层程序员,八年之后重新启航

此条目发表在 WordPress, 笔记 分类目录,贴了 , , , , 标签。将固定链接加入收藏夹。