netann: add new HostAnnouncer to support dynamic IPs via domains

In this commit, we add a new sub-system, then `HostAnnouncer` which
allows a users without a static IP address to ensure that lnd always
announces the most up to date address based on a domain name. A new
command line flag `--external-hosts` has been added which allows a user
to specify one or most hosts that should be periodically resolved to
update any advertised IPs the node has.

Fixes #1624.
This commit is contained in:
Olaoluwa Osuntokun
2020-05-12 17:05:18 -07:00
parent f9c6a1b73f
commit ba3688c3b9
4 changed files with 520 additions and 0 deletions

View File

@@ -271,6 +271,8 @@ type server struct {
// provide insights into their health and performance.
chanEventStore *chanfitness.ChannelEventStore
hostAnn *netann.HostAnnouncer
quit chan struct{}
wg sync.WaitGroup
@@ -1231,6 +1233,26 @@ func newServer(cfg *Config, listenAddrs []net.Addr, chanDB *channeldb.DB,
}
}
if len(cfg.ExternalHosts) != 0 {
advertisedIPs := make(map[string]struct{})
for _, addr := range s.currentNodeAnn.Addresses {
advertisedIPs[addr.String()] = struct{}{}
}
s.hostAnn = netann.NewHostAnnouncer(netann.HostAnnouncerConfig{
Hosts: cfg.ExternalHosts,
RefreshTicker: ticker.New(defaultHostSampleInterval),
LookupHost: func(host string) (net.Addr, error) {
return lncfg.ParseAddressString(
host, strconv.Itoa(defaultPeerPort),
cfg.net.ResolveTCPAddr,
)
},
AdvertisedIPs: advertisedIPs,
AnnounceNewIPs: netann.IPAnnouncer(s.genNodeAnnouncement),
})
}
// Create the connection manager which will be responsible for
// maintaining persistent outbound connections and also accepting new
// incoming connections
@@ -1274,6 +1296,13 @@ func (s *server) Start() error {
go s.watchExternalIP()
}
if s.hostAnn != nil {
if err := s.hostAnn.Start(); err != nil {
startErr = err
return
}
}
// Start the notification server. This is used so channel
// management goroutines can be notified when a funding
// transaction reaches a sufficient number of confirmations, or
@@ -1492,6 +1521,13 @@ func (s *server) Stop() error {
s.towerClient.Stop()
}
if s.hostAnn != nil {
if err := s.hostAnn.Stop(); err != nil {
srvrLog.Warnf("unable to shut down host "+
"annoucner: %v", err)
}
}
// Wait for all lingering goroutines to quit.
s.wg.Wait()