github.com/decred/dcrlnd@v0.7.6/lncfg/address.go (about)

     1  package lncfg
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"net"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    13  	"github.com/decred/dcrlnd/lnwire"
    14  	"github.com/decred/dcrlnd/tor"
    15  )
    16  
    17  var (
    18  	loopBackAddrs = []string{"localhost", "127.0.0.1", "[::1]"}
    19  )
    20  
    21  // TCPResolver is a function signature that resolves an address on a given
    22  // network.
    23  type TCPResolver = func(network, addr string) (*net.TCPAddr, error)
    24  
    25  // NormalizeAddresses returns a new slice with all the passed addresses
    26  // normalized with the given default port and all duplicates removed.
    27  func NormalizeAddresses(addrs []string, defaultPort string,
    28  	tcpResolver TCPResolver) ([]net.Addr, error) {
    29  
    30  	result := make([]net.Addr, 0, len(addrs))
    31  	seen := map[string]struct{}{}
    32  
    33  	for _, addr := range addrs {
    34  		parsedAddr, err := ParseAddressString(
    35  			addr, defaultPort, tcpResolver,
    36  		)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("parse address %s failed: %w",
    39  				addr, err)
    40  		}
    41  
    42  		if _, ok := seen[parsedAddr.String()]; !ok {
    43  			result = append(result, parsedAddr)
    44  			seen[parsedAddr.String()] = struct{}{}
    45  		}
    46  	}
    47  
    48  	return result, nil
    49  }
    50  
    51  // EnforceSafeAuthentication enforces "safe" authentication taking into account
    52  // the interfaces that the RPC servers are listening on, and if macaroons and
    53  // TLS is activated or not. To protect users from using dangerous config
    54  // combinations, we'll prevent disabling authentication if the server is
    55  // listening on a public interface.
    56  func EnforceSafeAuthentication(addrs []net.Addr, macaroonsActive,
    57  	tlsActive bool) error {
    58  
    59  	// We'll now examine all addresses that this RPC server is listening
    60  	// on. If it's a localhost address we'll skip it, otherwise, we'll
    61  	// return an error if macaroons are inactive.
    62  	for _, addr := range addrs {
    63  		if IsLoopback(addr.String()) || IsUnix(addr) {
    64  			continue
    65  		}
    66  
    67  		if !macaroonsActive {
    68  			return fmt.Errorf("detected RPC server listening on "+
    69  				"publicly reachable interface %v with "+
    70  				"authentication disabled! Refusing to start "+
    71  				"with --no-macaroons specified", addr)
    72  		}
    73  
    74  		if !tlsActive {
    75  			return fmt.Errorf("detected RPC server listening on "+
    76  				"publicly reachable interface %v with "+
    77  				"encryption disabled! Refusing to start "+
    78  				"with --no-rest-tls specified", addr)
    79  		}
    80  	}
    81  
    82  	return nil
    83  }
    84  
    85  // parseNetwork parses the network type of the given address.
    86  func parseNetwork(addr net.Addr) string {
    87  	switch addr := addr.(type) {
    88  	// TCP addresses resolved through net.ResolveTCPAddr give a default
    89  	// network of "tcp", so we'll map back the correct network for the given
    90  	// address. This ensures that we can listen on the correct interface
    91  	// (IPv4 vs IPv6).
    92  	case *net.TCPAddr:
    93  		if addr.IP.To4() != nil {
    94  			return "tcp4"
    95  		}
    96  		return "tcp6"
    97  
    98  	default:
    99  		return addr.Network()
   100  	}
   101  }
   102  
   103  // ListenOnAddress creates a listener that listens on the given address.
   104  func ListenOnAddress(addr net.Addr) (net.Listener, error) {
   105  	return net.Listen(parseNetwork(addr), addr.String())
   106  }
   107  
   108  // TLSListenOnAddress creates a TLS listener that listens on the given address.
   109  func TLSListenOnAddress(addr net.Addr,
   110  	config *tls.Config) (net.Listener, error) {
   111  	return tls.Listen(parseNetwork(addr), addr.String(), config)
   112  }
   113  
   114  // IsLoopback returns true if an address describes a loopback interface.
   115  func IsLoopback(addr string) bool {
   116  	for _, loopback := range loopBackAddrs {
   117  		if strings.Contains(addr, loopback) {
   118  			return true
   119  		}
   120  	}
   121  
   122  	return false
   123  }
   124  
   125  // isIPv6Host returns true if the host is IPV6 and false otherwise.
   126  func isIPv6Host(host string) bool {
   127  	v6Addr := net.ParseIP(host)
   128  	if v6Addr == nil {
   129  		return false
   130  	}
   131  
   132  	// The documentation states that if the IP address is an IPv6 address,
   133  	// then To4() will return nil.
   134  	return v6Addr.To4() == nil
   135  }
   136  
   137  // IsUnix returns true if an address describes an Unix socket address.
   138  func IsUnix(addr net.Addr) bool {
   139  	return strings.HasPrefix(addr.Network(), "unix")
   140  }
   141  
   142  // IsPrivate returns true if the address is private. The definitions are,
   143  //
   144  //	https://en.wikipedia.org/wiki/Link-local_address
   145  //	https://en.wikipedia.org/wiki/Multicast_address
   146  //	Local IPv4 addresses, https://tools.ietf.org/html/rfc1918
   147  //	Local IPv6 addresses, https://tools.ietf.org/html/rfc4193
   148  func IsPrivate(addr net.Addr) bool {
   149  	switch addr := addr.(type) {
   150  	case *net.TCPAddr:
   151  		// Check 169.254.0.0/16 and fe80::/10.
   152  		if addr.IP.IsLinkLocalUnicast() {
   153  			return true
   154  		}
   155  
   156  		// Check 224.0.0.0/4 and ff00::/8.
   157  		if addr.IP.IsLinkLocalMulticast() {
   158  			return true
   159  		}
   160  
   161  		// Check 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
   162  		if ip4 := addr.IP.To4(); ip4 != nil {
   163  			return ip4[0] == 10 ||
   164  				(ip4[0] == 172 && ip4[1]&0xf0 == 16) ||
   165  				(ip4[0] == 192 && ip4[1] == 168)
   166  		}
   167  
   168  		// Check fc00::/7.
   169  		return len(addr.IP) == net.IPv6len && addr.IP[0]&0xfe == 0xfc
   170  
   171  	default:
   172  		return false
   173  	}
   174  }
   175  
   176  // ParseAddressString converts an address in string format to a net.Addr that is
   177  // compatible with lnd. UDP is not supported because lnd needs reliable
   178  // connections. We accept a custom function to resolve any TCP addresses so
   179  // that caller is able control exactly how resolution is performed.
   180  func ParseAddressString(strAddress string, defaultPort string,
   181  	tcpResolver TCPResolver) (net.Addr, error) {
   182  
   183  	var parsedNetwork, parsedAddr string
   184  
   185  	// Addresses can either be in network://address:port format,
   186  	// network:address:port, address:port, or just port. We want to support
   187  	// all possible types.
   188  	if strings.Contains(strAddress, "://") {
   189  		parts := strings.Split(strAddress, "://")
   190  		parsedNetwork, parsedAddr = parts[0], parts[1]
   191  	} else if strings.Contains(strAddress, ":") {
   192  		parts := strings.Split(strAddress, ":")
   193  		parsedNetwork = parts[0]
   194  		parsedAddr = strings.Join(parts[1:], ":")
   195  	}
   196  
   197  	// Only TCP and Unix socket addresses are valid. We can't use IP or
   198  	// UDP only connections for anything we do in lnd.
   199  	switch parsedNetwork {
   200  	case "unix", "unixpacket":
   201  		return net.ResolveUnixAddr(parsedNetwork, parsedAddr)
   202  
   203  	case "tcp", "tcp4", "tcp6":
   204  		return tcpResolver(
   205  			parsedNetwork, verifyPort(parsedAddr, defaultPort),
   206  		)
   207  
   208  	case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram":
   209  		return nil, fmt.Errorf("only TCP or unix socket "+
   210  			"addresses are supported: %s", parsedAddr)
   211  
   212  	default:
   213  		// We'll now possibly apply the default port, use the local
   214  		// host short circuit, or parse out an all interfaces listen.
   215  		addrWithPort := verifyPort(strAddress, defaultPort)
   216  		rawHost, rawPort, _ := net.SplitHostPort(addrWithPort)
   217  
   218  		// If we reach this point, then we'll check to see if we have
   219  		// an onion addresses, if so, we can directly pass the raw
   220  		// address and port to create the proper address.
   221  		if tor.IsOnionHost(rawHost) {
   222  			portNum, err := strconv.Atoi(rawPort)
   223  			if err != nil {
   224  				return nil, err
   225  			}
   226  
   227  			return &tor.OnionAddr{
   228  				OnionService: rawHost,
   229  				Port:         portNum,
   230  			}, nil
   231  		}
   232  
   233  		// Otherwise, we'll attempt the resolve the host. The Tor
   234  		// resolver is unable to resolve local or IPv6 addresses, so
   235  		// we'll use the system resolver instead.
   236  		if rawHost == "" || IsLoopback(rawHost) ||
   237  			isIPv6Host(rawHost) {
   238  
   239  			return net.ResolveTCPAddr("tcp", addrWithPort)
   240  		}
   241  
   242  		// If we've reached this point, then it's possible that this
   243  		// resolve returns an error if it isn't able to resolve the
   244  		// host. For eaxmple, local entries in /etc/hosts will fail to
   245  		// be resolved by Tor. In order to handle this case, we'll fall
   246  		// back to the normal system resolver if we fail with an
   247  		// identifiable error.
   248  		addr, err := tcpResolver("tcp", addrWithPort)
   249  		if err != nil {
   250  			torErrStr := "tor host is unreachable"
   251  			if strings.Contains(err.Error(), torErrStr) {
   252  				return net.ResolveTCPAddr("tcp", addrWithPort)
   253  			}
   254  
   255  			return nil, err
   256  		}
   257  
   258  		return addr, nil
   259  	}
   260  }
   261  
   262  // ParseLNAddressString converts a string of the form <pubkey>@<addr> into an
   263  // lnwire.NetAddress. The <pubkey> must be presented in hex, and result in a
   264  // 33-byte, compressed public key that lies on the secp256k1 curve. The <addr>
   265  // may be any address supported by ParseAddressString. If no port is specified,
   266  // the defaultPort will be used. Any tcp addresses that need resolving will be
   267  // resolved using the custom TCPResolver.
   268  func ParseLNAddressString(strAddress string, defaultPort string,
   269  	tcpResolver TCPResolver) (*lnwire.NetAddress, error) {
   270  
   271  	// Split the address string around the @ sign.
   272  	parts := strings.Split(strAddress, "@")
   273  
   274  	// The string is malformed if there are not exactly two parts.
   275  	if len(parts) != 2 {
   276  		return nil, fmt.Errorf("invalid lightning address %s: "+
   277  			"must be of the form <pubkey-hex>@<addr>", strAddress)
   278  	}
   279  
   280  	// Now, take the first portion as the hex pubkey, and the latter as the
   281  	// address string.
   282  	parsedPubKey, parsedAddr := parts[0], parts[1]
   283  
   284  	// Decode the hex pubkey to get the raw compressed pubkey bytes.
   285  	pubKeyBytes, err := hex.DecodeString(parsedPubKey)
   286  	if err != nil {
   287  		return nil, fmt.Errorf("invalid lightning address pubkey: %v", err)
   288  	}
   289  
   290  	// The compressed pubkey should have a length of exactly 33 bytes.
   291  	if len(pubKeyBytes) != 33 {
   292  		return nil, fmt.Errorf("invalid lightning address pubkey: "+
   293  			"length must be 33 bytes, found %d", len(pubKeyBytes))
   294  	}
   295  
   296  	// Parse the pubkey bytes to verify that it corresponds to valid public
   297  	// key on the secp256k1 curve.
   298  	pubKey, err := secp256k1.ParsePubKey(pubKeyBytes)
   299  	if err != nil {
   300  		return nil, fmt.Errorf("invalid lightning address pubkey: %v", err)
   301  	}
   302  
   303  	// Finally, parse the address string using our generic address parser.
   304  	addr, err := ParseAddressString(parsedAddr, defaultPort, tcpResolver)
   305  	if err != nil {
   306  		return nil, fmt.Errorf("invalid lightning address address: %v", err)
   307  	}
   308  
   309  	return &lnwire.NetAddress{
   310  		IdentityKey: pubKey,
   311  		Address:     addr,
   312  	}, nil
   313  }
   314  
   315  // verifyPort makes sure that an address string has both a host and a port. If
   316  // there is no port found, the default port is appended. If the address is just
   317  // a port, then we'll assume that the user is using the short cut to specify a
   318  // localhost:port address.
   319  func verifyPort(address string, defaultPort string) string {
   320  	host, port, err := net.SplitHostPort(address)
   321  	if err != nil {
   322  		// If the address itself is just an integer, then we'll assume
   323  		// that we're mapping this directly to a localhost:port pair.
   324  		// This ensures we maintain the legacy behavior.
   325  		if _, err := strconv.Atoi(address); err == nil {
   326  			return net.JoinHostPort("localhost", address)
   327  		}
   328  
   329  		// Otherwise, we'll assume that the address just failed to
   330  		// attach its own port, so we'll use the default port. In the
   331  		// case of IPv6 addresses, if the host is already surrounded by
   332  		// brackets, then we'll avoid using the JoinHostPort function,
   333  		// since it will always add a pair of brackets.
   334  		if strings.HasPrefix(address, "[") {
   335  			return address + ":" + defaultPort
   336  		}
   337  		return net.JoinHostPort(address, defaultPort)
   338  	}
   339  
   340  	// In the case that both the host and port are empty, we'll use the
   341  	// default port.
   342  	if host == "" && port == "" {
   343  		return ":" + defaultPort
   344  	}
   345  
   346  	return address
   347  }
   348  
   349  // ClientAddressDialer creates a gRPC dialer that can also dial unix socket
   350  // addresses instead of just TCP addresses.
   351  func ClientAddressDialer(defaultPort string) func(context.Context,
   352  	string) (net.Conn, error) {
   353  
   354  	return func(ctx context.Context, addr string) (net.Conn, error) {
   355  		parsedAddr, err := ParseAddressString(
   356  			addr, defaultPort, net.ResolveTCPAddr,
   357  		)
   358  		if err != nil {
   359  			return nil, err
   360  		}
   361  
   362  		d := net.Dialer{}
   363  		return d.DialContext(
   364  			ctx, parsedAddr.Network(), parsedAddr.String(),
   365  		)
   366  	}
   367  }