Frage

Ich überlege mir, die Entwicklung einer app für die Google App Engine, die sollte nicht zu viel Verkehr.Ich würde wirklich lieber nicht zahlen übersteigen die freien Kontingente.Jedoch, wie es scheint, es wäre ganz einfach, einen denial-of-service-Angriff durch eine überbelastung der app und die überschreitung der Quoten.Gibt es irgendwelche Methoden zu verhindern oder zu erschweren überschreiten, die freien Kontingente?Ich weiß, dass ich könnte, zum Beispiel, die Anzahl der Anfragen von einer IP (wodurch es schwieriger wird, überschreitet die CPU-quota), aber gibt es eine Möglichkeit, es schwerer zu machen, übersteigt die Anforderungen oder die Bandbreite der Quoten?

War es hilfreich?

Lösung

Es gibt keine integrierten Tools DoS zu verhindern. Wenn Sie Google Apps schreiben, mit Java dann können Sie den service.FloodFilter Filter verwenden. Das folgende Stück Code wird ausgeführt, bevor irgendwelche Ihrer Servlets tun.

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();
    }
}

Wenn Sie Python verwenden, dann können Sie Ihre eigenen Filter rollen müssen.

Andere Tipps

Ich bin mir nicht sicher, ob es möglich ist, aber die App Engine FAQs zeigen an, dass, wenn Sie es ein DoS-Angriff zeigen dann werden sie alle Gebühren im Zusammenhang mit dem Angriff zurück.

Es scheint, dass sie für eine IP-Adresse basierte Filter zur Verfügung haben beide Python und Java jetzt (ich weiß, das ist ein alter Thread, aber es kommt immer noch hoch oben auf einer Google-Suche).

https://developers.google.com/appengine/docs/python/ config / dos

Es ist immer möglich, einen Dienst zu verwenden, die Denial-of-Service-Schutz-Funktionen vor einer App Engine-Anwendung zur Verfügung stellt. Zum Beispiel bietet Cloudflare einen angesehenen Service https://www.cloudflare.com/waf/ , und es gibt andere. Es ist mein Verständnis (Disclaimer: Ich den Service nicht persönlich in Anspruch genommen habe)., Dass diese Funktionen auf dem freien Plan verfügbar sind

Es ist auch ziemlich einfach, eine memcache Basis Rate Limiting Umsetzung in der Anwendung selbst zu konstruieren. Hier ist der erste Hit ich von einer Google-Suche nach dieser Methode bekam: http://blog.simonwillison.net / post / 57956846132 / ratelimitcache . Dieser Mechanismus ist solide und kann wirksam als gemeinsame memcache Nutzung kosten kann genügen und ist kostenlos. Darüber hinaus diesen Weg gehen gibt Ihnen die Kontrolle der Knöpfe. Der Nachteil ist, dass die Anwendung selbst muss die HTTP-Anforderung verarbeiten und entscheiden, es zu erlauben oder zu verweigern, so kann es (oder [kostenlos] Quote Erschöpfung) zu behandeln kosten werden.

Full Disclosure. Ich arbeite bei Google auf App Engine und haben keine Verbindung mit Cloudflare oder Simon Willison

Die GAE-firewall kürzlich veröffentlicht wurde, ersetzen den bisherigen, eher begrenzt, DoS Protection Service.

Es unterstützt die programmatische updates der firewall-Regeln über die (REST) - Admin-API: apps.firewall.ingressRules das könnte kombiniert werden mit einem in-app-Logik für die DoS-Erkennung, wie beschrieben in den anderen Antworten.Der Unterschied wäre, dass, sobald die Regel angewandt werden, die problematische Anforderungen nicht mehr Gebühren anfallen, wenn Sie nicht erreichen die app nicht mehr, so die in-app-Filterung selbst ist nicht erforderlich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top