Как создать черный список IP-адресов в Symfony2? - PullRequest
9 голосов
/ 22 ноября 2011

Да, я знаю, что Учебник для избирателей в кулинарной книге . Но я ищу что-то немного другое. Мне нужно два разных слоя черного списка:

  1. запретить определенному IP-адресу доступ ко всему сайту
  2. запретить вход на определенный IP-адрес

Я написал Voter, который проверяет, есть ли IP пользователя в базе данных. Для первого сценария я написал слушатель ядра, который проверяет каждый запрос и выдает 403 в случае, если он встречает заблокированного пользователя:

if (VoterInterface::ACCESS_DENIED === $this->voter->vote($token, $this, array())) {
    throw new AccessDeniedHttpException('Blacklisted, punk!');
}

Первая проблема заключается в самом VoterInterface, что вынуждает меня использовать TokenInterface $token, который мне не нужен в этом случае. Но это не имеет большого значения, я думаю. Следующее, что я действительно должен был использовать AccessDeniedHttpException, поскольку AccessDeniedException всегда пытается перенаправить меня на страницу входа и вызывает бесконечный цикл перенаправления в этом случае. Я бы смирился с этим, так как он отлично работает в dev среде, но когда я переключаюсь на prod, я получаю 503 со следующим в логе продукта:

[2011-11-21 20:54:04] security.INFO: заполненный SecurityContext с помощью анонимный токен [] []

[2011-11-21 20:54:04] request.ERROR: Symfony \ Component \ HttpKernel \ Exception \ AccessDeniedHttpException: В черном списке, панк! (uncaught исключения) в строке XXX 28 [] []

[2011-11-21 20:54:04] request.ERROR: Возникает исключение при обработке исключение (Symfony \ Component \ HttpKernel \ Exception \ AccessDeniedHttpException: В черном списке, панк!) [] []

Из того, что я прочитал, может быть проблема с xdebug, но это происходит, даже когда я выключаю его. Я также попробовал ваниль \Exception, и он делает то же самое. У кого-нибудь есть идеи, почему это происходит? Или, может быть, какое-то другое решение для такого черного списка.

Кроме того, я не знаю, как решить второй случай, так как я не знаю, как остановить пользователя до того, как ему назначат токен. Мое текущее решение имеет дело с InteractiveLoginEvent , проверкой внесения пользователя в черный список и, если да, удалением его токена. Это не кажется безопасным, и мне не очень комфортно с этим. Итак, есть идеи, как решить эту проблему? Я предполагаю, что мне просто не хватает очевидного «события перед входом».

Ответы [ 6 ]

4 голосов
/ 12 сентября 2012

К первой проблеме - в EventDispatcher есть фильтры , поэтому вы можете выбросить AccessDeniedHttpException до запроса запуска процесса контроллера.

Ко второй проблеме - если вы используете Пользовательский поставщик вы можете проверить на заблокированные IP-адреса в UserRepository.

namespace Acme\SecurityBundle\Entity;
//… some namespaces
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * UserRepository
 */
class UserRepository extends … implements …
{

    public function loadUserByUsername($username)
    {
        if ( $this->isBanned() ) {
            throw new AccessDeniedHttpException("You're banned!");
        }
        //… load user from DB
    }

    //… some other methods

    private function isBanned()
    {
        $q = $this->getEntityManager()->createQuery('SELECT b FROM AcmeSecurityBundle:BlackList b WHERE b.ip = :ip')
            ->setParameter('ip', @$_SERVER['REMOTE_ADDR'])
            ->setMaxResults(1)
        ;
        $blackList = $q->getOneOrNullResult();

        //… check if is banned
    }

}
4 голосов
/ 23 ноября 2011

Для ограничений IP для всего сайта лучше всего обрабатывать их на уровне apache, чтобы ваше приложение даже не попадало под запрос. Если вы пытаетесь не пустить спамера, вы не тратите ресурсы на их иногда автоматические запросы. В вашем случае было бы целесообразно записать запрещающие правила в файл .htaccess. В более крупных установках вы также можете настроить брандмауэр для блокировки определенных IP-адресов, чтобы эти запросы даже не попали на ваш сервер.

4 голосов
/ 22 ноября 2011

Чтобы запретить доступ ко всему сайту, вы можете адаптировать код белого списка, используемый для защиты среды разработки. Вставьте что-то вроде этого в app.php:

if (in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '1.2.3.4',))) {
    header('HTTP/1.0 403 Forbidden');
    exit('You are not allowed to access this site.');
}
1 голос
/ 08 января 2014

Вы можете легко заблокировать IP и диапазон IP, используя мой пакет => https://github.com/Spomky-Labs/SpomkyIpFilterBundle

1 голос
/ 02 декабря 2011

вы также можете использовать брандмауэр на сервере, например: http://www.shorewall.net/blacklisting_support.htm который полностью блокирует данный ips сервера.

, чтобы автоматически создать такой файл черного списка, посмотрите на следующий пример: http://www.justin.my/2010/08/generate-shorewall-blacklist-from-spamhaus-and-dshield/

0 голосов
/ 20 января 2016

Это не лучшая практика. Insight (анализ Sensio) возвращает: «Использование функций ответа PHP (например, header () здесь) не рекомендуется, так как оно обходит систему событий Symfony. Вместо этого используйте класс HttpFoundationResponse» и "$ _SERVER super global не должен использоваться."

<?php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

$loader = require_once __DIR__.'/../app/bootstrap.php.cache';

require_once __DIR__.'/../app/AppKernel.php';


$request = Request::createFromGlobals();

$client_ip = $request->getClientIp();
$authorized_hosts = ['127.0.0.1', 'fe80::1', '::1', 'localhost', 'yourIpAddress'];

// Securisation
if (!in_array($client_ip, $authorized_hosts)) {
    $response = new Response(
        "Forbidden",
        Response::HTTP_FORBIDDEN,
        array('content-type' => 'text/html')
    );
    $response->send();
    exit();
}

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

Это нормально для SensioInsight

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...