Как найти диапазон (префикс?) Адресов ipv6, который может использовать машина, и как преобразовать подсеть ipv6 в часть адресов ip? - PullRequest
0 голосов
/ 20 ноября 2018

Есть много вещей, которые я не понимаю в ipv6 и работе с сетями в целом, поэтому мне нужны некоторые дополнительные разъяснения по некоторым ответам, уже опубликованным на другие вопросы. Я перечислю свои вопросы, что я понял из других ответов, и что я все еще смущен.

  1. Допустим, у меня выделен VPS с подсетью / 56 ipv6 (256 * жилых / 64 подсети). Как я могу программно найти диапазон (префикс?) Ip's I "own". Как получить IPv4 и IPv6-адрес локальной машины? . Это ответ, который я увидел на этот вопрос: и то, что я понимаю, я понимаю, что я получаю DNS-имя хоста для машины, а затем ищу это же имя хоста, чтобы найти диапазон. Мне интересно две вещи: как мне это сделать в Go, и

  2. Как передать этот диапазон ^ в срез (массив) адресов ipv6. Для этого конкретного случая использования: идеальным решением было бы получить только один ipv6-адрес на \ 64 подсети, что привело бы к 256 отдельным ips

1 Ответ

0 голосов
/ 20 ноября 2018

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

Обратите внимание, что эти адреса не всегда доступныиз Интернета.Все зависит от того, как работает маршрутизация хостера.При любой облачной настройке вам почти всегда лучше запрашивать API провайдеров.


Чтобы вывести список всех / 64 подсетей в определенной подсети / 56, вы должны оставить 56 старших битовАдрес подсети, как они есть, и переставить следующие 64-56 = 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
    // [...]
}
...