package main import ( "context" "errors" "fmt" "net" "os" "time" "go.wit.com/lib/protobuf/argvpb" "go.wit.com/log" ) func ipv6fails() bool { var s string var err error var addrs []net.IP addrs, err = LookupIPv6("ipv6.google.com") if err != nil { log.Printf("%v\n", err) log.Info(s) WarningForIpv4() s = "THIS FEATURE IS NOT SUPPORTED ON IPv4" argvpb.BadExit(s, err) } if len(addrs) == 0 { s = "THIS FEATURE IS NOT SUPPORTED ON IPv4." argvpb.BadExit(s, errors.New("IPv6 DNS is not returning ip addresses")) } addrs, err = LookupIPv6("cgit.grid.wit.com") if err != nil { log.Printf("%v\n", err) log.Info(s) WarningForIpv4() s = "Your OS is not correctly resolving IPv6 addresses." argvpb.BadExit(s, err) } if len(addrs) == 0 { s = "Your OS is not correctly resolving IPv6 addresses." argvpb.BadExit(s, errors.New("IPv6 DNS is not returning ip addresses")) } /* s, err = IPv6TestDNS() if err != nil { log.Printf("%v\n", err) log.Info(s) WarningForIpv4() s = "THIS FEATURE IS NOT SUPPORTED ON IPv4" argvpb.BadExit(s, nil) } */ s, err = IPv6TestPing() if err != nil { log.Printf("%v\n", err) log.Info(s) WarningForIpv4() s = "THIS FEATURE IS NOT SUPPORTED ON IPv4" argvpb.BadExit(s, nil) } return true } func WarningForIpv4() { log.Info("") pfile, _ := resources.ReadFile("resources/IPv4") log.Info("") log.Info(string(pfile)) } // The host we will try to connect to. // ipv6.google.com is a good choice as it's highly available and resolves only to AAAA records (IPv6). const ipv6TestHost = "ipv6.google.com" const testPort = "443" // HTTPS port, almost always open. func LookupIPv6(hostname string) ([]net.IP, error) { dnsTimeout := 2 * time.Second ctx, cancel := context.WithTimeout(context.Background(), dnsTimeout) defer cancel() addrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", ipv6TestHost) return addrs, err } // a better test that should fail right away func IPv6TestDNS() (string, error) { // --- Step 1: Fast DNS Lookup --- // We'll use a separate, short timeout just for the DNS resolution. // If DNS is broken, we'll know in a second or two. dnsTimeout := 2 * time.Second ctx, cancel := context.WithTimeout(context.Background(), dnsTimeout) defer cancel() // net.DefaultResolver.LookupIPAddr forces the resolver to look up the host. // We specify "ip6" to ensure we only get AAAA records. // addrs, err := net.DefaultResolver.LookupIPAddr(ctx, "ip6", ipv6TestHost) addrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", ipv6TestHost) if err != nil { fmt.Printf("IPv6 DNS resolution failed: %v\n", err) fmt.Println("This likely means your network cannot resolve IPv6 addresses.") return "IPv6 connectivity test failed", err } if len(addrs) == 0 { fmt.Printf("No IPv6 addresses found for %s\n", ipv6TestHost) return "this should happen", errors.New("good or bad") } testping(addrs) return "IPv6 DNS lookup worked.", nil } func testping(addrs []net.IP) { // If we get here, DNS is working. Let's use the first address we found. targetIP := addrs[0].String() fmt.Printf("Successfully resolved %s to IPv6 address: %s\n", ipv6TestHost, targetIP) // --- Step 2: Connection Attempt --- // Now we try to connect to the IP we found. This tests routing and firewalls. connectionTimeout := 3 * time.Second conn, err := net.DialTimeout("tcp6", net.JoinHostPort(targetIP, testPort), connectionTimeout) if err != nil { fmt.Printf("IPv6 connection to %s failed: %v\n", targetIP, err) fmt.Println("This likely means your network has an IPv6 routing or firewall issue.") os.Exit(1) } defer conn.Close() fmt.Println("IPv6 ping test successful.") } func IPv6TestPing() (string, error) { // We use net.DialTimeout to attempt a TCP connection. // By specifying "tcp6" as the network, we force the dialer to use IPv6 only. // If the system can't resolve the AAAA record or can't route to the IPv6 address, // this will fail. timeout := 2 * time.Second conn, err := net.DialTimeout("tcp6", net.JoinHostPort(ipv6TestHost, testPort), timeout) // Check the result. if err != nil { // The connection failed. This indicates that IPv6 is not working correctly. return "IPv6 ping test failed", err } // If we get here, the connection was successful. // It's good practice to close the connection we opened. conn.Close() return "IPv6 ping test successful.", nil }