Nginx で IP アドレスを元にアクセス制限を行う方法

本記事は最終更新日より 1 年以上経過しております。
スポンサーリンク

 ここ数ヶ月は特にこれと言った問題も起こらず平和な運用をしていたが、アクセス数が増加するにつれてどこからかスパムコメントが目立つようになってきた。
 これといったアクセス制御は撤廃して放置していた部分もあったので、このタイミングでちょっとしつこいスパムコメントの発信源を制限する事にした。

制限方法

 Apache 時代なら Order ディレクティブで deny, allow なんて書きつつ deny xxx.xxx.xxx.xxx/yy と CIDR で指定した IP レンジをまるっとアクセス拒否する事が出来た。
 同じ様な事を Nginx でやろうとすると allow や deny ディレクティブでは上手く行えない。
 そこで今回用いるのは geo ディレクティブと if 文と return である。

アクセス制限をする

 次のような記述を http ブロック内に行う。その為、他にもバーチャルホストがあって同じ処理を行っている場合には、影響を与えないようなユニークな変数名で定義して上げた方が良いかもしれない。
 アクセスしてきたホストの IP アドレスがここに記述されたアドレス若しくは CIDR で示されるレンジにマッチしたら $deny_ip とした変数に 1 がセットされる。何もマッチしなかった場合には default で示す 0 がセットされる。
 制限したい IP アドレスや CIDR が複数ある場合は列挙して行けば良い。

geo $deny_ip {
    default 0;
    23.236.64.0/20 1;
}

 実際にアクセスを拒否する動作は server ブロック内にて行う。
 先程の geo ディレクティブにて定義した $deny_ip が真であった場合にはリターンコードとして 403 を返す。つまり Forbidden とする。

if ( $deny_ip ) {
    return 403;
}

おわりに

 Nginx はなかなかに便利なディレクティブが存在したり if 文が使えたりと、柔軟で可読性のある設定を記述できる事がまた面白い。
 if 文に関してはあまり推奨された物ではない雰囲気だから多用は避けたいが、サーバー負荷や応答速度に問題がなければそれで取り敢えずいいのではと思っていたりする。

スポンサーリンク