我希望能够通过IP禁止用户。我的想法是将一个IP列表保存为BannedIPs表中的行(IP列将是一个索引)。
要根据表检查用户的IP,我将为每个会话保留一个名为$ _SESSION ['IP']的会话变量。如果在任何请求中,$ _SESSION ['IP']与$ _SERVER ['REMOTE_ADDR']不匹配,我将更新$ _SESSION ['IP']并检查BannedIPs表以查看IP是否被禁止。 (标志也将保存为会话变量,指定用户是否被禁止)
以下是我想知道的事情:
请注意......
答案 0 :(得分:6)
首先,我建议不要使用MySQL和PHP来执行此操作。 Apache有一个Deny
指令来禁止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
此功能由Apache 2.2中的mod_authz_host
提供。有关每个指令的更多信息,请参阅Apache's mod_authz_host
Documentation Page。
话虽如此:
当用户的IP在$_SESSION['IP']
中始终可用时,为什么会有$_SERVER['REMOTE_ADDR']
?我能看到的唯一原因是保存到数据库的行程......但是如果你将这个IP添加到你的禁令列表中,他仍然可以访问,直到他的会话到期。
如果您确实仍想使用数据库,请将IP地址存储为INT
(或2 BIGINT
列(如果您要支持IPv6)。它们占用的空间少于字符串,比较快。
至于它的安全性......他们可以通过代理来绕过禁令。如果您希望收到响应,则在数据包中欺骗IP地址是完全没用的。
答案 1 :(得分:2)
Select Count(*) from bannedIPs where ip = $input
,如果返回0,则不会禁止IP。一般情况下,我建议您记住,您的站点可能被一台路由器后面的许多计算机访问,这意味着所有用户都会显示相同的IP。你禁止一个,你禁止他们。我决心通过电子邮件和其他方式禁止。此外,我想说,那些伤害你网页的人不会被ip禁令或其他手段阻止。考虑到这一点,始终保护自己免受XSS,sql注入等常见的待遇。
答案 2 :(得分:1)
回答你的第3个问题:
您可能需要处理IPv6以及IPv4,因此您的数据结构需要允许128位地址值。
答案 3 :(得分: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地址。
使用整数通常是最好的方法,尤其是在使用数据库和范围时。 如果您想更好地理解/读取数据,字符串会更好。
答案 4 :(得分:1)
http://www.rubyrobot.org/article/protect-your-web-server-from-spambots
我们的想法是将禁令存储在PHP(或其他)的数据库中,但不要使用PHP进行任何过滤。每个请求额外的DB命中可能是从快速到低速的转折点。
执行阻塞的位是内核级防火墙iptables。这由另一个只从数据库中读取的脚本更新。如果你愿意的话,你可以做一些像CSV一样简单的事情,并完全跳过数据库联系。
无论如何,IPTables 比全面数据库查询更有效。
如果使用SQL,请确保转义IP输入。我可能是偏执狂,但我已经看到$_SERVER['REMOTE_ADDR']
的各种废话。
的字符串。它们不是数字,而是四个数字的排列。 IPv6是十六进制的。字符串覆盖所有基础,处理成本很低。
您还应该知道服务器变量可能存在。阅读:Getting The Real IP Of Your Users