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

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!