首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

jetty防止Dos攻打的filter实现分析

2012-09-11 
jetty防止Dos攻击的filter实现分析jetty的org.eclipse.jetty.servlets.DoSFilter类是用来实现Dos攻击预防

jetty防止Dos攻击的filter实现分析

jetty的org.eclipse.jetty.servlets.DoSFilter类是用来实现Dos攻击预防的filter,里面涉及到一些变量,先了解下变量的含义:

 

    protected long _delayMs;超过最大处理请求数当前请求的等待时间,-1立即拒绝,0,无限等待,正数表达等待的毫秒数

    protected long _throttleMs;异步等待获取信号量的时间

    protected long _maxWaitMs;阻塞等待获取信号量的时间

    protected long _maxRequestMs;请求处理最大时间限制

    protected long _maxIdleTrackerMs;跟踪连接是否断开的最大等待时间

    protected int _throttledRequests;允许在等待队列中等待获取信号量的请求数

    protected int _maxRequestsPerSec; 每秒允许处理最多的请求数,超过将延迟,异步等待。

 

    protected boolean _insertHeaders; 是否往response写入dosfilter信息,默认true

    protected boolean _trackSessions;是否根据session来检测dos攻击,默认true

    protected boolean _remotePort;是否根据ip+port来检测dos攻击,默认false

protected String _whitelistStr;  白名单 ip白名单列表,这些通过都通过配置servlet的init-p

 

aram可以来重新设置。

 

首先看看init方法的初始化设置:


  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) throws IOException, ServletException    {        final HttpServletRequest srequest = (HttpServletRequest)request;        final HttpServletResponse sresponse = (HttpServletResponse)response;        final long now=_requestTimeoutQ.getNow();        // Look for the rate tracker for this request        RateTracker tracker = (RateTracker)request.getAttribute(__TRACKER);         if (tracker==null) //如果request没有进行过dosfilter的处理        {            // This is the first time we have seen this request.            // get a rate tracker associated with this request, and record one hit            tracker = getRateTracker(request); //根据request生成dos跟踪的对象,看下面方法            // Calculate the rate and check it is over the allowed limit            final boolean overRateLimit = tracker.isRateExceeded(now);//判断是否已经超过每秒最大处理请求数            // pass it through if  we are not currently over the rate limit            if (!overRateLimit)//如果没有超过,则正常处理            {                doFilterChain(filterchain,srequest,sresponse);                return;            }            // We are over the limit.            Log.warn("DOS ALERT: ip="+srequest.getRemoteAddr()+",session="+srequest.getRequestedSessionId()+",user="+srequest.getUserPrincipal());            // So either reject it, delay it or throttle it            switch((int)_delayMs) //根据当前配置的延时时间            {                case -1: //如果为-1,则直接拒绝                {                    // Reject this request                    if (_insertHeaders) //是否把dosfilter处理插入response的header                        ((HttpServletResponse)response).addHeader("DoSFilter","unavailable");                    ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);                    return;                }                case 0: //如果为0,则当前线程继续等待处理,                {                    // fall through to throttle code                    request.setAttribute(__TRACKER,tracker);                    break;                }                default://其他字段,则设置request的timeout时间为_delayMs,并且挂起当前线程,返回                {                    // insert a delay before throttling the request                    if (_insertHeaders)                        ((HttpServletResponse)response).addHeader("DoSFilter","delayed");                    Continuation continuation = ContinuationSupport.getContinuation(request);                    request.setAttribute(__TRACKER,tracker);                    if (_delayMs > 0)                        continuation.setTimeout(_delayMs);                    continuation.suspend();                    return;                }            }        }//_delayMs为0是,当前请求继续等待        // Throttle the request        boolean accepted = false;        try        {            // check if we can afford to accept another request at this time            accepted = _passes.tryAcquire(_maxWaitMs,TimeUnit.MILLISECONDS);//判断当前处理请求队列是否已经有处理完的请求,处理完的会释放信号量,则当前请求线程可以获取信号量            if (!accepted) //如果不能获取,则把当前请求设置为异步等待,异步等待的时间为_throttleMs,            {                // we were not accepted, so either we suspend to wait,or if we were woken up we insist or we fail                final Continuation continuation = ContinuationSupport.getContinuation(request);                Boolean throttled = (Boolean)request.getAttribute(__THROTTLED);                if (throttled!=Boolean.TRUE && _throttleMs>0)                {                    int priority = getPriority(request,tracker);                    request.setAttribute(__THROTTLED,Boolean.TRUE);                    if (_insertHeaders)                        ((HttpServletResponse)response).addHeader("DoSFilter","throttled");                    if (_throttleMs > 0)                        continuation.setTimeout(_throttleMs);                    continuation.suspend();                    continuation.addContinuationListener(_listener[priority]);                    _queue[priority].add(continuation);                    return;                }                // else were we resumed?                else if  (request.getAttribute("javax.servlet.resumed")==Boolean.TRUE)                 {//如果线程中心被唤醒,则可以获取到信号量,                    // we were resumed and somebody stole our pass, so we wait for the next one.                    _passes.acquire();                    accepted = true;                }            }            // if we were accepted (either immediately or after throttle)            if (accepted) //获取到了,继续执行,                // call the chain                doFilterChain(filterchain,srequest,sresponse);            else            {                // fail the request                if (_insertHeaders)                    ((HttpServletResponse)response).addHeader("DoSFilter","unavailable");                ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);            }        }        catch (InterruptedException e)        {            _context.log("DoS",e);            ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);        }        finally        {            if (accepted) //执行完了之后释放当前的信号量,唤醒等待队列中的第一个请求进行处理            {                // wake up the next highest priority request.                for (int p = _queue.length; p-- > 0;)                {                    Continuation continuation = _queue[p].poll();                    if (continuation != null && continuation.isSuspended())                    {                        continuation.resume();                        break;                    }                }                _passes.release();            }        }    }  public RateTracker getRateTracker(ServletRequest request)    {        HttpServletRequest srequest = (HttpServletRequest)request;        HttpSession session=srequest.getSession(false);        String loadId = extractUserId(request);        final int type;        if (loadId != null)        {            type = USER_AUTH;        }        else        {            if (_trackSessions && session!=null && !session.isNew())            {                loadId=session.getId();                type = USER_SESSION;            }            else            {                loadId = _remotePort?(request.getRemoteAddr()+request.getRemotePort()):request.getRemoteAddr();                type = USER_IP;            }        }        RateTracker tracker=_rateTrackers.get(loadId);        if (tracker==null)        {            RateTracker t;            if (_whitelist.contains(request.getRemoteAddr())) //如果在白名单中,则isRateExceeded一直返回false            {                t = new FixedRateTracker(loadId,type,_maxRequestsPerSec);            }            else            {                t = new RateTracker(loadId,type,_maxRequestsPerSec);            }            tracker=_rateTrackers.putIfAbsent(loadId,t);            if (tracker==null)                tracker=t;            if (type == USER_IP)            {                // USER_IP expiration from _rateTrackers is handled by the _trackerTimeoutQ                synchronized (_trackerTimeoutQ)                {                    _trackerTimeoutQ.schedule(tracker);                }            }            else if (session!=null)                // USER_SESSION expiration from _rateTrackers are handled by the HttpSessionBindingListener                session.setAttribute(__TRACKER,tracker);        }        return tracker;    }


热点排行