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

ミドルウェア本体です。

 1<?php
 2namespace App\Http\Middleware;
 3
 4use Closure;
 5use Illuminate\Support\Facades\Log;
 6
 7/**
 8 * クライアントのリアルIPがホワイトリストに存在するかチェックするためのミドルウェア
 9 */
10class IpLimit
11{
12    /**
13     * Handle an incoming request.
14     *
15     * @param  \Illuminate\Http\Request  $request
16     * @param  \Closure  $next
17     * @return mixed
18     */
19    public function handle($request, Closure $next)
20    {
21        $config = \Config::get('ip_limit');
22        if ($config['enable'] !== true) {
23            return $next($request);
24        }
25        if ($config['isProxy'] === true) {
26            $request->setTrustedProxies([$request->ip()]);
27        }
28        if ($this->isAllow($request->ip(), $config['allowIps']) === false) {
29            Log::debug('cannot access from : '. $request->ip());
30            abort(403);
31        }
32        return $next($request);
33    }
34
35    private function isAllow(string $remoteIp, array $accepts)
36    {
37        foreach ($accepts as $accept) {
38            if ($this->isIn($remoteIp, $accept)) {
39                return true;
40            }
41        }
42        return false;
43    }
44    private function isIn(string $remoteIp, string $accept)
45    {
46        if (strpos($accept, '/') === false) {
47            return ($remoteIp === $accept);
48        }
49        list($acceptIp, $mask) = explode('/', $accept);
50        $acceptLong            = ip2long($acceptIp) >> (32 - $mask);
51        $remoteLong            = ip2long($remoteIp) >> (32 - $mask);
52
53        return ($acceptLong == $remoteLong);
54    }
55}
56

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

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

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

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

config/ip_limit.php

 1<?php
 2
 3return [
 4    'enable'   => env('IP_LIMIT_ENABLE', false),
 5    'isProxy'  => env('IP_LIMIT_PROXY',  false),
 6    'allowIps' => [
 7        env('LOCALHOST_IP', '127.0.0.1'),
 8        192.168.0.98/21',
 9    ],
10];
11

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

使い方

.env

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

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

ミドルウェアの定義

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

1protected $middlewareGroups = [
2    'web' => [
3        :
4        \App\Http\Middleware\IpLimit::class,
5

おわりに

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

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

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

[Laravel]SQLをログ出力するミドルウェアつくったった
atuweb 開発ブログ

楽しい開発ライフをお過ごしください。

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

竹澤 有貴,栗生 和明,新原 雅司,大村 創太郎
出版社:ソシム  発売日:2018-09-26

Amazonで詳細を見る

PHPフレームワーク Laravel入門

掌田津耶乃
出版社:秀和システム  発売日:2017-09-16

Amazonで詳細を見る

初めてのPHP

David Sklar
出版社:オライリージャパン  発売日:2017-03-18

Amazonで詳細を見る