From 3a3b5413b99d258030095425291f83874bf8ba90 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 7 May 2020 18:28:52 +0800 Subject: [PATCH] lncfg: allow no auth on private addresses --- lncfg/address.go | 39 +++++++++++++++++++++++++++--- lncfg/address_test.go | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/lncfg/address.go b/lncfg/address.go index 7fe2d71d..2c1770e4 100644 --- a/lncfg/address.go +++ b/lncfg/address.go @@ -54,10 +54,10 @@ func NormalizeAddresses(addrs []string, defaultPort string, // interface. func EnforceSafeAuthentication(addrs []net.Addr, macaroonsActive bool) error { // We'll now examine all addresses that this RPC server is listening - // on. If it's a localhost address, we'll skip it, otherwise, we'll - // return an error if macaroons are inactive. + // on. If it's a localhost address or a private address, we'll skip it, + // otherwise, we'll return an error if macaroons are inactive. for _, addr := range addrs { - if IsLoopback(addr.String()) || IsUnix(addr) { + if IsLoopback(addr.String()) || IsUnix(addr) || IsPrivate(addr) { continue } @@ -117,6 +117,39 @@ func IsUnix(addr net.Addr) bool { return strings.HasPrefix(addr.Network(), "unix") } +// IsPrivate returns true if the address is private. The definitions are, +// https://en.wikipedia.org/wiki/Link-local_address +// https://en.wikipedia.org/wiki/Multicast_address +// Local IPv4 addresses, https://tools.ietf.org/html/rfc1918 +// Local IPv6 addresses, https://tools.ietf.org/html/rfc4193 +func IsPrivate(addr net.Addr) bool { + switch addr := addr.(type) { + case *net.TCPAddr: + // Check 169.254.0.0/16 and fe80::/10. + if addr.IP.IsLinkLocalUnicast() { + return true + } + + // Check 224.0.0.0/4 and ff00::/8. + if addr.IP.IsLinkLocalMulticast() { + return true + } + + // Check 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. + if ip4 := addr.IP.To4(); ip4 != nil { + return ip4[0] == 10 || + (ip4[0] == 172 && ip4[1]&0xf0 == 16) || + (ip4[0] == 192 && ip4[1] == 168) + } + + // Check fc00::/7. + return len(addr.IP) == net.IPv6len && addr.IP[0]&0xfe == 0xfc + + default: + return false + } +} + // ParseAddressString converts an address in string format to a net.Addr that is // compatible with lnd. UDP is not supported because lnd needs reliable // connections. We accept a custom function to resolve any TCP addresses so diff --git a/lncfg/address_test.go b/lncfg/address_test.go index c35d7199..208b0407 100644 --- a/lncfg/address_test.go +++ b/lncfg/address_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcec" + "github.com/stretchr/testify/require" ) // addressTest defines a test vector for an address that contains the non- @@ -265,3 +266,57 @@ func validateAddr(t *testing.T, addr net.Addr, test addressTest) { ) } } + +func TestIsPrivate(t *testing.T) { + nonPrivateIPList := []net.IP{ + net.IPv4(169, 255, 0, 0), + {0xfe, 0x79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + net.IPv4(225, 0, 0, 0), + {0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + net.IPv4(11, 0, 0, 0), + net.IPv4(172, 15, 0, 0), + net.IPv4(192, 169, 0, 0), + {0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + net.IPv4(8, 8, 8, 8), + {2, 0, 0, 1, 4, 8, 6, 0, 4, 8, 6, 0, 8, 8, 8, 8}, + } + privateIPList := []net.IP{ + net.IPv4(169, 254, 0, 0), + {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + net.IPv4(224, 0, 0, 0), + {0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + net.IPv4(10, 0, 0, 1), + net.IPv4(172, 16, 0, 1), + net.IPv4(172, 31, 255, 255), + net.IPv4(192, 168, 0, 1), + {0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + } + + testParams := []struct { + name string + ipList []net.IP + private bool + }{ + { + "Non-private addresses should return false", + nonPrivateIPList, false, + }, + { + "Private addresses should return true", + privateIPList, true, + }, + } + + for _, tt := range testParams { + test := tt + t.Run(test.name, func(t *testing.T) { + for _, ip := range test.ipList { + addr := &net.TCPAddr{IP: ip} + require.Equal( + t, test.private, IsPrivate(addr), + "expected IP: %s to be %v", ip, test.private, + ) + } + }) + } +}