サイトへのレイヤー7攻撃には、Webサーバーレイヤー(nginx、apacheなど)への攻撃と、通常はプロキシサーバー(nginx、apacheなど)の背後にあるアプリケーションサーバーレイヤー(php-fpm、nodejsなど)への攻撃が含まれます。など)。ネットワークプロトコルの観点からは、どちらもアプリケーション層の攻撃です。しかし、実際的な観点から、これら2つのケースを分離する必要があります。 Webサーバー(nginx、apacheなど)は、原則として、静的ファイル(画像、スタイル、スクリプト)を個別に提供し、動的コンテンツの要求をアプリケーションサーバー(php-fpm、nodejsなど)にプロキシします。静的リクエストとは異なり、動的コンテンツを生成するアプリケーションサーバーは、攻撃者が使用する数桁以上の制限されたシステムリソースを必要とするため、攻撃のターゲットになるのはこれらのリクエストです。
些細なことのように聞こえますが、攻撃から身を守るためには、最初にそれを特定する必要があります。実際、DDoS攻撃はサイトの障害につながる可能性があるだけでなく、開発者やシステム管理者によるミスに関連する他の理由も引き起こす可能性があります。分析の便宜のために、$ request_timeパラメーターをnginxログ形式に追加し(申し訳ありませんが、apacheのオプションはありません)、アプリケーションサーバーへのリクエストを別のファイルに記録する必要があります。
log_format timed '$remote_addr - $remote_user [$time_local] '
'$host:$server_port "$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" ($request_time s.)';
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
access_log /var/log/ngunx/application_access.log timed;
}
別のファイル(統計ログなし)でアプリケーションサーバーへのログを受信し、要求時間が秒単位であるため、攻撃が開始された瞬間、要求の数と応答時間が急激に増加し始めた瞬間をすばやく特定できます。
攻撃を特定したら、防御に進むことができます。
多くの場合、システム管理者は、単一のIPアドレスからの要求の数を制限することによってサイトを保護しようとします。これを行うには、1)nginx limit_req_zoneディレクティブ( ドキュメントを参照)、2)fail2ban、および3)iptablesを使用します。もちろん、これらの方法を使用する必要があります。ただし、この保護方法は10〜15年もの間効果がありませんでした。これには2つの理由があります。
1)7レベルの攻撃中にボットのネットワークによって生成されるトラフィックは、通常のサイト訪問者がアプリケーションサーバー(php-fpm)に対して1つの「重い」要求を持っているため、通常のサイト訪問者のトラフィックよりも量が少ない可能性があります。 、nodejsなど)Webサーバー(nginx、apacheなど)によって送信される静的ファイルをダウンロードするための約100の「軽い」要求があります。 Iptablesは、定量的なインジケーターによってのみトラフィックを制限でき、リクエストを静的と動的に分離することを考慮していないため、このようなリクエストから保護しません。
2)2番目の理由は、ボットネットワークの分散です(最初の文字はDDoS略語のDです)。攻撃には通常、数千のボットのネットワークが関係しています。彼らは平均的なユーザーよりも少ない頻度でリクエストを行うことができます。原則として、攻撃者はサイトを攻撃するときに、limit_req_zoneパラメーターとfail2banパラメーターを経験的に計算します。そして、この保護が機能しないようにボットネットワークを構成します。多くの場合、システム管理者はこれらのパラメータを過小評価し始め、実際のクライアントを無効にしますが、ボットからの保護に関してはあまり効果がありません。
DDoSからサイトを正常に保護するには、コンプレックス内のサーバーで可能なすべての保護手段を使用する必要があります。このトピックに関する以前の投稿 では、WebサーバーレベルでのDDoS保護iptablesの構成方法、およびシステムカーネルのどのパラメーターを最適な値に調整する必要があるか(まず、開いているファイルとソケットの数)に関する資料へのリンクがあります。これは前提条件であり、必要ですが、ボットから保護するための十分条件ではありません。
さらに、ボットの検出に基づいて保護を構築する必要があります。ボットを検出するメカニズムを理解するために必要なすべては、Habréの歴史的な記事で詳細に説明されてい ます。著者 kyprizelによるDDoSと戦うためのnginxモジュールは、同じ著者のtestcookie-nginx-moduleのライブラリに実装されてい ます。
これはCライブラリであり、著者の小さなコミュニティによって開発され続けています。おそらく、すべてのシステム管理者が本番サーバーで見慣れないライブラリをコンパイルする準備ができているわけではありません。ライブラリの作業に追加の変更を加える必要がある場合、これは通常のシステム管理者または開発者の範囲を完全に超えています。幸いなことに、新しい機能があります。nginxサーバーで実行できるLuaスクリプト言語です。 Luaスクリプトエンジンが組み込まれたnginxには、2つの人気のあるビルドがあります。元々はTaobao、次にCloudfareに触発されたopenrestyと、Ubuntuなどの一部のLinuxディストリビューションに含まれているnginx-extrasです。どちらのオプションも同じライブラリを使用するため、どちらを使用しても大きな違いはありません。
ボット保護は、1)JavaScriptコードの実行、2)リダイレクトの作成、および3)Cookieの設定を行うWebクライアントの機能の決定に基づくことができます。これらすべての方法の中で、JavaScriptコードの実行は最も有望ではないことが判明し、コンテンツがバックグラウンド(ajax)リクエストでロードされた場合、JavaScriptコードは実行されず、JavaScriptを使用してページをリロードすると、サイトへの移行の統計(タイトルリファラー以降)。したがって、Cookieを設定するリダイレクトがあり、その値はクライアントで再現できないロジックの対象であり、これらのCookieなしでクライアントがサイトにアクセスすることを許可しません。
私の仕事では、leeyiw / ngx_lua_anticcライブラリに依存していました 、現在開発されていませんが、元のライブラリの作業がすべてに適合していなかったため、apapacy / ngx_lua_anticcフォークの改善を続けました 。
ライブラリ内のクエリカウンターを操作するために、メモリテーブルが使用されます。これは、incrメソッドをサポートし、カウンター値をインクリメントしたり、TTLで値を設定したりするのに便利です。たとえば、次のコードスニペットは、クライアントに特定の名前が設定されたCookieがない場合、単一のIPアドレスからの要求の数を増やします。カウンタがまだ初期化されていない場合は、60秒のTTLで1に初期化されます。リクエスト数256(60秒)を超えた後、クライアントはサイトへのアクセスを許可されません。
local anticc = ngx.shared.nla_anticc
local remote_id = ngx.var.remote_addr
if not cookies[config.cookie_name] then
local count, err = anticc:incr(remote_id, 1)
if not count then
anticc:set(remote_id, 1, 60)
count = 1
end
if count >= 256 then
if count == 256 then
ngx.log(ngx.WARN, "client banned by remote address")
end
ngx.exit(444)
return
end
end
すべてのボットが有害であるわけではありません。たとえば、支払いステータスの変更をサイトに報告する検索ボットや支払いシステムのボットをスキップする必要があります。そのような要求が来る可能性のあるすべてのIPアドレスのリストを作成できればよいでしょう。この場合、「ホワイト」リストを作成できます。
local whitelist = ngx.shared.nla_whitelist
in_whitelist = whitelist:get(ngx.var.remote_addr)
if in_whitelist then
return
end
しかし、これが常に可能であるとは限りません。問題の1つは、Googleボットのアドレスの不確実性です。Googleボットを偽装するすべてのボットをスキップすることは、サイトから保護を削除することと同じです。したがって、resty.execモジュールを使用してhostコマンドを実行します。
local exec = require 'resty.exec'
if ngx.re.find(headers["User-Agent"],config.google_bots , "ioj") then
local prog = exec.new('/tmp/exec.sock')
prog.argv = { 'host', ngx.var.remote_addr }
local res, err = prog()
if res and ngx.re.find(res.stdout, "google") then
ngx.log(ngx.WARN, "ip " .. ngx.var.remote_addr .. " from " .. res.stdout .. " added to whitelist")
whitelist:add(ngx.var.remote_addr, true)
return
end
if res then
ngx.log(ngx.WARN, "ip " .. ngx.var.remote_addr .. " from " .. res.stdout .. "not added to whitelist")
else
ngx.log(ngx.WARN, "lua-resty-exec error: " .. err)
end
end
経験によれば、このような保護戦略により、不公正な競争によく使用される特定の種類の攻撃からサイトを保護できます。攻撃のメカニズムと保護方法を理解することは、fail2banに対する防御の試みが失敗した場合に多くの時間を節約するのに役立ちます。サードパーティの保護(Cloudfareなど)を使用する場合は、保護パラメーターをより慎重に選択してください。
apapacy@gmail.com2021年
5月9日