server: add automatic creation of v2 onion services
In this commit, we allow the daemon to use the recently introduced Tor Controller implementation. This will automatically create a v2 onion service at startup in order to listen for inbound connections over Tor. Co-Authored-By: Eugene <crypt-iq@users.noreply.github.com>
This commit is contained in:
1 file changed
+75
@@ -74,6 +74,16 @@ type server struct {
|
|||||||
// long-term identity private key.
|
// long-term identity private key.
|
||||||
lightningID [32]byte
|
lightningID [32]byte
|
||||||
|
|
||||||
|
// listenAddrs is the list of addresses the server is currently
|
||||||
|
// listening on.
|
||||||
|
listenAddrs []string
|
||||||
|
|
||||||
|
// torController is a client that will communicate with a locally
|
||||||
|
// running Tor server. This client will handle initiating and
|
||||||
|
// authenticating the connection to the Tor server, automatically
|
||||||
|
// creating and setting up onion services, etc.
|
||||||
|
torController *tor.Controller
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
peersByPub map[string]*peer
|
peersByPub map[string]*peer
|
||||||
|
|
||||||
@@ -215,6 +225,8 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
identityPriv: privKey,
|
identityPriv: privKey,
|
||||||
nodeSigner: newNodeSigner(privKey),
|
nodeSigner: newNodeSigner(privKey),
|
||||||
|
|
||||||
|
listenAddrs: listenAddrs,
|
||||||
|
|
||||||
// TODO(roasbeef): derive proper onion key based on rotation
|
// TODO(roasbeef): derive proper onion key based on rotation
|
||||||
// schedule
|
// schedule
|
||||||
sphinx: htlcswitch.NewOnionProcessor(sphinxRouter),
|
sphinx: htlcswitch.NewOnionProcessor(sphinxRouter),
|
||||||
@@ -299,6 +311,16 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
selfAddrs = append(selfAddrs, addr)
|
selfAddrs = append(selfAddrs, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we were requested to route connections through Tor and to
|
||||||
|
// automatically create an onion service, we'll initiate our Tor
|
||||||
|
// controller and establish a connection to the Tor server.
|
||||||
|
//
|
||||||
|
// NOTE: v3 onion services cannot be created automatically yet. In the
|
||||||
|
// future, this will be expanded to do so.
|
||||||
|
if cfg.Tor.Active && cfg.Tor.V2 {
|
||||||
|
s.torController = tor.NewController(cfg.Tor.Control)
|
||||||
|
}
|
||||||
|
|
||||||
chanGraph := chanDB.ChannelGraph()
|
chanGraph := chanDB.ChannelGraph()
|
||||||
|
|
||||||
// Parse node color from configuration.
|
// Parse node color from configuration.
|
||||||
@@ -588,6 +610,12 @@ func (s *server) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.torController != nil {
|
||||||
|
if err := s.initTorController(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start the notification server. This is used so channel management
|
// Start the notification server. This is used so channel management
|
||||||
// goroutines can be notified when a funding transaction reaches a
|
// goroutines can be notified when a funding transaction reaches a
|
||||||
// sufficient number of confirmations, or when the input for the
|
// sufficient number of confirmations, or when the input for the
|
||||||
@@ -659,6 +687,10 @@ func (s *server) Stop() error {
|
|||||||
|
|
||||||
close(s.quit)
|
close(s.quit)
|
||||||
|
|
||||||
|
if s.torController != nil {
|
||||||
|
s.torController.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Shutdown the wallet, funding manager, and the rpc server.
|
// Shutdown the wallet, funding manager, and the rpc server.
|
||||||
s.cc.chainNotifier.Stop()
|
s.cc.chainNotifier.Stop()
|
||||||
s.chanRouter.Stop()
|
s.chanRouter.Stop()
|
||||||
@@ -881,6 +913,49 @@ func (s *server) peerBootstrapper(numTargetPeers uint32,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initTorController initiliazes the Tor controller backed by lnd and
|
||||||
|
// automatically sets up a v2 onion service in order to listen for inbound
|
||||||
|
// connections over Tor.
|
||||||
|
func (s *server) initTorController() error {
|
||||||
|
if err := s.torController.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the different ports the server is listening on. The onion
|
||||||
|
// service's virtual port will map to these ports and one will be picked
|
||||||
|
// at random when the onion service is being accessed.
|
||||||
|
listenPorts := make(map[int]struct{})
|
||||||
|
for _, listenAddr := range s.listenAddrs {
|
||||||
|
// At this point, the listen addresses should have already been
|
||||||
|
// normalized, so it's safe to ignore the errors.
|
||||||
|
_, portStr, _ := net.SplitHostPort(listenAddr)
|
||||||
|
port, _ := strconv.Atoi(portStr)
|
||||||
|
listenPorts[port] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the port mapping has been set, we can go ahead and automatically
|
||||||
|
// create our onion service. The service's private key will be saved to
|
||||||
|
// disk in order to regain access to this service when restarting `lnd`.
|
||||||
|
virtToTargPorts := tor.VirtToTargPorts{defaultPeerPort: listenPorts}
|
||||||
|
onionServiceAddrs, err := s.torController.AddOnionV2(
|
||||||
|
cfg.Tor.V2PrivateKeyPath, virtToTargPorts,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that the onion service has been created, we'll add the different
|
||||||
|
// onion addresses it can be reached at to our list of advertised
|
||||||
|
// addresses.
|
||||||
|
for _, addr := range onionServiceAddrs {
|
||||||
|
s.currentNodeAnn.Addresses = append(
|
||||||
|
s.currentNodeAnn.Addresses, addr,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// genNodeAnnouncement generates and returns the current fully signed node
|
// genNodeAnnouncement generates and returns the current fully signed node
|
||||||
// announcement. If refresh is true, then the time stamp of the announcement
|
// announcement. If refresh is true, then the time stamp of the announcement
|
||||||
// will be updated in order to ensure it propagates through the network.
|
// will be updated in order to ensure it propagates through the network.
|
||||||
|
|||||||
Reference in new issue
Block a user