LaravelのプロジェクトでIP制限を実装しました。
多少需要があるかもしれないと思い、ソースを公開いたします。

動作確認環境

  • PHP 7.0.x
  • Laravel 5.3.x
  • CentOS 7系

ソースコード

以下のファイルを用意します。

  • app/Http/Middleware/IpLimit.php
  • config/ip_limit.php

app/Http/Middleware/IpLimit.php

ミドルウェア本体です。

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

/**
 * クライアントのリアルIPがホワイトリストに存在するかチェックするためのミドルウェア
 */
class IpLimit
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $config = \Config::get('ip_limit');
        if ($config['enable'] !== true) {
            return $next($request);
        }
        if ($config['isProxy'] === true) {
            $request->setTrustedProxies([$request->ip()]);
        }
        if ($this->isAllow($request->ip(), $config['allowIps']) === false) {
            Log::debug('cannot access from : '. $request->ip());
            abort(403);
        }
        return $next($request);
    }

    private function isAllow(string $remoteIp, array $accepts)
    {
        foreach ($accepts as $accept) {
            if ($this->isIn($remoteIp, $accept)) {
                return true;
            }
        }
        return false;
    }
    private function isIn(string $remoteIp, string $accept)
    {
        if (strpos($accept, '/') === false) {
            return ($remoteIp === $accept);
        }
        list($acceptIp, $mask) = explode('/', $accept);
        $acceptLong            = ip2long($acceptIp) >> (32 - $mask);
        $remoteLong            = ip2long($remoteIp) >> (32 - $mask);

        return ($acceptLong == $remoteLong);
    }
}

許可されていないIPアドレスからのアクセスがあった場合にログ出力して教えてくれます。
ログレベルはdebugにしていますので、適宜変更してください。

ロードバランサーを経由している場合考慮し、設定によってRealIPを取る処理を入れています。

サブネットマスクの処理はqiitaの次の記事をリスペクトいたしました。

qiita : IPアドレスが指定した範囲内にあるかどうか判別する
http://qiita.com/ran/items/039706c93a8ff85a011a

config/ip_limit.php

<?php

return [
    'enable'   => env('IP_LIMIT_ENABLE', false),
    'isProxy'  => env('IP_LIMIT_PROXY',  false),
    'allowIps' => [
        env('LOCALHOST_IP', '127.0.0.1'),
        ‘192.168.0.98/21',
    ],
];

アクセスを許可するIPアドレスを追加する場合はallowIpsの配列にリテラルを追加してください。
サブネットマスクはCIDR表記で表現します。

使い方

.env

Laravelの.envを修正し、次の設定を追加してください。

# IP制限を有効化する
IP_LIMIT_ENABLE=true
# Laravelがバランサー配下に設置されている場合にtrueにすると、Real IPを取得する
IP_LIMIT_PROXY=false
# Dockerやvagrantを利用している場合は127.0.0.1から変更します
LOCALHOST_IP=127.0.0.1

ミドルウェアの定義

app/Http/Kernel.phpに ミドルウェアを追加してください。

protected $middlewareGroups = [
    'web' => [
        :
        \App\Http\Middleware\IpLimit::class,

おわりに

説明不足のところや、ネーミングがカッコ悪いところはぜひご指摘ください!

ここまで書いておいてなんなのですが、素直にnginxでIP制限すればよかったです。

また、過去にはこんなミドルウェアも実装しました。

[Laravel]SQLをログ出力するミドルウェアつくったった
パフォーマンスが求められるWebアプリケーションは極限までSQLを調整するもの。 Laravelで実行されるSQLの把握するため...

この記事はtomita@atuwebがお届けしました。
楽しい開発ライフをお過ごしください。



Laravel: Up and Running: a Framework for Building Modern Php Apps



2017年02月21日:「CIDR表記」の誤表記を修正

スポンサーリンク
ad_336
ad_336
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存