セキュアな「x-ch-no-bypass」トークンを使用して、DNSバイパス攻撃を防御する。

はじめに

このガイドでは、DNSバイパス攻撃から防御する方法の概要と具体例を説明します。CrowdHandlerのどの連携機能においても、x-ch-no-bypassヘッダーの実装は必須ではありませんが、実装することでユーザー認証の追加の層が確保されるため、推奨されます。

この記事は、どのような統合タイプに関連していますか?

アカマイ

Cloudflare

CloudFront

DNS

「DNSバイパス攻撃」とは、具体的にどのようなものを指すのでしょうか?

お好みのCDNにCrowdHandlerを統合することで、CrowdHandlerによるチェックを回避することは困難になりますが、ウェブインフラに関連するネットワーク情報を突き止めることができる熟練したユーザーであれば、CDNのエンドポイントを迂回してトラフィックを送り、CrowdHandlerの統合を含むCDNが提供するすべての保護機能を回避できる可能性があります。

仕組み

設定が完了すると、CrowdHandler 連携機能は、アプリケーションに転送されるすべてのリクエストに「x-ch-no-bypass」という名前のヘッダーを追加します。このヘッダーの値には、セキュリティ保護されたバイパス防止トークンが設定されます。最小限のコードで、Web アプリケーションを構成し、リクエストにこのヘッダーとトークンが含まれているかどうかを確認できるようにすることで、CrowdHandler による検証を経たユーザーのみがアプリケーションにアクセスできるようにすることができます。

トークンはどこで確認できますか?

DNS連携機能をご利用の場合は、トークンはCrowdHandler管理コンソールの、保護対象となるWebアプリケーションのドメイン設定画面で確認できます。トークンの値は、「No-Bypass Token」フィールドに保存されています。

その他のCDN(Akamai、Cloudflare、CloudFront)との連携については、それぞれのインストールガイドに、バイパス防止トークンの設定方法が記載されています。

統合事例

x-ch-no-bypass リクエストヘッダーの存在と値の確認は、ほとんどのプログラミング言語や Web サーバーで簡単に実行できます。以下に、広く使われているさまざまな言語や Web サーバーにおける実装例をいくつか示します。

Apache

RewriteEngine On

# block if request header x-ch-no-bypass value isn't matched
RewriteCond %{HTTP:x-ch-no-bypass} !^(YOURTOKENVALUE)$
RewriteRule ^ - [F]

Nginx

location / {

    if ($http_x_ch_no_bypass != "YOURTOKENVALUE") {
        return 403;
    }

    proxy_pass http://app:3000/;
}

Express.js

app.get('/', (req, res) => {
    if (req.header('x-ch-no-bypass') !== "YOURTOKENVALUE") {
        res.status(403).send("Sorry! You can't see that.")
    }
    res.sendFile(__dirname + "/views/index.html");
})

PHP

function getRequestHeaders() {
    $headers = array();
    foreach($_SERVER as $key => $value) {
        if (substr($key, 0, 5) <> 'HTTP_') {
            continue;
        }

        $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
        $headers[$header] = $value;
    }
    return $headers;
}

$headers = getRequestHeaders();

if($headers['X-Ch-No-Bypass'] != "YOURTOKENVALUE") {
    header("HTTP/1.1 403 Forbidden" );
    exit;
}

Python (Django)

from django.http import HttpResponseForbidden
from django.http import HttpResponse

def index(request):
    chBypassKey = request.META.get('HTTP_X_CH_NO_BYPASS')
    if (chBypassKey) != "YOURTOKENVALUE" :
        return HttpResponseForbidden()
    else :
        return HttpResponse("Hello world!")