Laravel’de Hacklemeyi Önlemek İçin Ip Adres Engelleme Baştan Sona Detaylı Anlatım

Web ortamındaki uygulamalarımızı kullanan kötü niyetli kullanıcılar bulunabilir. Bu kullanıcılar ya başka ziyaretçileri rahatsız edebilir ya da formlarımızı kullanarak(SQL injection gibi…) uygulamayı çökertmek isteyebilir. Bu gibi ziyaretçilerin iplerini tespit ederek iplerini uygulama seviyesinde engelleyebiliriz. Bu yazıda Laravel 8′ de kötü niyetli kullanıcıların ip’ leri kara listeye alınarak nasıl engelleneceğini anlatacağım.

User Tablosuna last_login_at ve last_login_ip Alanlarını Ekleme

İlk önce kullanıcıların uygulamamıza giriş yaptıkları andaki zaman bilgilerini ve iplerini veritabanına kaydedeceğiz. Laravelin User modeli başlangıçta bu alanlara sahip olmadığı için bu alanları User tablosuna biz ekleyeceğiz. Bunun için ilk önce migration dosyalarını oluşturacağız. Laravel’ de aşağıdaki komutu çalıştırarak migration dosyasını oluşturuyoruz.

php artisan make:migration add_login_fields_to_users_table

class AddLoginFieldsToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->datetime('last_login_at')->nullable();
            $table->string('last_login_ip')->nullable();
        });
    }
}

Migration dosyasına last_login_at ve last_login_ip alanlarını ekleyip php artisan migrate komutunu terminalde çalıştırıyoruz.

app\Models\User.php model php dosyasında veritabanına eklediğimiz alanları tanımlıyoruz.

class User extends Authenticatable
{
  protected $fillable = [
        'name',
        'email',
        'password',
    	'last_login_at', 
    	'last_login_ip',
    ];

Son adımda kullanıcı web uygulamamıza giriş yaptığındaki ipsini ve giriş zamanını kaydetmek için LoginController‘ daki authenticated metodunu override ediyoruz.

app/Http/Controllers/Auth/LoginController.php

function authenticated(Request $request, $user)
{
    $user->update([
        'last_login_at' => Carbon::now()->toDateTimeString(),
        'last_login_ip' => $request->getClientIp()
    ]);
}

blocked_ips Tablosu

Daha sonra engellenecek iplerin tutulacağı blocked_ips tablosunu oluşturacağız. Bunun için php artisan make:migration create_blocked_ips_table migration dosyasını oluşturup içine ip alanını tanımlıyoruz.

class CreateBlockedIpsTable extends Migration
{
    public function up()
    {
        Schema::create('blocked_ips', function (Blueprint $table) {
            $table->id();
            $table->string('ip')->nullable();
            $table->timestamps();
        });
    }

php artisan migrate diyerek tablomuzu oluşturuyoruz.

Daha sonra php artisan make:model BlockedIp adında modelimizi oluşturuyoruz.

class BlockedIps extends Controller
{
    protected $fillable = [
        'ip'
    ];
}

Bu tablonun CRUD(create, read, update and delete) işlemleri için routes/web.php dosyasında route’ ları tanımlıyoruz.

		Route::get('blocked_ips', 'BlockedIpsController@getAll')->name('dashboard.blocked_ips');
		Route::get('blocked_ips', 'BlockedIpsController@create')->name('dashboard.create_blocked_ip');;
		Route::post('blocked_ips', 'BlockedIpsController@store')->name('dashboard.store_blocked_ip');;
		Route::delete('blocked_ips/{id}', 'BlockedIpsController@delete')->name('dashboard.delete_blocked_ip');;

php artisan make:controller BlockedIps komutu ile controller’ ımızı oluşturuyoruz. İçine kullanacağımız metodları yazıyoruz.

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class BlockedIpsController extends Controller
{
    public function getAll(Request $request){
      	try{
            $blocked_ips = \App\BlockedIp::get();
        }catch(\Exception $e){
            Log::error('Error when fetching blocked ips' . $e->getMessage());
        }
        return view('blocked_ips', $blocked_ips);
    }
  
  	public function create(Request $request){
        return view('create_blocked_ip');
    }

    public function store(Request $request){
        $params = $request->all();
      
        try{
            $blocked_ip = new \App\BlockedIps();
            $blocked_ip->fill($params);
            $blocked_ip->save();
        }catch(\Exception $e) {
            Log::error('Admin: new blocked ip error : ' . $e->getMessage());
        }
        return redirect()->route('dashboard.blocked_ips');
    }

    public function delete(Request $request, $id){
      	$blocked_ip = \App\BlockedIp::find($id);
 		try{
                $blocked_ip->delete();
           }catch(\Exception $e){
                Log::error('Admin: delete blocked ip error : ' . $e->getMessage());
           }
        return redirect()->route('dashboard.blocked_ips');
    }
}

Controller’ ımızda oluşturduğumuz metodları oluşturduktan sonra view dosyalarımızı oluşturuyoruz.

blocked_ips.blade.php dosyamızda ip’ leri listeliyoruz.

<h2>Engellenen IP listesi</h2>
    <a href="{{route('dashboard.create_blocked_ip')}}" class="btn btn-success" style="float: right;">Ip Ekle</a>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>IP</th>
                <th></th>
             </tr>
        </thead>
        <tbody>
             @for($blocked_ips as $blocked_ip)
                 <tr>
                     <td>{{$blocked_ip->ip}}</td>
                     <td><a href="{{route('dashboard.delete_blocked_ip', ['id' => $blocked_ip->id])}}" class="btn btn-danger delete-button">Sil</a></td>
                 </tr>
             @endfor
		</tbody>
	</table>

add_blocked_ip.blade.php dosyamızdaki form ile engellemek istediğimiz ipyi kara listeye alıyoruz.

<form action="" method="post" action="{{ route('dashboard.store_blocked_ip') }}">
      <!-- CROSS Site Request Forgery Protection -->
      @csrf
      <div class="form-group">
      	<label>Ip</label>
       	<input type="text" name="ip" required="required" class="form-control" placeholder="___.___.___.___">
      </div>
      <button type="submit" value="Submit" class="btn btn-dark btn-block">Kaydet</button>
</form>

RestrictIpMiddleware

Şimdi veri tabanında ipsini tespit ettiğimiz kullanıcının uygulamaya girişini engellemek için middleware oluşturacağız. Bunun için terminal ekranında php artisan make:middleware RestrictIpMiddleware komutunu çalıştırıyoruz.

Kernel.php dosyasındaki $middleware arrayine her requestte çalışması için RestrictIpAddressMiddleware middleware ‘i ekliyoruz.

protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    	\App\Http\Middleware\RestrictIpAddressMiddleware::class,
    ];

RestrictIpAddressMiddleware.php

middleware’ imizin handle metodunu aşağıdaki gibi düzenleyerek istenmeyen kullanıcıların uygulamamızı kullanmasını engelliyoruz.

<?php

namespace App\Http\Middleware;

use Closure;

class RestrictIpAddressMiddleware
{

    // Blocked IP addresses
    public $restrictedIp = [];
    
    public function restrictedIp(){
        $this->restrictedIp = \App\BlockedIps::get();
    }
    
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $this->restrictedIp();
        if (in_array($request->ip(), $this->restrictedIp->pluck('ip')->toArray())) {
            return response()->json(['message' => "You are not allowed to access this site."]);
        }
        return $next($request);
    }
}

Artık istenmeyen kullanıcıların iplerini tespit ederek uygulamamızdan uzak tutabiliriz.

Başarılar …