繁体   English   中英

查询以返回与 IP 地址块匹配的行?

[英]Query to return rows that match a block of ip addresses?

我试图阻止某些 IP 地址和 IP 范围执行某些操作。 现在,我SELECT * FROM blocked WHERE ip=$_SERVER['REMOTE_ADDR']并且如果 ->num_rows 返回 > 0,我重定向用户。

这适用于完整的 IP 地址,但如果我将199.90.*.*例如,放入数据库中,我该如何匹配? 另外,将 IP 存储在数据库中的最佳方法是什么?

您的问题的答案是使用like

SELECT *
FROM blocked
WHERE $_SERVER['REMOTE_ADDR'] like replace(ip, '*', '%')

like的通配符是'%'而不是'*' ,因此这用百分号替换星号。 我猜你实际上会存储像'199.199.%.%'这样的字符串,但以上是为了清楚起见。

尽管这在技术上解决了您的问题,但它还有其他问题,因为 MySQL 可能不会使用索引进行这些比较(请参阅此处)。 影响取决于阻塞的表有多大。 如果它有 100 行,这可能不是问题。 如果它有 100,000 那么它可能是。

对阻止表使用通配符的替代方法是将FromIPToIP作为列。 然后像“199.199。”就简单地存储为“199.199.000.000”和“199.199.999.999”。 查询将是:

where $_SERVER['REMOTE_ADDR'] between FromIP and ToIP

并且您将在blocked(FromIP, ToIP)上有一个索引。

我会首先检查完整的 IP 地址,然后用 * 屏蔽最后一个字节,然后检查它,然后是最后 2 个字节,依此类推。 通过这种方式,您可以从具体到不太具体,一旦您受到攻击,IP 就会被阻止。 这可能不是最有效的方法,但我想您只需在登录时执行一次。

为简单起见,我会将 IP 地址存储为字符串。

另一种解决方案可能是将 IP 地址存储为字节数组,但我猜这不会使任何事情变得更容易,并且使用例如命令行工具 SQL 工具的可维护性要低得多。

您最好的解决方案是使用INET_ATON函数。

将 IPv4 网络地址的点分四线表示为字符串,返回一个整数,该整数表示网络字节顺序(大端)中地址的数值。

因此,如果您想查找某个范围内的 IP,您可以使用这样的查询:

SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between INET_ATON(this_ip) and INET_ATON(this_other_ip).

我认为,在 MySQL 数据库中存储 IPv4 地址的最佳方法是使用该函数,将它们转换为int值并像这样存储。 如果您想从它的int表示中获取 IP,请使用INET_NTOA

将 IP 存储为int ,查询结束如下:

SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between this_ip and this_other_ip.

而不是使用 199.90.*.* 使用 (199.90.0.0)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM