画像やリンクが無効になっている可能性もあるのでご了承下さい。
Nginx の DoS 対策はも少ししてからでも良いかな…… なんて甘いことを言っていたら、早速朝方から延々と喰らっていたので対策を行ってみた。
尚、今朝あった小規模な DoS ぽい連続的アクセスは 8 時間ほど続いていたけど、全てのリクエストを捌ききっていたので Nginx 流石だなと関心してしまった。
利用するモジュール
Nginx はモジュールを追加するのであれば、ソースからビルドする必要があるので今回は避けた。Nginx Mainline バージョンの CentOS 7 用 RPM 標準で使用出来る ngx_http_limit_req_module を用いる事にした。もう一つ同時接続数制限を行える ngx_http_limit_conn_module も使えるので、場合によっては併用すると良いだろう。
使い方的な
http ブロックへ limit_req_zone ディレクティブを用いて確保するメモリ量を指定。リクエストレートも設定する。
次の例では 10MB のメモリを lrz という名前で確保し、毎秒 2 リクエストを越えないようにする。必然的にレートを下げていけば、ちょっとしたアクセスに反応するし、上げて行くと鈍くなるから程よい数値を目指すのは怠い。負荷テストツールを併用したり F5 連打しつつ感覚的に調整した。
http {
..
..
limit_req_zone $binary_remote_addr zone=lrz:10m rate=2r/s;
..
..
}
limit_req_zone で確保したメモリを用いて制限を掛けたいホストの server ないし location ディレクティブ以下で limit_req を用いるとリクエスト制限がかかる。
server {
..
..
location / {
limit_req zone=lrz burst=5 nodelay;
limit_req_status 429;
..
}
}
上記例では zone=lrz で示されるメモリを使用し、制限にひっかかれば即時 503 エラーを返す。
limit_req_status を用いれば、返すコードを任意に変更可能。デフォルトは 503 なので変更しないのであれば記述しなくても良いけど、明示しておいた方がいいのかな。
おわりに
まだこのモジュール類だけでも足りている感じだけど、もう少し強力にしたいのであれば fail2ban と連携してやると良いかも知れない。
fail2ban に触れたことも無いのでこう言うのもなんだけど便利そうだから今後の構想の一端になるかもという事で。
コメント