简体   繁体   English

如何找到机器可以使用的 ipv6 地址的范围(前缀?),以及如何将 ipv6 的 su.net 转换为 ip 地址的片段?

[英]How to find range (prefix?) of ipv6 addresses that a machine can use, and how to transform a subnet of ipv6 into a slice of ip addresses?

There are many things I don't understand about ipv6 and.networking in general, which is why I need some further clarification on some the answers already posted to other questions.一般来说,关于 ipv6 和网络有很多我不了解的地方,这就是为什么我需要进一步澄清一些已经发布到其他问题的答案。 I'll list my questions, what I grasped from other answers, and what I'm still confused about.我将列出我的问题、我从其他答案中掌握的内容以及我仍然感到困惑的内容。

  1. Say I have a VPS with a /56 ipv6 su.net (256 * residential /64 su.nets) allotted to it.假设我有一个分配给它的 /56 ipv6 su.net (256 * residential /64 su.nets) 的 VPS。 How can I programmatically find the range (prefix?) of the ip's I "own".我如何以编程方式找到我“拥有”的 ip 的范围(前缀?)。 How to get IPv4 and IPv6 address of local machine? 如何获取本地机器的 IPv4 和 IPv6 地址? . . This is the answer I saw for this question: and what I think I understand is that I get the DNS hostname for the machine, then look up that same hostname to find the range.这是我看到的这个问题的答案:我想我的理解是我得到了机器的 DNS 主机名,然后查找相同的主机名以找到范围。 I'm wondering two things: How do I do this in Go, and我想知道两件事:如何在 Go 中执行此操作,以及

  2. How do I transfer this range ^ into a slice (array) of ipv6 addresses.如何将此范围 ^ 传输到 ipv6 地址的切片(数组)中。 For this specific use case: the ideal solution would be to only get one ipv6 address per \64 su.net, resulting in 256 seperate ips对于这个特定的用例:理想的解决方案是每个 \64 su.net 只获得一个ipv6 地址,从而产生 256 个独立的 ips

DNS is not very helpful in determining the local IP addresses, because a DNS entry is not required to make an IP address work, nor is it required to point to (only) the machine that you happen to run your program on. DNS对确定本地IP地址不是很有帮助,因为不需要DNS条目即可使IP地址正常工作,也不需要指向(仅)指向您要在其上运行程序的计算机。

Instead, inspect the network interfaces and their configuration: 相反,请检查网络接口及其配置:

package main

import (
    "fmt"
    "log"
    "net"
    "os"
    "text/tabwriter"
)

func main() {
    tw := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)

    ifaces, err := net.Interfaces()
    if err != nil {
        log.Fatal(err)
    }

    for _, iface := range ifaces {
        addrs, err := iface.Addrs()
        if err != nil {
            log.Fatal(err)
        }
        for _, addr := range addrs {
            addr, ok := addr.(*net.IPNet)
            if !ok {
                // Not an IP interface
                continue
            }
            if addr.IP.To4() != nil {
                // Skip IPv4 addresses
                continue
            }

            fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", 
                iface.Name, addr.String(), addr.IP, addr.Mask)
        }
    }
    tw.Flush()
}

For my local machine the output is: 对于我的本地计算机,输出为:

lo          ::1/128                      ::1                       ffffffffffffffffffffffffffffffff
enp2s0      fe80::52e5:49ff:fe3b:107a/64 fe80::52e5:49ff:fe3b:107a ffffffffffffffff0000000000000000
docker0     fe80::42:afff:fedb:7389/64   fe80::42:afff:fedb:7389   ffffffffffffffff0000000000000000
tun0        fe80::f22c:2d3b:a5a0:1b61/64 fe80::f22c:2d3b:a5a0:1b61 ffffffffffffffff0000000000000000
vethd176f0c fe80::1cc1:65ff:fe39:feff/64 fe80::1cc1:65ff:fe39:feff ffffffffffffffff0000000000000000

Note that these addresses are not necessarily reachable from the Internet. 请注意,这些地址不一定可以从Internet到达。 This all depends on how the routing of the hoster works. 这一切都取决于托管者的路由工作方式。 In any kind of cloud setup, you are almost always better off querying the providers APIs. 在任何类型的云设置中,查询供应商API几乎总是更好。


To list all /64 subnets in a particular /56 subnet, you have to leave the 56 upper bits of the subnet address as they are and permute the following 64-56 = 8 bits (which happens to be the eigth byte): 要列出特定/ 56子网中的所有/ 64子网,您必须保留子网地址的56个高位不变,并置换以下64-56 = 8位(恰好是第8个字节):

package main

import (
    "fmt"
    "net"
)

func main() {
    _, subnet, _ := net.ParseCIDR("2001:db8::/56")
    fmt.Println(subnet)

    subnet.Mask = net.CIDRMask(64, 128) // change mask to /64

    for i := 0; i <= 0xff; i++ {
        subnet.IP[7] = byte(i) // permute the 8th byte
        fmt.Println("\t", subnet)
    }

    // Output:
    // 2001:db8::/56
    //          2001:db8::/64
    //          2001:db8:0:1::/64
    //          2001:db8:0:2::/64
    //          2001:db8:0:3::/64
    //          2001:db8:0:4::/64
    //          2001:db8:0:5::/64
    //          2001:db8:0:6::/64
    //          2001:db8:0:7::/64
    //          2001:db8:0:8::/64
    // [...]
}

Regarding the second part of your question, "How do I transfer this range ^ into a slice (array) of ipv6 addresses"关于问题的第二部分,“我如何将这个范围 ^ 转移到 ipv6 地址的切片(数组)中”

The IPAddress Go library can do this with polymorphic code that works with both IPv4 and IPv6 addresses and all prefix lengths. IPAddress Go 库可以使用适用于 IPv4 和 IPv6 地址以及所有前缀长度的多态代码来执行此操作。 Repository here .存储库在这里 Disclaimer: I am the project manager.免责声明:我是项目经理。

addrStr := "2001:db8::/56"
addr := ipaddr.NewIPAddressString(addrStr).GetAddress()
addrAdjusted := addr.SetPrefixLen(64) // adjust prefix
iterator := addrAdjusted.PrefixIterator()
var blocks []*ipaddr.IPAddress
for iterator.HasNext() {
    blocks = append(blocks, iterator.Next())
}

// print the details
fmt.Println("first and last blocks are",
    addrAdjusted.GetLower().ToPrefixBlock(), "and",
    addrAdjusted.GetUpper().ToPrefixBlock())
fmt.Print("list: ")
for i, addr := range blocks {
    if i < 3 || len(blocks)-i <= 3 {
        if i > 0 {
            fmt.Print(", ")
        }
        fmt.Print(addr)
    } else if i == 3 {
        fmt.Print(", ...")
    }
}

Output: Output:

first and last blocks are 2001:db8::/64 and 2001:db8:0:ff::/64
list: 2001:db8::/64, 2001:db8:0:1::/64, 2001:db8:0:2::/64, ..., 2001:db8:0:fd::/64, 2001:db8:0:fe::/64, 2001:db8:0:ff::/64

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM