代码之家  ›  专栏  ›  技术社区  ›  Cam

用php/mysql通过IP禁止

  •  3
  • Cam  · 技术社区  · 14 年前

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

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

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

    请注意。。。

    • 我估计数据库中会存储1000-10000个被禁止的IP。
    • $\u SERVER['REMOTE\u ADDR']是发送当前请求的IP。
    5 回复  |  直到 14 年前
        1
  •  6
  •   Andrew Moore    14 年前

    首先,我建议不要使用MySQL和PHP来实现这一点。阿帕奇有一个 Deny

    .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's mod_authz_host Documentation Page


    也就是说:

    1. 为什么有 $_SESSION['IP'] 当用户的IP始终可用时 $_SERVER['REMOTE_ADDR'] ? 我能看到的唯一原因是保存一次数据库访问。。。但是如果你把这个IP添加到你的禁止列表中,他仍然可以访问,直到他的会话过期。

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

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

        2
  •  2
  •   Femaref    14 年前
    1. 是的,通过HTTP头欺骗。
    2. Select Count(*) from bannedIPs where ip = $input
    3. 我会使用字符串。

    一般来说,我建议你记住,你的网站可能会被一个路由器后面的许多计算机访问,这意味着所有用户都会显示相同的ip。你禁止一个,你禁止所有人。我决心通过电子邮件和其他方式禁止。另外,我想说的是,人们伤害你的网页将不会远离知识产权禁令或其他手段。记住这一点,一定要保护自己免受XSS、sql注入等常见的攻击。

        3
  •  1
  •   ChrisF toni    14 年前

    这是你的第三个问题:

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

        4
  •  1
  •   favo    14 年前

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

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

    用户的IP地址保存在您的会话($\u 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
    }
    

    … WHERE ip LIKE '192.168.0.%' …
    

    使用整数通常是最好的方法,尤其是在处理数据库和范围时。

        5
  •  1
  •   Oli    14 年前
    1. http://www.rubyrobot.org/article/protect-your-web-server-from-spambots

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

      执行阻塞的位是内核级防火墙iptables。这会被另一个只从数据库读取的脚本更新。你可以用CSV这样简单的东西做一些类似的事情,如果你想的话,可以完全跳过数据库联系。

      不管怎样,IPTables是 许多的 比完整的数据库查询更高效。

    2. 如果使用SQL,请确保转义IP输入。我可能有点偏执,但我看到过各种各样的胡说八道 $_SERVER['REMOTE_ADDR']

    3. 串。它们不是数字,而是四个数字的组合。IPv6是十六进制的。一根线覆盖了所有的碱基,处理成本很小。

    您还应该知道服务器变量可能会撒谎。阅读: Getting The Real IP Of Your Users