繁体   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?

一般来说,关于 ipv6 和网络有很多我不了解的地方,这就是为什么我需要进一步澄清一些已经发布到其他问题的答案。 我将列出我的问题、我从其他答案中掌握的内容以及我仍然感到困惑的内容。

  1. 假设我有一个分配给它的 /56 ipv6 su.net (256 * residential /64 su.nets) 的 VPS。 我如何以编程方式找到我“拥有”的 ip 的范围(前缀?)。 如何获取本地机器的 IPv4 和 IPv6 地址? . 这是我看到的这个问题的答案:我想我的理解是我得到了机器的 DNS 主机名,然后查找相同的主机名以找到范围。 我想知道两件事:如何在 Go 中执行此操作,以及

  2. 如何将此范围 ^ 传输到 ipv6 地址的切片(数组)中。 对于这个特定的用例:理想的解决方案是每个 \64 su.net 只获得一个ipv6 地址,从而产生 256 个独立的 ips

DNS对确定本地IP地址不是很有帮助,因为不需要DNS条目即可使IP地址正常工作,也不需要指向(仅)指向您要在其上运行程序的计算机。

相反,请检查网络接口及其配置:

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()
}

对于我的本地计算机,输出为:

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

请注意,这些地址不一定可以从Internet到达。 这一切都取决于托管者的路由工作方式。 在任何类型的云设置中,查询供应商API几乎总是更好。


要列出特定/ 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
    // [...]
}

关于问题的第二部分,“我如何将这个范围 ^ 转移到 ipv6 地址的切片(数组)中”

IPAddress Go 库可以使用适用于 IPv4 和 IPv6 地址以及所有前缀长度的多态代码来执行此操作。 存储库在这里 免责声明:我是项目经理。

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:

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