tor: remove Onion Service upon shutdown

This commit adds a new method to call DEL_ONION when lnd is shutting
down. Tor controller will now be aware of the active serviceID and
removes the service upon shutdown.
This commit is contained in:
yyforyongyu 2021-09-23 18:37:30 +08:00
parent 0b80d4feaa
commit 90e6c70ea0
No known key found for this signature in database
GPG Key ID: 9BCD95C4FF296868
3 changed files with 67 additions and 0 deletions

View File

@ -244,6 +244,9 @@ func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) {
}
}
c.activeServiceID = serviceID
log.Debugf("serviceID:%s added to tor controller", serviceID)
// Finally, we'll return the onion address composed of the service ID,
// along with the onion suffix, and the port this onion service can be
// reached at externally.
@ -252,3 +255,47 @@ func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) {
Port: cfg.VirtualPort,
}, nil
}
// DelOnion tells the Tor daemon to remove an onion service, which satisfies
// either,
// - the onion service was created on the same control connection as the
// "DEL_ONION" command.
// - the onion service was created using the "Detach" flag.
func (c *Controller) DelOnion(serviceID string) error {
log.Debugf("removing serviceID:%s from tor controller", serviceID)
cmd := fmt.Sprintf("DEL_ONION %s", serviceID)
// Send the command to create the onion service to the Tor server and
// await its response.
code, _, err := c.sendCommand(cmd)
// Tor replies with "250 OK" on success, or a 512 if there are an
// invalid number of arguments, or a 552 if it doesn't recognize the
// ServiceID.
switch code {
// Replied 250 OK.
case success:
return nil
// Replied 512 for invalid arguments. This is most likely that the
// serviceID is not set(empty string).
case invalidNumOfArguments:
return fmt.Errorf("invalid arguments: %w", err)
// Replied 552, which means either,
// - the serviceID is invalid.
// - the onion service is not owned by the current control connection
// and,
// - the onion service is not a detached service.
// In either case, we will ignore the error and log a warning as there
// not much we can do from the controller side.
case serviceIDNotRecognized:
log.Warnf("removing serviceID:%v not found", serviceID)
return nil
default:
return fmt.Errorf("undefined response code: %v, err: %w",
code, err)
}
}

View File

@ -20,6 +20,14 @@ const (
// request.
success = 250
// invalidNumOfArguments is the Tor Control response code representing
// there being an invalid number of arguments.
invalidNumOfArguments = 512
// serviceIDNotRecognized is the Tor Control response code representing
// the specified ServiceID is not recognized.
serviceIDNotRecognized = 552
// nonceLen is the length of a nonce generated by either the controller
// or the Tor server
nonceLen = 32
@ -100,6 +108,9 @@ type Controller struct {
// to connect to the LND node. This is required when the Tor server
// runs on another host, otherwise the service will not be reachable.
targetIPAddress string
// activeServiceID is the Onion ServiceID created by ADD_ONION.
activeServiceID string
}
// NewController returns a new Tor controller that will be able to interact with
@ -142,6 +153,15 @@ func (c *Controller) Stop() error {
log.Info("Stopping tor controller")
// Remove the onion service.
if err := c.DelOnion(c.activeServiceID); err != nil {
log.Errorf("DEL_ONION got error: %v", err)
return err
}
// Reset service ID.
c.activeServiceID = ""
return c.conn.Close()
}