У меня есть IP-фильтр для белого списка в одном из моих старых проектов, который я хочу повторно использовать в новом приложении.Рефакторинг PHP-основанного IP-фильтра для работы с IPv6
Редактировать для уточнения; Он работает следующим образом:
Белый список содержит записи в формате, указанном ниже. Используя foreach ($whitelist as $listed)
, я проверяю тип ввода текущей записи ($listed
), а затем сравните эту запись с $ip
. Как только он найдет запись, которая соответствует указанному IP, она вернет true, если после прохождения всего белого списка совпадение не будет найдено, оно вернет false.
В настоящее время, только IPv4 поддерживается и фильтр позволяет белый список записей, как следуют:
- IP-диапазон, указав BEGIN - END (
192.168.0.1-192.168.0.5
) - одного IP-адреса (например,
192.168.0.2
) - IP-диапазона с использованием * -wildcard (например
192.168.0.*
)
методы для проверки каждого из этих случаев выглядят так, гдеявляется IP клиента и $listed
является запись из белого списка/черный список, соответствующий одному из перечисленных выше форматов:
public function checkAgainstRange($ip, $listed)
{
list($begin, $end) = explode('-', $listed);
$begin = ip2long($begin);
$end = ip2long($end);
$ip = ip2long($ip);
return ($ip >= $begin && $ip <= $end);
}
public function checkAgainstSingle($ip, $listed)
{
return long2ip(ip2long($ip)) === long2ip(ip2long($listed));
}
public function checkAgainstWildcard($ip, $listed)
{
$listedSegment = explode('.', $listed);
$ipSegment = explode('.', $ip);
for ($i = 0; $i < count($listedSegment); $i++) {
// We're finished when the wildcarded block is reached
// Important: Check for wildcard first, as it won't match the client IP!
if ($listedSegment[$i] == '*') {
return true;
}
if ($listedSegment[$i] != $ipSegment[$i]) {
return false;
}
}
// Just to be safe: If we reach this, something went wrong
return false;
}
мне нужны некоторые указания относительно того, как сделать эти работы с IPv6-адресами.
Некоторые из необходимых изменений очевидны: * ip2long()
работает только с IPv4-адресами * Я должен проверить :
в качестве возможного разделителя checkAgainstWildcard()
.
Я нашел inet_ntop()
и inet_pton()
в php-документах. Могу ли я использовать следующее, чтобы сравнить два отдельных IP-адреса?
public function checkAgainstSingle($ip, $listed)
{
$ip = inet_ntop($ip);
$listed = inet_ntop($listed);
if ($ip === false || $listed === false) {
throw new \Exception;
}
return $ip === $false;
}
Примеры использования:
$filter = new IpFilter();
$ip = $_SERVER['REMOTE_ADDR'];
$result = $filter->checkAgainstSingle($ip, '192.168.0.1');
$result = $filter->checkAgainstRange($ip, '192.168.0.1-192.168.0.10');
$result = $filter->checkAgainstWildcard($ip, '192.168.0.*');
Это даже полезно иметь что-то вроде checkAgainstRange()
? И если да, то как я мог бы даже проверить IPv6-диапазоны аналогичным образом? Очевидно, я не могу изменить ip2long()
на inet_ntop()
здесь ...
То же самое относится к подстановочным диапазонам. Должен ли я их хранить, и достаточно ли проверить :
как разделитель сегментов, и если он не найден, вернитесь в .
в качестве разделителя?
Что именно должен делать фильтр? Я не понимаю, что ожидаемый результат здесь. Не могли бы вы предоставить демо? Должен ли результат быть таким, чтобы данный IP соответствовал данному патерну? –
Да, это Ip-фильтр, сопоставляющий IP с белым списком, проверяя, является ли '$ ip == $ filter', где' $ filters' - это единственная запись из белого списка в одном из указанных форматов. В принципе, я просматриваю свой белый список и останавливаюсь, как только нахожу запись, которая соответствует моему ip. Я отредактирую свой вопрос, чтобы сделать его более ясным. – dbrumann