Brave publisher PUBLISHER
Web developer Front-End in Oise, France - Gary Deshayes

Symfony Event Subscriber | Restricting an ip range with an Event Subscriber

Web developer Front-End in Oise, France - Gary Deshayes <--Traduction

Created at : Saturday 14 November 2020

Adding an Event Subscriber under Symfony with IP range restriction


As part of the tutorial, we will set up an IP range restriction to allow certain IPs, but you can use Event subscriber
in any case. An Event subscriber allows us to execute code before entering in our route to a controller for example, it allows us to check certain
things like token connection, and all other kinds of manipulations.

Added the SecureIpSubscriber.php file.


You have to start by adding an EventSubscriber folder in the src folder of your Symfony project (Or wherever you want but it's faster here).
And then add the following file :

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class SecureIpSubscriber implements EventSubscriberInterface
{
    public function onKernelController($event)
    {
        // Add your code here
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => 'onKernelController',
        ];
    }
}

You can see that our SecureIpSubscriber class necessarily implements the EventSubscriberInterface
And that thanks to the static getSubscribedEvents function, we know the event on which the class is listening, there are several Symfony events
The code that will be executed when listening on this event is present in the onKernelController function, so we will see how to restrict ip!

Definition of ip ranges and addition of a sort function


To restrict ip ranges we must first know which ranges to restrict:

class SecureIpSubscriber implements EventSubscriberInterface
{
    private $ips = array(
        array('deb' => '125.1.0.1', 'fin' => '125.158.3.254'),
        array('deb' => '192.168.5.1', 'fin' => '192.168.160.254'),
    );

    /**
    Code ...
    */
}

 

So we add a private variable that allows us to define two ip ranges, we could add as many as we want.
And then we need a function (which is not mine) that will allow us to sort the ip in our array.

 

    //Check rangeip
    private function verifRangeIP($IP, $RangeIP)
    {
        $result = true;
        $tabIP = explode(".", $IP);
        if (is_array($RangeIP)) {
            foreach ($RangeIP as $value) {
                $tabRangeIP[] = explode(".", $value);
            }
            for ($i = 0; $i < 4; $i++) {
                if (($tabIP[$i] < $tabRangeIP[0][$i]) || ($tabIP[$i] > $tabRangeIP[1][$i])) {
                    $result = FALSE;
                }
            }
        } else {
            $tabRangeIP = explode(".", $RangeIP);
            for ($i = 0; $i < 4; $i++) {
                if (($tabIP[$i] != $tabRangeIP[$i])) {
                    $result = FALSE;
                }
            }
        }
        return ($result);
    }

 

And once we have defined our ranges and the verifRangeIp function in our class, we can write the code in the onKernelController :

 

    //Check ip on api route
    public function onKernelController($event)
    {
        if ($event->getRequest()->get('_route') == "api") {
            $ip = $_SERVER['REMOTE_ADDR'];
            $valid = false;
            // localhost
            if ($ip == '::1' || $ip == '127.0.0.1') {
                $valid = true;
            } else {
                foreach ($this->ips as $range) {
                    $valid = $this->verifRangeIP($ip, $plage);
                    if ($valid === true) break;
                }
            }

            if ($valid === false) {
                exit();
            }
        }
    }

 

In my case we can see that I have restricted the ip for only one route, but it is possible to remove this condition so that it is applicable to the whole of 
the application, or add others of your choice.
So we check if the ip is localhost or in an ip range, if it's good we continue on our way that could return us data from an API and in
Otherwise the code is exit and the person receives nothing.

Symfony Event Subscriber | Restricting an ip range with an Event Subscriber

We can see in the Symfony profiler that we fit well in our new Event Subscriber, it's possible to dump in it to debug!

This tutorial is now finished, thanks for reading and feel free to share it!

 

 

News publications :

Symfony 5 | Return an image via a controller route

Symfony

Created at : Wednesday 1 September 2021

VueJS 3, ExpressJS 4.17 | Uploading and resizing an image

Javascript Framework JS

Created at : Saturday 28 November 2020

Symfony Event Subscriber | Restricting an ip range with an Event Subscriber

Symfony

Created at : Saturday 14 November 2020

Angular, ExpressJS | JWT authentication with Angular 10 and ExpressJS 4 (MySQL)

Javascript SQL Framework JS

Created at : Sunday 20 September 2020

Symfony, Excel, CSV | Generating a CSV file for Excel with Symfony

Symfony

Created at : Thursday 6 August 2020

Symfony FormType Choice | Set data default to group of radio button

Symfony

Created at : Sunday 26 July 2020

Doctrine, Symfony | Difference between two dates in MySQL (Day, month, year...)

Symfony SQL

Created at : Thursday 18 June 2020

JavaScript, jQuery et Regex | Secure a password in real time with JS

Javascript jQuery

Created at : Monday 23 March 2020

Symfony, Doctrine | Retrieve old data of FormType

Symfony

Created at : Friday 14 February 2020

jQuery, Webpack and Symfony | Call jQuery in your twig files

Symfony Bugs

Created at : Sunday 26 January 2020