2010-06-06 57 views
3

我希望能够通过IP来禁止用户。我的想法是将IP列表保留在BannedIPs表中(IP列将作为索引)。通过IP使用php/mysql禁止

要检查用户的IP对表,我会为每个会话保留一个名为$ _SESSION ['IP']的会话变量。如果有任何请求,$ _SESSION ['IP']与$ _SERVER ['REMOTE_ADDR']不匹配,我将更新$ _SESSION ['IP']并检查BannedIPs表以查看IP是否被禁止。 (A标志也将被保存为一个会话变量指定用户是否被禁止)

这里的事情,我想知道:

  1. 这听起来像关于速度的好策略和安全(有人能够以某种方式绕过IP禁令,除了更改IP,编辑:或使用代理)?
  2. 什么是最好的方式来构造一个MySQL查询,检查是否存在一行?也就是说,查询数据库以查看是否存在具有特定IP的行(检查它是否被禁止)的最佳方法是什么?
  3. 我应该将IP保存为整数或字符串吗?

注意...

  • 我估计会有1000-10000之间禁止IP的存储在数据库中。
  • $ _SERVER ['REMOTE_ADDR']是发送当前请求的IP。
+0

不知道这一点,但在我的大学里,每个人都有相同的知识产权,所以如果你的网站与学校有关,这可能是一个问题。 – ggfan 2010-06-06 22:30:06

+0

@ggfan:我的网站与学校无关 - 但这是一个很好的观点。不过,如果我想禁止某个建筑物/学校的人,我确实宁愿整个地方都被禁止,所以这很好。 – Cam 2010-06-06 22:34:01

+3

不仅仅是学校,还有许多具有代理服务器的组织。公司,图书馆等 – Jeff 2010-06-06 22:34:04

回答

6

首先,我会建议不要使用MySQL和PHP来做到这一点。 Apache有一个禁止IP地址的指令,最终会比本土解决方案更好。

你可以很容易地创建一个后端来查看&编辑一个.htaccess文件与所有这些条目。

这里是禁止2个的IP地址(对于那些想知道谷歌DNS服务器)和显示禁止,如果自定义页面...

Order Allow,Deny 
Deny from 8.8.8.8 
Deny from 8.8.4.4 
Allow from all 

ErrorDocument 403 /access_is_denied.htm 

此功能由mod_authz_host在Apache 2.2的提供了一个例子。关于每个指令的更多信息可以在Apache's mod_authz_host Documentation Page中找到。


话虽这么说:

  1. 为什么$_SESSION['IP']在所有当用户的IP是始终可用的$_SERVER['REMOTE_ADDR']?我能看到的唯一原因是为了省去一趟数据库......但是,如果您将IP添加到禁止列表中,他仍然可以访问,直到他的会话过期。

  2. 如果您确实想要使用数据库,请将IP地址存储为INT(或者如果您要支持IPv6,则需要存储2个BIGINT列)。他们比字符串占用更少的空间,并且比较快。

至于它的安全性......他们可以通过代理绕过禁令。如果您希望接收响应,欺骗分组中的IP地址是完全没有用的。

+0

使用.htaccess解决方案,我是否可以将用户重定向到自定义的“禁止”页面?这是必要的,因为我禁止学校/企业。 +1注意到用户仍然可以访问,直到会话过期 - 我没有想到这一点。 – Cam 2010-06-06 22:47:05

+1

@incrediman:是的,你可以......我已经更新了我的答案,以说明你如何实现这一目标。 – 2010-06-06 23:23:10

+0

真棒,谢谢! – Cam 2010-06-06 23:24:34

1

重新您的问题3:

你可能需要的IPv4让你的数据结构需要允许128位的地址值照顾IPv6的为好。

2
  1. 是的,通过HTTP标头欺骗。
  2. Select Count(*) from bannedIPs where ip = $input,如果返回0,则不禁止IP。
  3. 我会使用字符串。

一般来说,我建议您记住,您的网站可能会被一台路由器后面的许多计算机访问,这意味着所有用户都将显示相同的IP。你禁止一个,你禁止他们。我会决定通过电子邮件和其他方式禁止。另外,我想说,那些伤害你网页的人不会被ip禁令或其他手段阻止。考虑到这一点,始终保护自己免受像XSS,SQL注入等通常的待遇。

+0

禁止通过电子邮件是不是一个问题,因为我也禁止与唯一的电子邮件相关的帐户。另外,+1 - 我喜欢查询。 – Cam 2010-06-06 22:41:34

1

10.000条目是MySQL的简单游戏。只要将索引设置正确,这个数量就没有问题。

也许你应该考虑一个白名单而不是黑名单,这可能会减少你的IP地址列表?

只要用户不在旋转代理后面,您的策略就可以工作。即通过AOL客户端访问网站的AOL用户将拥有不同的IP地址,因为他们的请求来自不同的代理服务器。通常这不是问题。

用户的IP地址保存在会话中($ _SESSION ['IP']),通常存储在您的服务器上,因此足够安全。

这里是一个示例代码表中的检查项目:

$raw = mysql_query ("SELECT ip FROM ip_blacklist WHERE ip = '" . mysql_escape_string(getenv('REMOTE_ADDR')) . "' LIMIT 0,1"); 
if (mysql_num_rows ($raw)) { 
 // match found 
} 
else { 
// no match found 
} 

您可以修改它来搜索只针对IP的一部分。即改为192.168.0.1,你可以搜索192.168.0%。

… WHERE ip LIKE '192.168.0.%' … 

这可以让你筛选小型网络太不是定义的所有IP地址。

使用整数通常是最好的方法,特别是在使用数据库和范围时。 如果您想更好地理解/读取您的数据,字符串会更好。

1
  1. http://www.rubyrobot.org/article/protect-your-web-server-from-spambots

    的想法是你存储的禁令,从PHP(或其他)的数据库,但是你没有做任何PHP过滤。额外的数据库击中每个请求可能是从快速到缓慢的临界点。

    阻塞的位是内核级防火墙iptables。这由另一个刚刚从数据库读取的脚本进行更新。如果你愿意,你可以做一些类似于CSV那样简单的事情,并跳过数据库联系。

    无论如何,IPTables是很多比全功能数据库查询更有效。

  2. 如果您使用SQL,请确保您转义IP输入。我可能是偏执狂,但我通过$_SERVER['REMOTE_ADDR']看到了各种废话。

  3. 字符串。他们不是数字,他们是四个数字的安排。 IPv6是十六进制的。字符串以很小的处理成本覆盖所有基地。

你也应该知道,服务器变量可以说谎。阅读:Getting The Real IP Of Your Users

+0

+1。你可以扩展“你应该知道,服务器变量可以说谎”? – Cam 2010-06-06 22:49:19

+0

另外 - 你真的认为这将是如此巨大的打击我的分贝,如果IP列索引,并有最大10k的IP? – Cam 2010-06-06 22:55:06

+0

对于一些ISP,REMOTE_ADDR会为大量用户显示相同的结果,因为他们会使用代理。有时'HTTP_X_FORWARDED_FOR'可以作为替代方案(请参阅链接),但有些情况下,您显然无法获取用户的真实IP地址。我只需重新启动路由器就可以获得新的IP(需要30秒)。因此,通过知识产权取缔有时候不会有效,在某些情况下禁止你不打算取缔的人。仔细玩。 – Oli 2010-06-06 22:55:57