Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

每周异常:第 4期,如何避免客户端攻击造成的大量异常报警 (20130807) #14

Closed
hotoo opened this issue Aug 7, 2013 · 2 comments

Comments

@hotoo
Copy link
Member

hotoo commented Aug 7, 2013

在 JavaScript 异常监控过程中,发现有很多由于客户端连续攻击造成的大量异常,导致监控系统报警。

2013-08-07 9 58 37

(图中大量不连续的波动,都是攻击造成的)

这种少量用户(UV)发起攻击造成的大量异常(PV)波动,不是我们实时监控需要关注的部分。
我们实时监控最重要的是要发现由于系统发布过程中,我们的发布的代码有问题导致大量用户受影响而出现的波动(波形可能跟上图的每一个异常波形相似)。

理论上导致异常数据波动的场景包括:

  • 少量用户发起大量攻击。
  • 大量用户同时涌入或离开。
  • 发布问题代码影响到大量用户。

少量用户发起大量攻击造成数据波动,是我们可以不必实时关注实时报警的部分。

大量用户同时涌入或离开造成的异常数量(PV)波动,也是我们无需实时关注的部分,另外我们也可以通过异常率规避波动。

场景 异常 PV 异常 UV 异常率(PV) 异常率(UV)
攻击 波动 无波动 波动 无波动
涌入 波动 波动 无波动 无波动
发布 波动 波动 波动 波动

注:

  • 异常率(PV) = 异常PV / 所在页面PV
  • 异常率(UV) = 异常UV / 所在页面UV

从上面的对照表可以看出,理论上我们只需要关注异常率(UV) 是否正常波动就可以了。

理想很性感,现实很骨感。

我们的数据仓库、数据分析系统对于实时 PV 有很强的处理能力,但是对于 UV 就感觉力有不逮。

起初想到在实时日志处理逻辑中使用缓存(伪代码):

class LogParse(){

  var user_cache = {};
  var MINUTES_FORMAT = "YYYYMMDDHHmm";
  var lastTime = moment().format(MINUTES_FORMAT);

  function parse(log){
    // PV 统计

    var now = moment().format(MINUTES_FORMAT);
    if(now !== lastTime){
      user_cache = {};
      lastTime = now;
    }
    if(user_cache.hasOwnProperty(user_id)){return;}
    // UV 统计
  }

}
  • 但是实时数据分析系统是分布式的,由多台服务器组成的集群同时处理日志,所以里面的内部状态只有本机有效
  • 另外更致命的是,实时数据分析系统是无状态的,下次执行会 new 新的 LogParser 实例,同一台机器的状态也保证不了。

于是我们又想到一种从客户端来标识用户的方法:

  1. 客户端单位时间内同一个页面抛出的同一个异常,第一次打上 uv 标记。
  2. 数据处理时遇到 uv 标记的日志,同时统计算做一个异常 uv。

由于客户端时间和服务端有时间差,每个客户端时间和服务端时间差也不一致,导致这种方案会有稍大误差,但也基本能解决问题。

但是要在客户端打标记,则需要在客户端(cookie 或其他本地存储)记录每个异常(url, file, line, message 相同被当作同一个异常)最后抛出的时间,每次抛出异常都需要读写本地存储,稍嫌臃肿。

通过深入分析实际的攻击案例,发现攻击引发大量异常的场景中,客户端页面是不刷新或重新访问的,都是直接在当前访问的页面执行上批量脚本。

因此我们可以使用局部变量,将当前访问的页面的每个异常最后抛出时间记录在内存中,重新访问页面则重新开始记录。

这种方案对于防范攻击造成的大量异常非常有效;对于大量用户涌入引起的异常也有一定效用,毕竟正常用户较少会频繁触发异常。

总之,通过这个方案,我们可以非常有效的实时监控异常波动,较少误报。

p.s. 这个想法是早上洗澡的时候想到的,还没开始实践。但是我信心满满写下这篇,数据会来证明我是对的。

@lifesinger
Copy link

这个想法是早上洗澡的时候想到的,还没开始实践。但是我信心满满写下这篇,数据会来证明我是对的。

顶这句话。

@noahlu noahlu closed this as completed Aug 13, 2013
@hotoo hotoo reopened this Aug 14, 2013
@hotoo hotoo closed this as completed Aug 16, 2013
@hotoo
Copy link
Member Author

hotoo commented Aug 20, 2013

是时候结帐了。正好发布一天,大家看数据:

2013-08-20 3 55 10

图中的灰色竖线是发布点,橙色是 JavaScript 异常,绿色是静态资源异常。

妈妈再也不用担心我的手机会收到误报的报警短信了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants