英文:
IP address to Int
问题
所以我遇到了将IPv4和IPv6转换为整数的问题,但是我找到了一个方便的Go脚本可以实现,但是我需要将其转换为Node.js。
我已经尝试了NPM中的插件,包括ip2int
,但似乎有问题,而且只适用于IPv4。
我想知道是否有人知道如何将Go代码转换为Node.js的JavaScript。因为我知道以下代码在Go中可以工作。
package main
import (
"fmt"
"math/big"
"net"
)
func Ip2Int(ip net.IP) *big.Int {
i := big.NewInt(0)
i.SetBytes(ip)
return i
}
func main() {
fmt.Println(Ip2Int(net.ParseIP("20.36.77.12").To4()).String())
fmt.Println(Ip2Int(net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334").To16()).String())
}
我们需要将IP地址解析为整数的原因是,当我们接收到IP地址时,我们可以搜索以查看该IP地址是否在我们收集的IP地址范围内。
例如,RAPD返回:
"startAddress": "35.192.0.0",
"endAddress": "35.207.255.255",
因此,如果我们将这两个地址都转换为整数,我们可以将它们存储在数据库中,并进行gte
或lte
搜索,以查看IP地址是否在存储的值之间。
英文:
So I am having an issue with converting IPv4 and IPv6 to Int, I however have found this handy Go script which does it, however I need it for NodeJS.
I have tried the plugins in NPM including ip2int
but it seems to be broken, and only work for IPv4.
I am wondering if anyone would know how to convert GO into Javascript for nodeJS. As I know the following code works in Go.
package main
import (
"fmt"
"math/big"
"net"
)
func Ip2Int(ip net.IP) *big.Int {
i := big.NewInt(0)
i.SetBytes(ip)
return i
}
func main() {
fmt.Println(Ip2Int(net.ParseIP("20.36.77.12").To4()).String())
fmt.Println(Ip2Int(net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334").To16()).String())
}
The reason why we need to parse the IP addresses to int is so that when we receive the IP address we can search to see if that IP address is inside one of the ranges of IP addresses that we have collected.
For example RAPD returns
"startAddress": "35.192.0.0",
"endAddress": "35.207.255.255",
so if we convert both of those to int we can store them in our DB and do a gte
or lte
search and see if the IP address is in between any of the stored values.
答案1
得分: 4
更新:根据下面的评论,在IPv6的情况下使用BigInt
请参考这个解决方案。
对于IPv4,请使用以下代码:
ipv4.split('.').reduce(function(int, value) { return int * 256 + +value })
对于IPv6,您首先需要解析十六进制值,十六进制值表示2个字节:
ipv6.split(':').map(str => Number('0x'+str)).reduce(function(int, value) { return BigInt(int) * BigInt(65536) + BigInt(+value) })
我还将IPv6的解决方案添加到了引用的gist中。
英文:
Update: use BigInt's in case of ipv6 in response to comments below
See this solution.
For IPv4 use:
ipv4.split('.').reduce(function(int, value) { return int * 256 + +value })
For IPv6 you first need to parse the hex values and the hex values represent 2 bytes:
ipv6.split(':').split(':').map(str => Number('0x'+str)).reduce(function(int, value) { return BigInt(int) * BigInt(65536) + BigInt(+value) })
I've also added the ipv6 solution to the referenced gist.
答案2
得分: 1
const IPv4ToInt = ipv4 => ipv4.split(".").reduce((a, b) => a << 8 | b) >>> 0;
和一个简单的IPv6实现:
const IPv6ToBigInt = ipv6 => BigInt("0x" + ipv6.toLowerCase().split(":").map(v => v.padStart(4, 0)).join(""));
或者一个更详细的实现:
// 将多种IPv6格式规范化为长版本
// 在这种格式下,字符串排序等同于数字排序
const normalizeIPv6 = (ipv6) => {
// 对于嵌入IPv4的IPv6
// 如 "::ffff:127.0.0.1"
ipv6 = ipv6.replace(/\d+\.\d+\.\d+\.\d+$/, ipv4 => {
const [a, b, c, d] = ipv4.split(".");
return (a << 8 | b).toString(16) + ":" + (c << 8 | d).toString(16)
});
// 简写的IP
// 如 "2001:db8::1428:57ab"
ipv6 = ipv6.replace("::", ":".repeat(10 - ipv6.split(":").length));
return ipv6.toLowerCase().split(":").map(v => v.padStart(4, 0)).join(":");
}
const IPv6ToBigInt = ipv6 => BigInt("0x" + normalizeIPv6(ipv6).replaceAll(":", ""));
// 测试
[
"2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
"2001:0db8:85a3:08d3:1319:8a2e:0370:7345", // 检查精度
"2001:db8:0:8d3:0:8a2e:70:7344",
"2001:db8:0:0:0:0:1428:57ab",
"2001:db8::1428:57ab",
"2001:0db8:0:0:8d3:0:0:0",
"2001:db8:0:0:8d3::",
"2001:db8::8d3:0:0:0",
"::ffff:127.0.0.1",
"::ffff:7f00:1"
].forEach(ip => console.log({
ip,
normalized: normalizeIPv6(ip),
bigInt: IPv6ToBigInt(ip).toString() // toString() or SO console doesn't print them.
}));
英文:
const IPv4ToInt = ipv4 => ipv4.split(".").reduce((a, b) => a << 8 | b) >>> 0;
and a simple IPv6 implementation:
const IPv6ToBigInt = ipv6 => BigInt("0x" + ipv6.toLowerCase().split(":").map(v => v.padStart(4, 0)).join(""));
or a more extensive one
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// normalizes several IPv6 formats to the long version
// in this format a string sort is equivalent to a numeric sort
const normalizeIPv6 = (ipv6) => {
// for embedded IPv4 in IPv6.
// like "::ffff:127.0.0.1"
ipv6 = ipv6.replace(/\d+\.\d+\.\d+\.\d+$/, ipv4 => {
const [a, b, c, d] = ipv4.split(".");
return (a << 8 | b).toString(16) + ":" + (c << 8 | d).toString(16)
});
// shortened IPs
// like "2001:db8::1428:57ab"
ipv6 = ipv6.replace("::", ":".repeat(10 - ipv6.split(":").length));
return ipv6.toLowerCase().split(":").map(v => v.padStart(4, 0)).join(":");
}
const IPv6ToBigInt = ipv6 => BigInt("0x" + normalizeIPv6(ipv6).replaceAll(":", ""));
// tests
[
"2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
"2001:0db8:85a3:08d3:1319:8a2e:0370:7345", // check precision
"2001:db8:0:8d3:0:8a2e:70:7344",
"2001:db8:0:0:0:0:1428:57ab",
"2001:db8::1428:57ab",
"2001:0db8:0:0:8d3:0:0:0",
"2001:db8:0:0:8d3::",
"2001:db8::8d3:0:0:0",
"::ffff:127.0.0.1",
"::ffff:7f00:1"
].forEach(ip => console.log({
ip,
normalized: normalizeIPv6(ip),
bigInt: IPv6ToBigInt(ip).toString() // toString() or SO console doesn't print them.
}));
<!-- language: lang-css -->
.as-console-wrapper{top:0;max-height:100%!important}
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论