github.com/MetalBlockchain/metalgo@v1.11.9/utils/dynamicip/opendns_resolver.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package dynamicip
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"net"
    10  	"net/netip"
    11  
    12  	"github.com/MetalBlockchain/metalgo/utils/ips"
    13  )
    14  
    15  const openDNSUrl = "resolver1.opendns.com:53"
    16  
    17  var (
    18  	errOpenDNSNoIP = errors.New("openDNS returned no ip")
    19  
    20  	_ Resolver = (*openDNSResolver)(nil)
    21  )
    22  
    23  // openDNSResolver resolves our public IP using openDNS
    24  type openDNSResolver struct {
    25  	resolver *net.Resolver
    26  }
    27  
    28  func newOpenDNSResolver() Resolver {
    29  	return &openDNSResolver{
    30  		resolver: &net.Resolver{
    31  			PreferGo: true,
    32  			Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
    33  				d := net.Dialer{}
    34  				return d.DialContext(ctx, "udp", openDNSUrl)
    35  			},
    36  		},
    37  	}
    38  }
    39  
    40  func (r *openDNSResolver) Resolve(ctx context.Context) (netip.Addr, error) {
    41  	resolvedIPs, err := r.resolver.LookupIP(ctx, "ip", "myip.opendns.com")
    42  	if err != nil {
    43  		return netip.Addr{}, err
    44  	}
    45  	for _, ip := range resolvedIPs {
    46  		if addr, ok := ips.AddrFromSlice(ip); ok {
    47  			return addr, nil
    48  		}
    49  	}
    50  	return netip.Addr{}, errOpenDNSNoIP
    51  }