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:
Wilmer Paulino 2018-04-27 17:02:05 -04:00
parent 3bb1733fa2
commit 1012f876e1
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F

View File

@ -74,6 +74,16 @@ type server struct {
// long-term identity private key.
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
peersByPub map[string]*peer
@ -215,6 +225,8 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
identityPriv: privKey,
nodeSigner: newNodeSigner(privKey),
listenAddrs: listenAddrs,
// TODO(roasbeef): derive proper onion key based on rotation
// schedule
sphinx: htlcswitch.NewOnionProcessor(sphinxRouter),
@ -299,6 +311,16 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
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()
// Parse node color from configuration.
@ -588,6 +610,12 @@ func (s *server) Start() error {
return nil
}
if s.torController != nil {
if err := s.initTorController(); err != nil {
return err
}
}
// 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 when the input for the
@ -659,6 +687,10 @@ func (s *server) Stop() error {
close(s.quit)
if s.torController != nil {
s.torController.Stop()
}
// Shutdown the wallet, funding manager, and the rpc server.
s.cc.chainNotifier.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
// announcement. If refresh is true, then the time stamp of the announcement
// will be updated in order to ensure it propagates through the network.