使用php/mysql通过IP禁止

使用php/mysql通过IP禁止,php,mysql,Php,Mysql,我希望能够通过IP禁止用户。我的想法是将IP列表作为行保存在BannedIPs表中(IP列将是索引) 为了对照表检查用户的IP,我将为每个会话保留一个名为$_session['IP']的会话变量。如果在任何请求中,$\u会话['IP']与$\u服务器['REMOTE\u ADDR']不匹配,我将更新$\u会话['IP'],并检查BannedIPs表以查看该IP是否被禁止。(一个标志也将保存为会话变量,指定是否禁止用户) 以下是我想知道的事情: 在速度和安全方面,这听起来像是一个很好的策略吗(除了

我希望能够通过IP禁止用户。我的想法是将IP列表作为行保存在BannedIPs表中(IP列将是索引)

为了对照表检查用户的IP,我将为每个会话保留一个名为$_session['IP']的会话变量。如果在任何请求中,$\u会话['IP']与$\u服务器['REMOTE\u ADDR']不匹配,我将更新$\u会话['IP'],并检查BannedIPs表以查看该IP是否被禁止。(一个标志也将保存为会话变量,指定是否禁止用户)

以下是我想知道的事情:

  • 在速度和安全方面,这听起来像是一个很好的策略吗(除了更改IP、编辑或使用代理之外,是否有人能够以某种方式绕过IP禁令)
  • 构造检查行是否存在的mysql查询的最佳方法是什么?也就是说,查询db以查看是否存在具有特定IP的行(检查是否被禁止)的最佳方法是什么
  • 我应该将IP保存为整数还是字符串
  • 请注意

    • 我估计数据库中将存储1000-10000个被禁止的IP
    • $\u SERVER['REMOTE\u ADDR']是从中发送当前请求的IP
    关于你的第三个问题:

    您可能需要考虑IPv6和IPv4,因此您的数据结构需要允许128位地址值

  • 是的,通过HTTP头欺骗
  • 从bannedIPs中选择Count(*),其中ip=$input
    ,如果返回0,则不禁止ip
  • 我会使用字符串

  • 一般来说,我建议您记住,您的站点可能会被一个路由器后面的多台计算机访问,这意味着所有用户都将使用相同的ip。你禁止一个,你就禁止所有人。我决心通过电子邮件和其他方式禁止。另外,我想说的是,那些损害你网页的人不会被ip禁令或其他方式拒之门外。考虑到这一点,请始终保护自己不受XSS、sql注入等常见处理方式的影响。

    首先,我建议不要使用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提供。有关每个指令的更多信息,请参阅


    也就是说:

  • 当用户的IP在
    $\u服务器['REMOTE\u ADDR']
    中始终可用时,为什么要使用
    $\u会话['IP']
    ?我能看到的唯一原因是保存到数据库的行程。。。但是如果你把这个IP添加到你的禁止列表中,他仍然可以访问,直到他的会话到期

  • 如果确实要继续使用数据库,请将IP地址存储为
    INT
    (如果要支持IPv6,请存储为2列
    BIGINT
    )。它们比字符串占用更少的空间,而且比较起来更快


  • 至于它的安全性。。。他们可以通过代理绕过禁令。如果您希望收到响应,那么在数据包中欺骗IP地址是完全没有用的。

    10.000个条目对于MySQL来说是一个简单的游戏。只要将索引设置正确,这个数量就不会有问题

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

    只要用户不支持旋转代理,您的策略就会起作用。i、 e.通过AOL客户端访问网站的AOL用户将拥有不同的IP地址,因为他们的请求来自不同的代理服务器。通常这不是问题

    用户的IP地址保存在您的会话($\u会话['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的一部分。i、 e.您可以搜索192.168.0%而不是192.168.0.1:

    … WHERE ip LIKE '192.168.0.%' …
    
    这也允许您过滤小型网络,而不是定义所有IP地址

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

  • 其思想是将禁令存储在来自PHP(或其他)的数据库中,但不使用PHP进行任何过滤。每一个请求的额外DB命中率可能是从快到慢的转折点

    执行阻塞的位是内核级防火墙iptables。这将由另一个仅从数据库读取的脚本更新。如果您愿意,您可以使用CSV这样简单的工具执行类似的操作,并完全跳过数据库联系

    无论如何,IPTables比完全的on-DB查询要高效得多

  • 如果使用SQL,请确保转义IP输入。我可能有点偏执,但我已经看到各种各样的胡说八道从
    $\u服务器['REMOTE\u ADDR']

  • 字符串。它们不是数字,而是四个数字的组合。IPv6是十六进制的。一个字符串可以覆盖所有的碱基,处理成本很低


  • 您还应该知道,服务器变量可能会撒谎。阅读:

    对此不确定,但在我的大学里,每个人都有相同的IP,因此如果你的网站与学校相关,这可能会成为一个问题。@ggfan:我的网站与学校无关,但这是一个很好的观点。但是,如果我想禁止某人进入某个建筑/学校,我真的希望整个地方也被禁止,所以这很好。不仅仅是学校,还有许多拥有代理服务器的组织。公司、图书馆等。禁止使用电子邮件不是问题,因为我也禁止使用与独特电子邮件相关的帐户。另外,+1-我喜欢这个查询。使用.htaccess解决方案,我可以重新