🙌

Cloudflare Managed Challenge の実装サンプルとTurnstileの違い

2023/05/23に公開

以前こちらの記事でTurnstileについてまとめました。Turnstileとは最近よく見る以下です。

これにより90%以上CAPTCHAの出力を減らせたことをCloudflareは発表しています。

これと非常に似た動作を行うものにManaged Challengeというものがあります。この記事ではその違いと実装サンプルをまとめます。

Managed Challenge とは

Managed ChallengeとはCloudflareのWAFにおける推奨設定項目の一つで、リクエストの特性に応じて、自動で複数のクライアントを識別する仕組みを選択し、リクエスト元がBotかどうかを判別します。利用されるアルゴリズムのすべては公開していませんが、主なものは以下になります。

・JSチャレンジ
クライアントブラウザに小さなJavaScriptを実行させてその結果をもとに、
リクエスト元がブラウザかどうかを判別します。
GoogleのPicassoアルゴリズムなどを用いており、こちらに概要をまとめています。
・インタラクティブチャレンジ
ユーザーにボタンを押させるなど人間操作を要求します。
例のこれです。

・Private Access Token
この記事でまとめていますが、Google,AppleとCloudflareが共同開発した、iOS向けセキュリティです。トークンは1年の有効期限を持ち、非常に良いユーザー体験を実現できます。iOS16以上で利用可能です。

Turnstileとの違いについて

このManaged ChallengeとTurnstileとの違いは、技術的にはほぼ同一ですが、リクエスト元クライアントの判別を行う場所が異なります。

Turnstileはオリジンにスクリプトを組み込みCloudflare APIを呼び出す動作をします。オリジンの負荷管理やスクリプトの制御はユーザー側が行う必要がありますが、その画面などを全てカスタマイズ可能です。

一方Managed Challengeはクラウドフレア側で表示されるため、とても手軽に設定できる反面、画面のカスタマイズには制限があります(HTMLベースの差し替えは可能ですが画面遷移などは固定化されます)またTurnstileは100万リクエスト/月までは無償で利用可能ですが(それ以上はEnterpriseプランが必要)、Managed ChallengeであればProプラン以上で利用できます。

やってみる

実装はとてもシンプルです。まずは保護すべきオリジンをDNS Proxyモードで設定してください。
その後マネージメントコンソールのSecurityWAFをクリックします。

Create firewall ruleを押します。

imageresize.harunobukameda.labrat.onlineを保護したい場合以下のように設定します。

適応したいルールを設定してDeploy firewall ruleを押します。

その際Test ruleボタンを押すと過去72時間以内のリクエストのうちどれぐらいの割合にこのルールが適応されるかがグラフで表示されます。

設定は以上です。アクセスを行うと一瞬以下の画面が表示されます。

通常ブラウザであれば問題なくオリジンが表示されるはずです。
例えばHeaderを消してアクセスを行うと以下のようにインタラクティブチャレンジが表示されています。これはCloudflare内部ロジックとしてHeaderが空欄のリクエストをまずはBotとして認識し、人間であるか?の確認を求めるためです。

JavaScriptからアクセスさせると以下のようなエラーが戻ります。これはJSチャレンジ(クライアントブラウザでJSを実行させた結果をもって、リクエスト元がブラウザかどうかを判別する仕組み)が動作しなかったためエラーが戻っています。

<!DOCTYPE html>
<html lang="en-US">
<head>
    <title>Just a moment...</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="robots" content="noindex,nofollow">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="/cdn-cgi/styles/challenges.css" rel="stylesheet">
    

</head>
<body class="no-js">
    <div class="main-wrapper" role="main">
    <div class="main-content">
        <noscript>
            <div id="challenge-error-title">
                <div class="h2">
                    <span class="icon-wrapper">
                        <div class="heading-icon warning-icon"></div>
                    </span>
                    <span id="challenge-error-text">
                        Enable JavaScript and cookies to continue
                    </span>
                </div>
            </div>
        </noscript>
        <div id="trk_jschal_js" style="display:none;background-image:url('/cdn-cgi/images/trace/managed/nojs/transparent.gif?ray=7cbbe084d151f681')"></div>
        <form id="challenge-form" action="/?__cf_chl_f_tk=pGdff81krFYWL0IpFyo5ru6g71HY9vHro660CPDAOGQ-1684829998-0-gaNycGzNCyU" method="POST" enctype="application/x-www-form-urlencoded">
            <input type="hidden" name="md" value="VvOW1boj_kGCtygh_S1Rkp2KNgf1HVYaEg0YtRc2F.s-1684829998-0-ARw-Pbpgoet31zGtUvf2A34WGSsOeqo33R9-AgqXdgbe9QJuPyvZ2B9fHR69915TYJDZS3uXqYon1KcO7ykE2tp82vwzRHVncBcHDK-pNoPdZM7bvwOPwwRTMcT6mhTpIn967R78wvtjPDZN3mN_ZWvvVR7lHrv4ALpgYYWTfV9og-HafQmGmkDE5A2h2OyLIO_lqocrsY5_aG6zBmVazL1AnML09EDC_Qixfg6k0zsFxWCvuZE1NOlk4-vCXgfYYbPt6i6JCC_RlYZRl2R9yVHqm_DEVw7NgMe7aGZjdDzyFYS3f3eqTuLNOmdLiQcY6sHXFwsMQDpcXWZejLD0qd6bA4du1u8yKru5uWpPnaOmgVHsCz9PMkOi5X9lVPG0taVWKZqAegLu00IGISP3FrXNDfghcmLAjUgLeXE0VbH-eU32y8MGm0owN7GzWbwH5nGJG4ubokMaxzuOUTb72H7ckX0n1z1nXd1Xifjnz47C2G9asvvRvDQY3d9boF3CrMoqWQNdr57p4CwpEpob1b3LVfeXuWLnVa4Adb7Cpjn7yBus5_Txtc2L7zOCKYdA90Wue9lz8apFVYMvYUZbgv40aVF5uTi3XNA2019irC_1N3GhGHYCqKMOKacSPh9jQba78KKZ3BF2niicqPAdK6FEYaDLZ73my_LFQodBWamr60L-7MO34T2Z56LknGZXb-t4Mszg15SCP2wb9uY9poxp05QyzdVf31I983ZpGAs0_4xXG6gq-XWSZS4upoPCDgggYyeJDk1KBzLBf1pjEbMKVzsGssWoTLyN-hQgEfsx_-DJY7E6ZPuO4By2XzzbG_CkrmTzJFZ0QKyqHZwwfI-wamV60nt0fA-I3HAfkmetooWWSkpHofMbbTlLsPxeWRqueAX8ryiazkvUfdQ1DJxwz9e6ZkB-4LssUGV-OgK755MvvdovS2djINUjLdKNchThGhScgh5ZQZH8FN_MIYuLRv2aDMt5qXKaxrNccvNJ-7kOlWUu7eeMW0hFEUDqIGnzCIkHx3LVCsyjQ1NexuTdGZXfTqWA0L2Hm85uWNgluQIZvnIduy0uLqy-VVB2zJcMxvurwuZlpgtLkQ9NTS08M5UnkFjEv5xbUEB6jSnW6lAoJhEwCVpEgteuS3HoDtvhZH650jWLAarHHWuJzrpWsqyeSDFapD8xmV4EJBeyN7q4wCgKI_2iHwgH_r6AmMf1BcqLfAZ4aAWGAXpIophybRVni6wziFrW-7iyfEwHFtEqXl2P1MTP_UcYjOaWYIvKyq7-CqDd_soIld7Pg13IdKdht4Y84v2-hjIvxJI_IvOpk_lWWaMDEOS0sAgH2Q9kSMsjwmdW-xTIa_ci7traMQcFpbKEuaS5ztMDRdSXWM1L82mR_TrepFOw3drD_OpQB3UJ1iMAWyhabU8XvJEaEkGFphHYZKOBjtAdOLaCsfTE-TmUGz0RrgVGuAOyvHrGnunIAxzXMnIBi0Xna-ktfgZep1zYfSFRu8owScRIew2jbaRrnZli_MqUlh-NYUuKNiRBvGgUnxQ_xj_csFgz1M6Pfop_x8fhpwKMJPshEuWlNFoOzrTrgwtsS1K0m8HDto7UAzMkpy2Z_lrbYM_I7_ZruLmbbZSatPpm7390CwlZDdIjDDpa6AYSREgQ8JgwMTOmxMEPk_--gRfVDT-jwMr3AdiahMKjLZcAc2_OePyNSsNRSiIkEeTmgvA3rFO6COr6W76zUb9_8NKFMUssBbEF_aI11eOUIJoRWs81HGPD6SPZWN5Z82gt11zbxyW2-CsfH5Jg1V0mwpR5UsPBAH8o4VEYfdMJsRzB410cGQdNSj1_OKQqeeBEfcbh9LNIX_U5HZhle8dEGQkoXapTLv2qtv16vKj9m73PnZRUx04s4MVzizsei5s6oloteg3aruTw5SYYgK2ckKnJqRaSXSJ48V5BetY4GgdTk0P6Xr1w0FNO4VYTRGYJOiIANHy5UTRVvJlEFw2CLRuIQV8mpWyqEqB6Tppz-glWocMwO9CctbZ8Fb_iVUoCa7KFBbalGbOPPEGa-yImErjPwjeFbVceZ3AdAKms8kjdvI2INX88PCEM48Y_YOgwjBWWIHadvbAxdKrj6JOqoPKi1pdEfB5dDPEUguB6vw_1R1xMDCoZQbkV0QEA7l4P75Ha-h8cB48HuOkVQAQxN8UVh8jSC7rpVGXkdO696CwQF5ZNKL0mjQlQFcwjTM-06AfkeXod3Kg-vlmJkpoM35m6aB4c8mGf8DGPeYDWAnYyDc2jeFT1XzbwFQ8Gr0v4fkrBOiL7ysO2yGOXK70f02qmWH9jrUT_kX4PhSQap3qjMLuv_3P_7Jd9LRNOH35ewEL5_ZcduJf6AbcrcAYZOLmm7dBOG_eF6z0x2AH5gZZyrxWhEgQBKiIWnZlVIlOPbFb1AkQBrezunZ38ZVX0oTjZ-yK_gHOnf42uBHoz7VLRz0ppBbrPNisk6oRFG3AAtYPqjxLvMyNeiEowtNqb_RCDH0IrjUMLGaypX5OWgN_vdaPZiswy7tVfQRKKmZfgtT06_Ol1d8s2B1q0keBDIxviT_fLB9u2a9-AssqD17n3ZSmQj98fdhSroMPTHUlSKjc4Zta_bXLOUwXNdRbVK_naqey-rbgMgi2hdUdVGqA7BoC9dZLEgGtO3kaj7VhMC9AeHD23u1m9Bvmy5mqx2Ytgbf_U0YLKnyfSmPXU2EFPfct-seXAWbldSEm94ZVhYJscNOKNiI4lBzFtrWb9qxEG-1EPpJpIG_DMJmPLhIik7C1y">
        </form>
    </div>
</div>
<script>
    (function(){
        window._cf_chl_opt={
            cvId: '2',
            cZone: 'imageresize.harunobukameda.labrat.online',
            cType: 'managed',
            cNounce: '79753',
            cRay: '7cbbe084d151f681',
            cHash: '94f49977ab8303e',
            cUPMDTk: "\/?__cf_chl_tk=pGdff81krFYWL0IpFyo5ru6g71HY9vHro660CPDAOGQ-1684829998-0-gaNycGzNCyU",
            cFPWv: 'g',
            cTTimeMs: '1000',
            cMTimeMs: '0',
            cTplV: 5,
            cTplB: 'cf',
            cK: "",
            cRq: {
                ru: 'aHR0cHM6Ly9pbWFnZXJlc2l6ZS5oYXJ1bm9idWthbWVkYS5sYWJyYXQub25saW5lLw==',
                ra: 'Tk9fVUE=',
                rm: 'R0VU',
                d: 'CeNMYKBj/gvgKuqc6yn3H+M8+jCDiVv707HJ1iU8dLupSoMI+faLi9XLYtKFJULFzjD5A5cN9iJNpndQMtuReWqLxlfa/d35rX19xlTTV4k2rdpOttpPTrejX7fCZN6pDaDTuBEXiWbZ6ZQYibj3e0BLyQ/D/3fkrXzkwUkDTTaz+ULKZX8ab+CAyWA9R/O55CkYrE7KHB0RmBYWJiw3SIIPEAqW7IAFcYMG3rZbeaT3w8reEIC4K0IitJ6DfKVy29aT1Wn104nf5zCihY2zT6qQFECQKJpyXLNHUZRDyTuSqDmS/oIMM3WDvUKeEdqxWYHM7o5ONNIz1Z4zJCv4enTFW+kIp8OzdNR6ynxzbSjlfE0zGOZMIE+YuCSxmjX0+aQH5b2kTbR/xkmaytvAYwog9E2PCgqj6G4hEqCUCAXkT72P9n7dgoLPFfxu4wF4EtCvifp6qmqiqK8RoVaCkFN30MToa7cXsFM9K77JBuZ4xbIrRnSTFoppOjgk6J8m/yT6uScNUJ8uYv3gH4yfUyu5a0L/Ac8CbxIwBm+yrdtr+9IdqWBCzzdXP55PWazvzGjkKzl/AZe5e54k3KurMwxjvFWihHDHQ18yUp//hPY=',
                t: 'MTY4NDgyOTk5OC44NjMwMDA=',
                m: 'NiYZ92vAqoKJ06/vhWT5wbET3LIBTmsbHcmSa6S1fMs=',
                i1: 'cmhb6JHTXZv/MFuGSRecIQ==',
                i2: 'bK3F4CYn2H/qhfwAoXu9zQ==',
                zh: 'cSItkUQZGfbuZ0HOcrN0eJNkw2APqbjU2qkPOaTUK5E=',
                uh: 'DV4j3Tmrbi5Rs1q3ahwVS6SgbPbI7np5884QO1u1Cgg=',
                hh: 'BpD3kmE+DGappqGFgbe0S74ZMbNAVX40mgssFic3pGg=',
            }
        };
        var trkjs = document.createElement('img');
        trkjs.setAttribute('src', '/cdn-cgi/images/trace/managed/js/transparent.gif?ray=7cbbe084d151f681');
        trkjs.setAttribute('alt', '');
        trkjs.setAttribute('style', 'display: none');
        document.body.appendChild(trkjs);
        var cpo = document.createElement('script');
        cpo.src = '/cdn-cgi/challenge-platform/h/g/orchestrate/managed/v1?ray=7cbbe084d151f681';
        window._cf_chl_opt.cOgUHash = location.hash === '' && location.href.indexOf('#') !== -1 ? '#' : location.hash;
        window._cf_chl_opt.cOgUQuery = location.search === '' && location.href.slice(0, location.href.length - window._cf_chl_opt.cOgUHash.length).indexOf('?') !== -1 ? '?' : location.search;
        if (window.history && window.history.replaceState) {
            var ogU = location.pathname + window._cf_chl_opt.cOgUQuery + window._cf_chl_opt.cOgUHash;
            history.replaceState(null, null, "\/?__cf_chl_rt_tk=pGdff81krFYWL0IpFyo5ru6g71HY9vHro660CPDAOGQ-1684829998-0-gaNycGzNCyU" + window._cf_chl_opt.cOgUHash);
            cpo.onload = function() {
                history.replaceState(null, null, ogU);
            };
        }
        document.getElementsByTagName('head')[0].appendChild(cpo);
    }());
</script>


</body>
</html>

動きは気になる方は、
https://imageresize.harunobukameda.labrat.online/
にアクセスしてみて下さい。(2023/05/24 23:59:59までは残しておきます)

Discussion