首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ip2location中的IP数据库及IPV4到IPV6的转换

ip2location中的IP数据库及IPV4到IPV6的转换
EN

Stack Overflow用户
提问于 2014-12-10 10:30:10
回答 1查看 1.3K关注 0票数 0

我正在尝试从ip2location使用IP到国家数据库。

我的问题是,IPV6数据库文件是否已经包含嵌入的IPV4地址,还是必须同时使用IPV4和IPV6数据库来覆盖所有版本的互联网IP范围。

我的意思是,如果我想同时支持IPV4和IPV6,我应该将两个数据库文件加载到同一个mysql表中,或者应该只使用IPV6。

我指的是文件IP2LOCATION-LIT-DB11.CSV.ZIP和IP2LOCATION-LITE-DB11.IPV6.CSV.ZIP

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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地址

代码语言:javascript
复制
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,这里有一些用于测试和清除的帮助代码。

代码语言:javascript
复制
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{$_};
        }
    }
}

这是测试代码的输出:

代码语言:javascript
复制
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

搜索数据库直到现在显示一切正常工作。

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

https://stackoverflow.com/questions/27398691

复制
相关文章

相似问题

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