我的一个旧项目中有一个用于白名单的 IP 过滤器,我想在新应用程序中重用它。
编辑澄清;它是这样工作的:
白名单包含以下指定格式的条目。使用foreach ($whitelist as $listed)
,我检查当前条目 ( $listed
) 是哪种类型,然后将此条目与$ip
. 一旦找到与指定 IP 匹配的条目,它将返回 true,如果在遍历整个白名单后未找到匹配项,它将返回 false。
截至目前,仅支持 IPv4,过滤器允许以下白名单条目:
192.168.0.1-192.168.0.5
通过指定 BEGIN - END ( )指定 IP 范围- 单个 IP 地址(例如
192.168.0.2
) - 使用 * 通配符的 IP 范围(例如
192.168.0.*
)
检查每种情况的方法如下所示,其中$ip
是客户端的 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()
.
我在 php-docs 中找到了inet_ntop()
和。inet_pton()
我可以使用以下内容来比较两个单个 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()
这里...
通配符范围也是如此。我应该保留它们吗?作为段分隔符检查是否足够:
,如果找不到,则回退到.
分隔符?