「DDoS攻撃対策 トリロジー」最終回: HTTP(S)フラッド攻撃の対策

今回はこの「DDoS攻撃対策 トリロジー」最終回だ。正直、このシリーズは人気がないよう見った。しかし、DDoS攻撃は、今日のあらゆるインターネットサービスにとって主なセキュリティ上の脅威であり、緊急時に対応できるように、事前に何を想定しているかを知っておくことが重要だ。

好かれようが好かれまいが、今回は最終回だった。将来的には、私は多分DDoS攻撃に関連する経験記事をこれ以上書くべきではないだ。それらの多くは、商業秘密だからだ。

今回の記事は、「HTTP(S) フラッド攻撃」の対策ですが、しかし今回は前回の「一般的なDDoS攻撃の対策」よりほとんど簡単だった。まず「HTTP(S) フラッド攻撃」を対策ため、必要のお金は前回より安くだ、そして、規模はともかく、方法は同じいだ。つまり「HTTP(S) フラッド攻撃」の防衛理念は全部同じだ。

同じに、今回の記事は大体は防衛の方法そして理念を教えれだけだ、だから、それが取得してすぐに使用することができるコードやプログラムを提供してない。

では、そろそろ始めましょう。

------------------------------------------

# 1. HTTP(S)フラッド攻撃対策基本概要

HTTP(S)フラッド攻撃の対策理念と一般的なDDoS攻撃は同じいに「防御コストには攻撃コストより低くされる。」だった。

しかし、と一般的なDDoS攻撃に違うのば、その理念は誰でもほとんど実現できる。

HTTP(S)フラッド攻撃を防衛は全部3種類の理論方法がある。

それは：

**1. 速度制限系（アクセス頻度の制限）**
**2. マンマシン検証系**
**3. より高い代償を支払う系**

Webサービスの種類にもよりますが、1つ種類の方法のみに適したサービスもあれば、3つ種類の方法で同時に利用できるサービスもあります。 そのため、Webサービスの種類に応じてメソッドを使い分ける必要がある。

でも、HTTP(S)フラッド攻撃を防衛する前に、様々の準備が必要だ。例えば、**インフラ構造**。

![Snipaste_2020-10-04_18-52-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/b3edd519-b037-42e9-36bd-6ff166d51a9d.png)

まず、私はソースサーバーのフロントエンドに専用のリバースプロキシサーバーを追加することを強くお勧めしまう。

これには2つの利点がある。

まず、**リバースプロキシサーバーにウェブアプリケーションファイアウォール（WAF）の機能を導入して、ソースサーバに十分な処理リソースを持たせるを本職なことにするができる。それに、こんな構築すれば、WAFも十分な処理リソースはHTTP(S)フラッド攻撃を防衛するた。**特にHTTPSフラッド攻撃、SSLのオフロードには、非常に大量のCPU処理リソースが必要だ。だからこそ、もしできれば、独立のリバースプロキシサーバーをつかってくれ。

そして、これにより、**後でパフォーマンスを簡単にスケーリングできる。**もし大き規模なHTTP(S)フラッド攻撃、攻撃リクエストの処理は全部リバースプロキシサーバーで対処するが、性能が足りないとき、我々はただの簡単にリバースプロキシサーバーを増加するでいい。

HTTPSフラッド攻撃にとって、一般的なはそんな方法を処理するですが、しかし特殊状況もある。特例状況例え、こ回の攻撃が、単一の攻撃元と多数のプロキシサーバーによって開始されるHTTPSフラッド攻撃である場合、もし攻撃のパケットメッセージの分析方法がわかるなら、攻撃されたデータパケットの特性値を分析し、ファイアウォールを直接使用してブロックすることができる。 これにより、SSLオフロード操作を実行する必要がなくなり、CPUリソースを節約した。

------------------------------------------

# 2. HTTP(S)フラッド攻撃対策解明

HTTP(S)フラッド攻撃対策は全部3種類の理論方法がある。それぞれは自分の適切な状況がある。では、各メソッドがどのようなシナリオに適しているのかを見てみよう。

------------------------------------------

## 2.1 速度制限（アクセス頻度の制限）

通常はソースサーバーを保護するためにアクセス速度の制限を設定している。 一般的な訪問者が1秒間に一度に多くのリクエストを送らないのも事実だ。

通常、アクセス速度を制限するには、nginxのlimit_reqコマンドを使用する。

例：

    http {
     limit_req_zone $binary_remote_addr zone=myreqzone:10m
     limit_req_log_level warn;

     server {
        ## 1つのIPにつき10接続に制限
        ## 通常、ブラウザは各ホストへの接続を2つまたは3つ開きます。
        ## トリガされた場合、503エラーを返します。
        ## 「nodelay」とは、ウォームアップをせずにまっすぐ上に上がることを意味します。
        limit_req zone=myreqzone burst=10 nodelay;
     }
    }

**同時に、アクセス速度の制限も、APIサーバーの唯一の保護方法だ。リクエストするAPI自体もプログラムであるため、マンマシン検証普通は無理だ。**

**ただし、アクセス頻度の制限は大体２つの問題がある。**

**まずはもし攻撃者はたくさんのプロキシサーバーを使いれば、アクセス頻度制限の効果はほとんどないだ。Nginxのアクセス頻度制限機能は基本にIPを使ってそれに判断するが、たくさんのプロキシサーバーを使いれば、その制限は無効だった。**

**そして、複数のリバースプロキシサーバーを利用してのばいは、単点のリバースプロキシサーバーのIP制限リストは自分だけ使う、であり、そのリストは他のサーバーとの同期はできない。そのせいで、アクセス速度制限の効果が弱くなる。**

ですから、私の方法は、「Nginx-Lua」を使って、自分でアクセス頻度制限機能を構築する。まず、IPアドレスだけに頼るのではなく、クライアントIDを導入してを使ってに判断する。そして、アクセス頻度制限のクライアントリストは「Redis」を使って、全サーバークラスターで同期する。

------------------------------------------

## 2.2 マンマシン検証

![Snipaste_2020-10-04_22-21-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/d6a248df-0995-1045-222f-d371c11a90f4.png)

上の図は、マンマシン検証のフローチャートだ。

DDoS攻撃は大体人間以外のアクセスするから、だから基本理論は**「このリクエストが本当に人がな？ここでチェックしよ。」**。

本当な人をサイトのアクセスは、きっとブラウザを使っている。だから、このリクエストは本当にブラウザからかどうか、チェックすれば直ぐわかる。

簡単に言えば、こればブラウザ検証。検証コード以外の方法はすべてブラウザ検証だった。ブラウザの特性を利用して、それに本当かどうかには検証する。

どの方法を使用しても、全方法のロジックフローは図のようになる。

どんな方法あるのか、みってみよう。

------------------------------------------

#### 2.2.1 Set-Cookie検証

まずは、Set-Cookie検証法。

**この方法はブラウザのCookie機能を利用して、そのままにブラウザ検証した。**

ご存知のとおり、通常のブラウザはCookieにアクセスできる。そのため、クライアントが正常に戻るかどうかを確認するためにWAFはCookie情報を書き込もうとする。

じゃ、Nginxでその機能を実現するは、まず最初の簡単の例を見ろう：

    server{
        ......
        if ($cookie_check != "imnotrobot"){
        add_header Set-Cookie "check=imnotrobot";
        rewrite .* "$scheme://$host$uri" redirect;
        }
        ......
    }

これでは、簡単なCookie検証機能が完成した。

しかし、そのCookieの内容は固定されており、誰が見ても同じだ。これは簡単に逃げられてしまうので、いくつかの変数を追加するが必要だ：

    server{
        ......
        if ($cookie_check != "imnotrobot$remote_addr"){
        add_header Set-Cookie "check=imnotrobot$remote_addr";
        rewrite .* "$scheme://$host$uri" redirect;
        }
        ......
    }

これでは、Cookieの内容はクライアントのIPがある。

しかしそれでも、もし攻撃者本気に見れば、すぐに対策がある。ですから、一番いいの方法はそのCookieの内容をハッシュ操作にはソルト値を使用する。だけどう、Nginxの構成ファイルでそのハッシュ操作関係の関数がないですが、どうしましょう？

ここで、「Nginx Lua」をもう一度使って：

    server{
        ......
        rewrite_by_lua '
                local cookie_info = ngx.md5("This is salt value" .. ngx.var.remote_addr)
                if (ngx.var.cookie_check ~= cookie_info) then
                    ngx.header["Set-Cookie"] = "check=" .. cookie_info
                    return ngx.redirect(ngx.var.scheme .. "://" .. ngx.var.host .. ngx.var.uri)
                end
        ';
        ......
    }

これでは、ハッシュ操作にはソルト値を使用しているのSet-Cookie検証機能が完全に完成した。

ただし、今までのHTTP(S)フラッド攻撃プログラムは４割このSet-Cookie検証法に対策していった。だから、この方法はもう絶対安全したを言われない。

------------------------------------------

#### 2.2.2 JavaScript検証

Set-Cookie検証法ダメなら、じゃJavaScript検証法がどうっか？

ご存知のとおり、**通常のブラウザはJavaScriptを実行するができる。**そのため、Set-Cookie法は使わないて、JavaScriptをCookie情報を設定する。

    server{
        ......
        rewrite_by_lua '
                local cookie_info = ngx.md5("This is salt value" .. ngx.var.remote_addr)
                local jssetcookie = "<script>document.cookie=\"check=" .. cookie_info .. "\";location.reload();</script>"
                if (ngx.var.cookie_check ~= cookie_info) then
		            ngx.print(jssetcookie)
		            ngx.exit(200)
                end
        ';
        ......
    }

これでは、JavaScriptバージョンのSet-Cookie検証機能が完全に完成した。

ただし、JavaScriptはできるなことはたくさんがある。Set-Cookieだけじゃなく、例えば「302ジャンプ検証」も一つの検証方法だ。ところで、CloudFlareのJavaScript検証方法は「文字列コンテンツの文字数の計算」。だから、どんな方法が使うのか、自分に創造しよう。

でも、JavaScript検証方法は攻撃者によってクラックされってもちろんできる。

------------------------------------------

#### 2.2.3 検証コード

これは大技だ。

Set-Cookie検証法とJavaScript検証方法はただのブラウザを検証するだけ、しかし、**検証コードは直接に本当な人かどうかこれをチェックする。**


だけど、簡単な検証コードは、例え画像検証コード。画像認識機能は簡単的に画像検証コードをクラックする。

**「Google reCAPTCHA」ような、解読しにくい検証コードの使用をお勧めする。**

これからは、攻撃者の敵人はGoogleだった、私たちには関係ないだ。

------------------------------------------

## 2.3 攻撃者はより高い代償を支払う

「攻撃者はより高い代償を支払う」方法は、先の「マンマシン検証」だけに基づく進化的な方法です。

この方法は、**もはや本当な人かどうかは関係ない、どうせ代償を払うんだろ。**

以前、ある新しい検証コードサビース「Coinhive Captcha」がある。この「Coinhive Captcha」検証コードは暗号通貨「Monero」のマイニング計算を使用した検証コードサービスだ。この検証コードは本気に言えば本当な人かどうかは関係ない、代償を払っだったでいい。

これでは、攻撃側も大惨事になってしまう。「Coinhive Captcha」検証コードを実行すると、攻撃を継続することができず、すべてのCPUリソースを使い切ってしまう。 しかし、「Coinhive Captcha」検証コードを実行しないと攻撃を継続することもできない。だから、当時のDDoS攻撃に対しては、このCAPTCHAを使用することが非常に有効でした。

残念ながら、「Coinhive」は運営を停止した。

しかし、私たちはこのアイデアから学び、同様のサービスを自分たちで開発することができるんだ。もっと簡単言えば、支払い用のQRコードを直接入力して、支払いなしでアクセスを禁止することもできるんだ。

------------------------------------------

# 3. 結論

HTTP(S)フラッド攻撃の方法は以上だ。

できれば、今でも一般の方には「CloudFlare」の使用をお勧めする。検証コード機能は簡単にクリックしてすぐに有効する。

最後に、最も重要な点を説明する必要がある。DDoS攻撃に対する防御力がどれほど強力であっても、Webサービス自体のパフォーマンスが高くなければ、DDoS攻撃に対する防御の意味が全くないんだ。

以上。