DOS 攻撃対策の Filter といえば、HTTP サーバか、Java だと、Servlet FIlter で、
実装を行っているのが、多い気がします。

Dropwizard を使って書いているアプリケーションでは、どうしたらよいかを調べてみました。1
Dropwizard は HTTP サーバに Jersey を使っているので、その Filter の定義方法になります。


参考サイト


MyWebApplication.java

Jersey は Jetty のライブラリが使えるので、org.eclipse.jetty.servlets.DoSFilter使えます。 2
以下、Application クラスに、DosFilter 定義を追加しました。
正しく理解できてないかもですが、Jerseyは Jettyに依存している認識です。

package mypackage;

import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.jetty.MutableServletContextHandler;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlets.DoSFilter;
import mypackage.MyConfiguration
import javax.servlet.DispatcherType;

import java.util.EnumSet;

/**
 * MyWebApplication
 *
 * @author Kem
 */
public class MyWebApplication extends Application<MyConfiguration> {

    public static void main(String[] args) throws Exception {
        new Festivals4PartyPeopleApp().run(args);
    }

    @Override
    public String getName() {
        return "MyWebApplication";
    }

    @Override
    public void initialize(Bootstrap<MyConfiguration> bootstrap) {
        // Do Nothing....
    }

    @Override
    public void run(MyConfiguration t, Environment e) throws Exception {
        MutableServletContextHandler context = e.getApplicationContext();
        // DOS Attack 対策 Filterの定義
        FilterHolder doSFilterHolder = new FilterHolder(new DoSFilter());
        doSFilterHolder.setName("DoSFilter");
        doSFilterHolder.setInitParameter("maxRequestsPerSec", "3");
        doSFilterHolder.setInitParameter("delayMs", "-1");
        context.addFilter(doSFilterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));

        // 429 ページの設定
        ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
        errorHandler.addErrorPage(429, "/429");
        context.setErrorHandler(errorHandler);
    }
}

  • 説明
    • MutableServletContextHandler に対して、DoSFilter を addFilter します。
    • maxRequestsPerSec Dos アタックとみなす1秒間のリクエスト数を定義します。3 [3] 感覚的には厳しめの3設定。
    • context.addFilter(doSFilterHolder, "/*", EnumSet.of(DispatcherType.REQUEST)); で、REQUEST dispatcher設定しています。 4 [4] servlet 2.4 から、デフォルト REQUEST
    • delayMs を -1 にすると、HTTP エラーコード 429 TOO MANY REQUESTS が飛びます。
    • 429 の エラー時の URLを設定しています。

確認

以下、curlコマンドで、429ページに遷移することが確認できました。

while true; do (sleep 2; curl http://127.0.0.1:18080)& done | grep '429 Too Many Requests'

以上です。

コメント