我正在尝试从ip2location使用IP到国家数据库。
我的问题是,IPV6数据库文件是否已经包含嵌入的IPV4地址,还是必须同时使用IPV4和IPV6数据库来覆盖所有版本的互联网IP范围。
我的意思是,如果我想同时支持IPV4和IPV6,我应该将两个数据库文件加载到同一个mysql表中,或者应该只使用IPV6。
我指的是文件IP2LOCATION-LIT-DB11.CSV.ZIP和IP2LOCATION-LITE-DB11.IPV6.CSV.ZIP
发布于 2014-12-11 12:25:47
经过两天的搜索和测试,我正在回答我自己的问题。IPV4可以嵌入到IPV6中,该文件IP2LOCATION-LITE-DB11.IPV6.CSV.ZIP包含嵌入为IPV6的IPV4,所有IP都存储为十进制(39,0)。
我在这里使用IPV6数据库文件对IP的IPV4和IPV6的两个版本使用的诀窍是,在搜索数据库时将IPV4地址转换为IPV6,然后将其转换为Integer并进行正常搜索。这样,您的应用程序就可以同时支持IPV4和IPV6。
要将IPV4转换为IPV6,这篇wiki文章的答案是:
地址
IPv6 4-映射的IPv6地址
Hybrid dual-stack IPv6/IPv4 implementations recognize a special class of addresses,
the IPv4-mapped IPv6 addresses. In these addresses, the first 80 bits are zero, the
next 16 bits are one, and the remaining 32 bits are the IPv4 address. One may see these
addresses with the first 96 bits written in the standard IPv6 format, and the
remaining 32 bits written in the customary dot-decimal notation of IPv4. For example,
::ffff:192.0.2.128 represents the IPv4 address 192.0.2.128. A deprecated format for
IPv4-compatible IPv6 addresses was ::192.0.2.128这篇文章在这个问题上也很好:
IPv4 6/IPv4 4地址嵌入

您所需要做的就是在IP前面加上::ffff:,以便IP地址192.0.2.128将::ffff:192.0.2.128作为有效的IPV6。
下一步是将IP ( IPV4或IPV6 )转换为Decimail (39,0),现在可以正常地搜索数据库。
由于我使用Perl,这里有一些用于测试和清除的帮助代码。
use Net::IP ':PROC';
# IPV4 address
my $ipaddress = '197.36.107.146';
my $ip = new Net::IP ($ipaddress) or die (Net::IP::Error());
print ("IPV4 : ".$ip->ip()."\n");
print ("IPV4 Integer : ".$ip->intip()."\n");
print ("Version : ".$ip->version()."\n");
print ("Size: ".$ip->size()."\n");
print ("Len : ".$ip->prefixlen()."\n");
print ("Type: ".$ip->iptype()."\n");
print "\n";
# Convert IPV4 to IPV6. Just prepend ipv4 with '::ffff:'
my $ip = new Net::IP ("::ffff:".$ipaddress) or die (Net::IP::Error());
print ("IPV6 : ".$ip->ip()."\n");
print ("IPV6 Integer : ".$ip->intip()."\n");
print ("Version : ".$ip->version()."\n");
print ("Size: ".$ip->size()."\n");
print ("Len : ".$ip->prefixlen()."\n");
print ("Type: ".$ip->iptype()."\n");
print "\n";
# detect the user ip address and convert it
my $user_ip = get_user_ip();
$user_ip ||= $ipaddress; # just for testing on command line
print "Detected User IP address: $user_ip\n";
# if user remote address is IPV4 convert it to IPV6
if ($user_ip =~ /\./) {
# Convert IPV4 to IPV6
$user_ip = Net::IP->new("::ffff:$user_ip");
# Now convert it to Integer
$user_ip = $user_ip->intip();
}
else {
# Already IPV6, just convert to Integer
$user_ip = Net::IP->new($user_ip);
$user_ip = $user_ip->intip();
}
print "User IP address in IPV6 format: $user_ip\n";
#----------------------------------
# Now you can search the geo database with IPV4 and IPV6 stored as decimails
# select * from ip_country where $ipaddress<=ip_to limit 1
#----------------------------------
sub get_user_ip {
foreach (qw(REMOTE_ADDR HTTP_CLIENT_IP HTTP_X_FORWARDED_FOR HTTP_X_FORWARDED HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR HTTP_FORWARDED)) {
if ($ENV{$_}) {
return $ENV{$_};
}
}
}这是测试代码的输出:
IPV4 : 197.36.107.146
IPV4 Integer : 3307498386
Version : 4
Size: 1
Len : 32
Type: PUBLIC
IPV6 : 0000:0000:0000:0000:0000:ffff:c524:6b92
IPV6 Integer : 281473989241746
Version : 6
Size: 1
Len : 128
Type: IPV4MAP
Detected User IP address: 197.36.107.146
User IP address in IPV6 format: 281473989241746搜索数据库直到现在显示一切正常工作。
https://stackoverflow.com/questions/27398691
复制相似问题