实际上这是一个两部分的问题:
首先,ip2long是一个很好的IP验证器吗?假设有人在表单中插入IP,我想验证它是否正确。是否可以检查ip2long是否返回FALSE?
第二:您如何看待访问者的IP,并拒绝访问,如果它不是有效的IP?看着我的访客的ips,有时我会发现像“1.1 TIBURON”这样的东西。那是什么意思?我听到'欺骗ip'的表达,是什么呢?它与垃圾邮件机器人有关吗?
答案 0 :(得分:1)
如果您只需要确认IP地址格式正确,您可以使用常规表达式,如下图所示。
修改强>
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 :(得分:0)
取决于您希望验证的彻底程度。对形式良好的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(或者你正在运行的任何网络服务器)。
您是否有机会在客户端上阅读IP(使用javascript)?
答案 2 :(得分:0)
我有这个代码。已经有一段时间了,我不太清楚它背后的一些决定,但我向你保证它已经过彻底的测试。 (实际上我只是稍微调整一下,重命名变量并添加注释,所以我可能就把它弄坏了:)
您可能会发现get_ip_addr
和is_private_ip_addr
功能很有用
get_ip_addr
可以同时使用IP地址或主机名。
<?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下发布此代码
做任何你想要的东西,但如果你改进它,请在这里告诉我们。
我正在标记这个帖子社区wiki ..