سؤال

أنا النظر في تطوير التطبيق من Google App Engine ، والتي يجب أن لا تحصل على الكثير من حركة المرور.أنا حقا لا تدفع إلى تجاوز حصص مجانية.ومع ذلك, يبدو أنه سيكون من السهل جدا أن يسبب الحرمان من الخدمة الهجوم من خلال إثقال التطبيق وتجاوز الحصص.هل هناك أي وسائل لمنع أو تجعل من الصعب أن تتجاوز حصص مجانية?وأنا أعلم أنني يمكن ، على سبيل المثال ، الحد من عدد الطلبات الواردة من عنوان IP (مما يجعل من الصعب أن يتجاوز وحدة المعالجة المركزية الكوتا) ، ولكن هل هناك أي طريقة لجعل الأمر أكثر صعوبة تجاوز طلبات أو عرض النطاق الترددي الحصص?

هل كانت مفيدة؟

المحلول

هناك المدمج في الأدوات لمنع DoS.إذا كنت تكتب في Google Apps باستخدام جافا ثم يمكنك استخدام service.FloodFilter مرشح.الجزء التالي من التعليمات البرمجية سيتم تنفيذ قبل أي من سيرفلتس القيام به.

package service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;


/**
 * 
 * This filter can protect web server from simple DoS attacks
 * via request flooding.
 * 
 * It can limit a number of simultaneously processing requests
 * from one ip and requests to one page.
 *
 * To use filter add this lines to your web.xml file in a <web-app> section.
 * 
    <filter>
        <filter-name>FloodFilter</filter-name>
        <filter-class>service.FloodFilter</filter-class>
        <init-param>
            <param-name>maxPageRequests</param-name>
            <param-value>50</param-value>
        </init-param>
        <init-param>
            <param-name>maxClientRequests</param-name>
            <param-value>5</param-value>
        </init-param>
        <init-param>
            <param-name>busyPage</param-name>
            <param-value>/busy.html</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>JSP flood filter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
 *  
 *  PARAMETERS
 *  
 *  maxPageRequests:    limits simultaneous requests to every page
 *  maxClientRequests:  limits simultaneous requests from one client (ip)
 *  busyPage:           busy page to send to client if the limit is exceeded
 *                      this page MUST NOT be intercepted by this filter
 *  
 */
public class FloodFilter implements Filter
{
    private Map <String, Integer> pageRequests;
    private Map <String, Integer> clientRequests;

    private ServletContext context;
    private int maxPageRequests = 50;
    private int maxClientRequests = 10;
    private String busyPage = "/busy.html";


    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException
    {
        String page = null;
        String ip = null;

        try {
            if ( request instanceof HttpServletRequest ) {
                // obtaining client ip and page URI without parameters & jsessionid
                HttpServletRequest req = (HttpServletRequest) request;
                page = req.getRequestURI();

                if ( page.indexOf( ';' ) >= 0 )
                    page = page.substring( 0, page.indexOf( ';' ) );

                ip = req.getRemoteAddr();

                // trying & registering request
                if ( !tryRequest( page, ip ) ) {
                    // too many requests in process (from one client or for this page) 
                    context.log( "Flood denied from "+ip+" on page "+page );
                    page = null;
                    // forwarding to busy page
                    context.getRequestDispatcher( busyPage ).forward( request, response );
                    return;
                }
            }

            // requesting next filter or servlet
            chain.doFilter( request, response );
        } finally {
            if ( page != null )
                // unregistering the request
                releaseRequest( page, ip );
        }
    }


    private synchronized boolean tryRequest( String page, String ip )
    {
        // checking page requests
        Integer pNum = pageRequests.get( page );

        if ( pNum == null )
            pNum = 1;
        else {
            if ( pNum > maxPageRequests )
                return false;

            pNum = pNum + 1;
        }

        // checking client requests
        Integer cNum = clientRequests.get( ip );

        if ( cNum == null )
            cNum = 1;
        else {
            if ( cNum > maxClientRequests )
                return false;

            cNum = cNum + 1;
        }

        pageRequests.put( page, pNum );
        clientRequests.put( ip, cNum );

        return true;
    }


    private synchronized void releaseRequest( String page, String ip )
    {
        // removing page request
        Integer pNum = pageRequests.get( page );

        if ( pNum == null ) return;

        if ( pNum <= 1 )
            pageRequests.remove( page );
        else
            pageRequests.put( page, pNum-1 );

        // removing client request
        Integer cNum = clientRequests.get( ip );

        if ( cNum == null ) return;

        if ( cNum <= 1 )
            clientRequests.remove( ip );
        else
            clientRequests.put( ip, cNum-1 );
    }


    public synchronized void init( FilterConfig config ) throws ServletException
    {
        // configuring filter
        this.context = config.getServletContext();
        pageRequests = new HashMap <String,Integer> ();
        clientRequests = new HashMap <String,Integer> ();
        String s = config.getInitParameter( "maxPageRequests" );

        if ( s != null ) 
            maxPageRequests = Integer.parseInt( s );

        s = config.getInitParameter( "maxClientRequests" );

        if ( s != null ) 
            maxClientRequests = Integer.parseInt( s );

        s = config.getInitParameter( "busyPage" );

        if ( s != null ) 
            busyPage = s;
    }


    public synchronized void destroy()
    {
        pageRequests.clear();
        clientRequests.clear();
    }
}

إذا كنت تستخدم بايثون, ثم قد يكون لديك للفة فلتر الخاصة بك.

نصائح أخرى

وانها دائما الممكن استخدام خدمة توفر الحرمان من ميزات الحماية من الخدمة أمام تطبيق App Engine. على سبيل المثال، يوفر كلودفلاري على https://www.cloudflare.com/waf/ ، وهناك آخرون. انها فهمي (تنويه: أنا لم تستخدم خدمة شخصيا). ان هذه الميزات متوفرة على خطة الحرة

وكما انه من السهل إلى حد ما بناء على معدل على أساس memcache الحد تنفيذ في التطبيق الخاص بك نفسه. ها هي الضربة الأولى التي حصلت عليها من جوجل للبحث عن هذا الأسلوب: http://blog.simonwillison.net / آخر / 57956846132 / ratelimitcache . هذه الآلية سليمة، ويمكن أن تكلف اعتبارا استخدام memcache المشتركة قد يكفي ومجانية. وعلاوة على ذلك، يذهب هذا الطريق يضع لكم في السيطرة على المقابض. العيب هو أن التطبيق نفسه يجب التعامل مع طلب HTTP ويقرر السماح أو الرفض، لذلك قد يكون هناك تكلف (أو [مجانا] استنفاد الحصص) للتعامل معها.

والكشف الكامل: أنا أعمل في جوجل على محرك التطبيقات، والتي لا علاقة لها كلودفلاري أو سيمون ويليسون

على جي إن جدار الحماية صدر مؤخرا ، وتهدف إلى استبدال السابق ، محدودة نوعا ما ، دوس خدمة الحماية.

وهو يدعم برنامجي التحديثات من قواعد جدار الحماية عن طريق (بقية) المشرف API: تطبيقات.جدار الحماية.ingressRules التي يمكن أن تكون جنبا إلى جنب مع في التطبيق قطعة من المنطق دوس الكشف كما هو موضح في إجابات أخرى.يمكن أن يكون الفرق أنه بمجرد حكم نشر المخالف الطلبات التي لم تعد تتحمل رسوم كما أنها لا تصل إلى التطبيق بعد الآن, حتى في التطبيق تصفية نفسها ليست هناك حاجة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top