首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >验证用户IP和表单IP:我应该使用ip2long吗?

验证用户IP和表单IP:我应该使用ip2long吗?
EN

Stack Overflow用户
提问于 2010-11-23 16:44:21
回答 3查看 1.1K关注 0票数 2

实际上,这是一个两部分的问题:

首先,ip2long是一个好的IP验证器吗?假设有人在表单中插入了一个IP,我想验证它是否正确。是否可以只检查ip2long是否不返回FALSE?

第二:检查访客的IP,如果不是合法的IP就拒绝访问,你怎么看?看看我的访客的ips,有时我会发现像"1.1 TIBURON“这样的东西。那是什么?我听说过‘欺骗ip’的说法,是这样的吗?它与垃圾邮件机器人有关吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-11-23 17:10:30

这取决于您希望验证的彻底程度。对格式良好的IP地址的一个非常简单的检查是沿着/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/行的正则表达式。(实际上,SubniC的正则表达式可能要好得多)。这将捕获您的1.1。TIBURON入口,因为它不是很好的形式。

我不确定ip2long是否会检查这一点,或者只是默默地丢弃看起来不像IP的字符串部分。

再往前一步,您可以阻止“保留”的IP地址和范围,如127.0.0.1、255.255.255.255等。

您可能还想添加一个黑名单,以过滤来自可疑网络的请求,或者来自您过去遇到过问题的客户端的请求。

我很好奇这个条目是怎么来的--攻击者不应该把这个值放在$_ server‘’REMOTE_ADDR‘中,除非他们已经攻破了底层操作系统,或者至少是apache (或者你正在运行的任何web服务器)。

您不会碰巧在客户端读取IP (使用javascript)?

票数 0
EN

Stack Overflow用户

发布于 2010-11-23 17:01:24

如果您只需要验证IP地址的格式是否正确,您可以使用如下所示的正则表达式。

编辑:

代码语言:javascript
复制
if (preg_match('/\A(?:^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)\Z/im', $subject)) {
    # Successful match
} else {
    # Match attempt failed
}

如果您想要更进一步,您可以对该IP执行ping操作,以发现它是否处于活动状态。

关于你的第二个问题,我不知道该说什么,我从来没有见过"1.1 TIBURON“的事情,

HTH

票数 1
EN

Stack Overflow用户

发布于 2010-11-23 20:31:33

我有这段代码。这已经有一段时间了,我不太记得它背后的一些决定,但我向你保证,它已经经过了彻底的测试

(实际上我只是稍微调整了一下,重命名了变量并添加了注释,所以我可能只是破坏了它:)

您可能会发现get_ip_addris_private_ip_addr函数很有用。

get_ip_addr可以接受IP地址或主机名。

代码语言:javascript
复制
<?php

function get_ip_addr($host){
    $long_ipaddr = my_ip2long($host);
    $host = trim($host);
    if( $long_ipaddr !== false ){
        $str_ip = long2ip($long_ipaddr); // Because of e.g. 245.254.245
        return $str_ip;
    }

    $ip_addr = @gethostbyname($host);
    if( $ip_addr and $ip_addr != -1  ){
        return $ip_addr;
    }

    return false;
}

function my_ip2long($ipaddr){
    $long_ip = ip2long($ipaddr);
    if( $long_ip === false ){
        return false;
    }

    // http://php.net/manual/en/function.ip2long.php says:
    //   Note:
    //   Because PHP's integer type is signed, and many IP addresses
    //   will result in negative integers, you need to use
    //   the "%u" formatter of sprintf() or printf() to get 
    //   the string representation of the unsigned IP address.
    $long_ip = sprintf("%u", $long_ip);
    return $long_ip;
}

function ip2bin($ip){
    $octets = explode(".", $ip);
    foreach($octets as $k => $v){
        $octets[$k] = str_pad(decbin($v), 8, "0", STR_PAD_LEFT);
    }
    return implode('', $octets);
}

function ip_in_range($ip, $prefix, $mask_len){
    $ip = ip2bin($ip);
    $prefix = ip2bin($prefix);

    $ip = substr($ip, 0, $mask_len);
    $prefix = substr($prefix, 0, $mask_len);

    // Watch out! Two numerical strings are converted to integers
    // when you use ==. This is trouble for long integers.
    // Using === skips this behaviour
    return ($ip === $prefix);
}


function is_private_ip_addr($ipaddr){
    if( "localhost" === $ipaddr ) return true;

    $long_ipaddr = my_ip2long($ipaddr);
    if( $long_ipaddr === false ){
        return false; // Shouldn't be calling this!
    }
    // Info below obtained from http://bugs.php.net/bug.php?id=47435#c145655
    //   Not sure why 127.0.0.0/8 isn't mentioned ...?
    //   Also, in IPv6 there's the multicast address range: ff00::/8s
    //
    //      IPv4 private ranges
    //        10.0.0.0/8     // private use network (rfc1918)
    //        172.16.0.0/12  // private use network (rfc1918)
    //        192.168.0.0/16 // private use network (rfc1918)
    //   
    //      IPv4 reserved ranges
    //        0.0.0.0/8      // "this" network (rfc1700)
    //        169.254.0.0/16 // link local network (rfc3927)
    //        192.0.2.0/24   // test net (rfc3330)
    //        224.0.0.0/4    // Multicast (rfc3171)
    //        240.0.0.0/4    // Reserved for Future Use (rfc1700)
    //   
    //      IPv6 Private range
    //        fc00::/7       // unique-local addresses (rfc4193)
    //     
    //      IPv6 Reserved ranges
    //        ::/128         // unspecified address (rfc4291)
    //        ::1/128        // loopback address (rfc4291)
    //        fe80::/10      // link local unicast (rfc4291)
    //        2001:db8::/32  // documentation addresses (rfc3849)
    //        5f00::/8       // 6Bone
    //        3ffe::/16      // 6Bone
    //        ::ffff:0:0/96  // IPv4-Mapped addresses (rfc4291)
    //        2001:10::/28   // ORCHID addresses (rfc4843)
    //        ::/0           // default unicast route address
    //
    // Anyways, this are the relevant RFCs:
    //    RFC 3330 (Sep 2002), "Special-Use IPv4 Addresses":
    //                              see section 3 for a nice table
    //    RFC 5156 (Apr 2008), "Special-Use IPv6 Addresses"
    // 

    // Also, this function currently only deals with IPv4 addresses,
    // since PHP's ip2long simply doesn't support IPv6 anyway.
    // You can't currently even trust long ints to have 64 bit,
    // so a 128 bit long int is out of the question.

    if( ip_in_range($ipaddr,   "127.0.0.0",  8) ) return true; // Loopback
    if( ip_in_range($ipaddr,    "10.0.0.0",  8) ) return true; // Private addresses (Class A range)
    if( ip_in_range($ipaddr,  "172.16.0.0", 12) ) return true; // Private addresses (Class B range)
    if( ip_in_range($ipaddr, "192.168.0.0", 16) ) return true; // Private addresses (Class C range)
    if( ip_in_range($ipaddr, "169.254.0.0", 16) ) return true; // "This" network
    if( ip_in_range($ipaddr,   "192.0.2.0", 24) ) return true; // "TEST-NET" (documentation and examples)
    if( ip_in_range($ipaddr,   "224.0.0.0",  4) ) return true; // Multicast
    if( ip_in_range($ipaddr,   "240.0.2.0",  4) ) return true; // Reserved for future use

    return false;
}

您可以考虑在许可的CC BY-SA下发布此代码。

你可以随心所欲地使用它,但如果你对它有所改进,请在这里告诉我们。

我在社区维基上给这篇文章做了标记。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4254149

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档