Merge pull request #4473 from yyforyongyu/allow-no-auth-private-addr
lncfg: allow no auth on private addresses
This commit is contained in:
commit
ffe7c3e626
@ -170,7 +170,7 @@ type Config struct {
|
|||||||
TLSAutoRefresh bool `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed"`
|
TLSAutoRefresh bool `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed"`
|
||||||
TLSDisableAutofill bool `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate, use first --tlsextradomain as Common Name instead, if set"`
|
TLSDisableAutofill bool `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate, use first --tlsextradomain as Common Name instead, if set"`
|
||||||
|
|
||||||
NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication"`
|
NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication, can only be used if server is not listening on a public interface."`
|
||||||
AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"`
|
AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"`
|
||||||
ReadMacPath string `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"`
|
ReadMacPath string `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"`
|
||||||
InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to the invoice-only macaroon for lnd's RPC and REST services if it doesn't exist"`
|
InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to the invoice-only macaroon for lnd's RPC and REST services if it doesn't exist"`
|
||||||
|
@ -81,7 +81,14 @@ methods. This means a few important things:
|
|||||||
You can also run `lnd` with the `--no-macaroons` option, which skips the
|
You can also run `lnd` with the `--no-macaroons` option, which skips the
|
||||||
creation of the macaroon files and all macaroon checks within the RPC server.
|
creation of the macaroon files and all macaroon checks within the RPC server.
|
||||||
This means you can still pass a macaroon to the RPC server with a client, but
|
This means you can still pass a macaroon to the RPC server with a client, but
|
||||||
it won't be checked for validity.
|
it won't be checked for validity. Note that disabling authentication of a server
|
||||||
|
that's listening on a public interface is not allowed. This means the
|
||||||
|
`--no-macaroons` option is only permitted when the RPC server is in a private
|
||||||
|
network. In CIDR notation, the following IPs are considered private,
|
||||||
|
- [`169.254.0.0/16` and `fe80::/10`](https://en.wikipedia.org/wiki/Link-local_address).
|
||||||
|
- [`224.0.0.0/4` and `ff00::/8`](https://en.wikipedia.org/wiki/Multicast_address).
|
||||||
|
- [`10.0.0.0/8`, `172.16.0.0/12` and `192.168.0.0/16`](https://tools.ietf.org/html/rfc1918).
|
||||||
|
- [`fc00::/7`](https://tools.ietf.org/html/rfc4193).
|
||||||
|
|
||||||
Since `lnd` requires macaroons by default in order to call RPC methods, `lncli`
|
Since `lnd` requires macaroons by default in order to call RPC methods, `lncli`
|
||||||
now reads a macaroon and provides it in the RPC call. Unless the path is
|
now reads a macaroon and provides it in the RPC call. Unless the path is
|
||||||
|
@ -54,10 +54,10 @@ func NormalizeAddresses(addrs []string, defaultPort string,
|
|||||||
// interface.
|
// interface.
|
||||||
func EnforceSafeAuthentication(addrs []net.Addr, macaroonsActive bool) error {
|
func EnforceSafeAuthentication(addrs []net.Addr, macaroonsActive bool) error {
|
||||||
// We'll now examine all addresses that this RPC server is listening
|
// 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
|
// on. If it's a localhost address or a private address, we'll skip it,
|
||||||
// return an error if macaroons are inactive.
|
// otherwise, we'll return an error if macaroons are inactive.
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
if IsLoopback(addr.String()) || IsUnix(addr) {
|
if IsLoopback(addr.String()) || IsUnix(addr) || IsPrivate(addr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +117,39 @@ func IsUnix(addr net.Addr) bool {
|
|||||||
return strings.HasPrefix(addr.Network(), "unix")
|
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
|
// ParseAddressString converts an address in string format to a net.Addr that is
|
||||||
// compatible with lnd. UDP is not supported because lnd needs reliable
|
// compatible with lnd. UDP is not supported because lnd needs reliable
|
||||||
// connections. We accept a custom function to resolve any TCP addresses so
|
// connections. We accept a custom function to resolve any TCP addresses so
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// addressTest defines a test vector for an address that contains the non-
|
// 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user