Install via Composer:
composer require coosos/ip-filter-bundle
Ensure your composer.json meets the requirements (PHP 7.1+, Symfony 4/5, Doctrine 2.6+).
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Coosos\IpFilterBundle\CoososIpFilterBundle::class => ['all' => true],
];
Create an IP Filter Model:
Generate a Doctrine entity (e.g., IpFilter) with fields for ip, rangeStart, rangeEnd, isAuthorized, and environments (e.g., ['dev', 'test']).
Example:
php bin/console make:entity IpFilter
Add fields:
# src/Entity/IpFilter.php
/**
* @ORM\Column(type="string", length=45, nullable=true)
*/
private $ip;
/**
* @ORM\Column(type="string", length=45, nullable=true)
*/
private $rangeStart;
/**
* @ORM\Column(type="string", length=45, nullable=true)
*/
private $rangeEnd;
/**
* @ORM\Column(type="boolean")
*/
private $isAuthorized = false;
/**
* @ORM\Column(type="json")
*/
private $environments = [];
Configure the Bundle:
Add to config/packages/coosos_ip_filter.yaml:
coosos_ip_filter:
model: App\Entity\IpFilter
firewall: main # or your custom firewall name
First Use Case:
Seed your database with allowed/blocked IPs (e.g., via a migration or doctrine:fixtures:load).
Test access by simulating requests from different IPs:
curl -H "X-Forwarded-For: 192.168.1.20" http://your-app.test/
Dynamic IP Filtering:
IpFilterListener) to check IPs on every request.// src/EventListener/CustomIpFilterListener.php
use Coosos\IpFilterBundle\EventListener\IpFilterListener;
use Psr\Log\LoggerInterface;
class CustomIpFilterListener extends IpFilterListener
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
protected function onBlockedRequest($ip)
{
$this->logger->warning(sprintf('Blocked IP: %s', $ip));
parent::onBlockedRequest($ip);
}
}
services.yaml:
services:
App\EventListener\CustomIpFilterListener:
arguments: ['@logger']
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Environment-Specific Rules:
environments field to apply rules per environment (e.g., allow 192.168.1.* only in dev).dev environment:
// src/DataFixtures/IpFilterFixtures.php
public function load(ObjectManager $manager)
{
$ipFilter = new IpFilter();
$ipFilter->setRangeStart('192.168.1.0');
$ipFilter->setRangeEnd('192.168.1.255');
$ipFilter->setIsAuthorized(true);
$ipFilter->setEnvironments(['dev']);
$manager->persist($ipFilter);
$manager->flush();
}
Integration with Security System:
// src/Security/Voter/IpFilterVoter.php
use Coosos\IpFilterBundle\IpFilterManager;
class IpFilterVoter extends Voter
{
private $ipFilterManager;
public function __construct(IpFilterManager $ipFilterManager)
{
$this->ipFilterManager = $ipFilterManager;
}
protected function supports($attribute, $subject)
{
return $attribute === 'IP_FILTER';
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$ip = $token->getClientIp();
if (!$this->ipFilterManager->isIpAllowed($ip)) {
return AccessDeniedException::create();
}
return AccessDecision::GRANTED;
}
}
security.yaml:
security:
access_control:
- { path: ^/, roles: ROLE_USER, voter: App\Security\Voter\IpFilterVoter, attribute: IP_FILTER }
Bulk IP Management:
BulkOperations or a custom command to update IPs en masse:
php bin/console make:command UpdateIpFilters
Example command:
// src/Command/UpdateIpFiltersCommand.php
use Doctrine\ORM\EntityManagerInterface;
use Coosos\IpFilterBundle\Entity\IpFilter;
class UpdateIpFiltersCommand extends Command
{
protected static $defaultName = 'app:update-ip-filters';
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ipFilters = $this->entityManager->getRepository(IpFilter::class)->findAll();
foreach ($ipFilters as $ipFilter) {
$ipFilter->setEnvironments(['prod']); // Update all to 'prod'
$this->entityManager->persist($ipFilter);
}
$this->entityManager->flush();
$output->writeln('Updated IP filters for all environments.');
}
}
Performance Overhead:
IpFilterManager results if rules change infrequently:
$cache = $container->get('cache.app');
$key = 'ip_filter_rules_' . $_ENV['APP_ENV'];
$rules = $cache->get($key, function() {
return $this->ipFilterManager->getAllFilters();
});
IP Detection Issues:
getClientIp() may return incorrect IPs behind proxies (e.g., X-Forwarded-For).trusted_proxies in framework.yaml:
framework:
trusted_proxies: ['127.0.0.1', '192.168.1.0/24'] # Add your proxy IPs
getClientIp() in the listener if needed:
protected function getClientIp(Request $request)
{
return $request->headers->get('X-Forwarded-For') ?: $request->getClientIp();
}
Priority Logic:
// Test that 192.168.1.20 is allowed even if 192.168.1.10-100 is blocked
$this->assertTrue($ipFilterManager->isIpAllowed('192.168.1.20'));
IPv6 Support:
2001:0db8::/32) for ranges.Database Bloat:
192.168.1.0/24) and store as a single record.protected function isIpAllowed($ip)
{
$result = parent::isIpAllowed($ip);
\Log::debug(sprintf('IP %s allowed: %s', $ip, $result));
return $result;
}
2
How can I help you explore Laravel packages today?