Skip to content

Commit

Permalink
multi: add deadline for first connection of new LNC conn
Browse files Browse the repository at this point in the history
In this commit, we add a deadline for the initial connection of an LNC
connection. So with this, the user is forced to use their pairing phrase
within a certain time frame. After this initial connection, future
connections are made with the second handshake version meaning that the
pairing phrase is rendered useless. By adding a time limit to the time
in which a user can use their pairing phrase, we reduce the risk created
by the users pairing phrase being leaked. The default time limit is set
to 10 minutes but can be customsed with the new `firstlncconndeadline`
flag.
  • Loading branch information
ellemouton committed Aug 18, 2022
1 parent 03deb1a commit 96dbc12
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 33 deletions.
33 changes: 18 additions & 15 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ type Config struct {

MacaroonPath string `long:"macaroonpath" description:"Path to write the macaroon for litd's RPC and REST services if it doesn't exist."`

FirstLNCConnDeadline time.Duration `long:"firstlncconndeadline" description:"The duration after a new LNC session will be revoked if no connection is made with it. This only applies for the first connection which is made using the pairing phrase. "`

// Network is the Bitcoin network we're running on. This will be parsed
// before the configuration is loaded and will set the correct flag on
// `lnd.bitcoin.mainnet|testnet|regtest` and also for the other daemons.
Expand Down Expand Up @@ -302,21 +304,22 @@ func defaultConfig() *Config {
TLSCertPath: poolDefaultConfig.TLSCertPath,
},
},
Network: DefaultNetwork,
LndMode: DefaultLndMode,
Lnd: &lndDefaultConfig,
LitDir: DefaultLitDir,
LetsEncryptListen: defaultLetsEncryptListen,
LetsEncryptDir: defaultLetsEncryptDir,
MacaroonPath: DefaultMacaroonPath,
ConfigFile: defaultConfigFile,
FaradayMode: defaultFaradayMode,
Faraday: &faradayDefaultConfig,
faradayRpcConfig: &frdrpcserver.Config{},
LoopMode: defaultLoopMode,
Loop: &loopDefaultConfig,
PoolMode: defaultPoolMode,
Pool: &poolDefaultConfig,
Network: DefaultNetwork,
LndMode: DefaultLndMode,
Lnd: &lndDefaultConfig,
LitDir: DefaultLitDir,
LetsEncryptListen: defaultLetsEncryptListen,
LetsEncryptDir: defaultLetsEncryptDir,
MacaroonPath: DefaultMacaroonPath,
ConfigFile: defaultConfigFile,
FaradayMode: defaultFaradayMode,
Faraday: &faradayDefaultConfig,
faradayRpcConfig: &frdrpcserver.Config{},
LoopMode: defaultLoopMode,
Loop: &loopDefaultConfig,
PoolMode: defaultPoolMode,
Pool: &poolDefaultConfig,
FirstLNCConnDeadline: 10 * time.Minute,
}
}

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,6 @@ require (
// decision with a replace.
replace github.com/lightningnetwork/lnd => github.com/lightningnetwork/lnd v0.15.0-beta

replace github.com/lightninglabs/lightning-node-connect => github.com/ellemouton/lightning-node-connect v0.1.5-alpha.0.20220818155633-c0c62efe6eea

go 1.17
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvyukov/go-fuzz v0.0.0-20210602112143-b1f3d6f4ef4e h1:qTP1telKJHlToHlwPQNmVg4yfMDMHe4Z3SYmzkrvA2M=
github.com/dvyukov/go-fuzz v0.0.0-20210602112143-b1f3d6f4ef4e/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/ellemouton/lightning-node-connect v0.1.5-alpha.0.20220818155633-c0c62efe6eea h1:vHtcBa7AgiRoxQuqplsn9CJKgYP3cxyYwNCJdLwbDvk=
github.com/ellemouton/lightning-node-connect v0.1.5-alpha.0.20220818155633-c0c62efe6eea/go.mod h1:dgyhE+O4GpWBhS7yIzKCm8LqFHX8/QRwJ6OWFrN+WnA=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down Expand Up @@ -541,8 +543,6 @@ github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62 h1:t
github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62/go.mod h1:9kcDuyINNf4RB6vrmPLAMGZmYgN0oPxhdt3IicL9sQY=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha h1:d+jKyAvCQMLq5O1IL6ONWM/l4C7Q3Q00HkdjDIG9uTg=
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha/go.mod h1:dgyhE+O4GpWBhS7yIzKCm8LqFHX8/QRwJ6OWFrN+WnA=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2 h1:Er1miPZD2XZwcfE4xoS5AILqP1mj7kqnhbBSxW9BDxY=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2/go.mod h1:antQGRDRJiuyQF6l+k6NECCSImgCpwaZapATth2Chv4=
github.com/lightninglabs/lndclient v0.15.0-0/go.mod h1:ORS/YFe9hAXlzN/Uj+gvTmrnXEml6yD6dWwzCjpTJyQ=
Expand Down
10 changes: 6 additions & 4 deletions session/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ func newMailboxSession() *mailboxSession {

func (m *mailboxSession) start(session *Session,
serverCreator GRPCServerCreator, authData []byte,
onUpdate func(sess *Session) error) error {
onUpdate func(sess *Session) error,
onNewStatus func(s mailbox.ServerConnStatus)) error {

tlsConfig := &tls.Config{}
if session.DevServer {
Expand All @@ -52,7 +53,7 @@ func (m *mailboxSession) start(session *Session,

// Start the mailbox gRPC server.
mailboxServer, err := mailbox.NewServer(
session.ServerAddr, keys,
session.ServerAddr, keys, onNewStatus,
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 2 * time.Minute,
Expand Down Expand Up @@ -104,7 +105,8 @@ func NewServer(serverCreator GRPCServerCreator) *Server {
}

func (s *Server) StartSession(session *Session, authData []byte,
onUpdate func(sess *Session) error) (chan struct{}, error) {
onUpdate func(sess *Session) error,
onNewStatus func(s mailbox.ServerConnStatus)) (chan struct{}, error) {

s.activeSessionsMtx.Lock()
defer s.activeSessionsMtx.Unlock()
Expand All @@ -121,7 +123,7 @@ func (s *Server) StartSession(session *Session, authData []byte,
s.activeSessions[id] = sess

return sess.quit, sess.start(
session, s.serverCreator, authData, onUpdate,
session, s.serverCreator, authData, onUpdate, onNewStatus,
)
}

Expand Down
98 changes: 86 additions & 12 deletions session_rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type sessionRpcServerConfig struct {
registerGrpcServers func(server *grpc.Server)
superMacBaker func(ctx context.Context, rootKeyID uint64,
recipe *session.MacaroonRecipe) (string, error)
firstConnectionDeadline time.Duration
}

// newSessionRPCServer creates a new sessionRpcServer using the passed config.
Expand Down Expand Up @@ -214,15 +215,79 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
return nil
}

authData := []byte(fmt.Sprintf("%s: %s", HeaderMacaroon, mac))
var (
isFirstConn = sess.RemotePublicKey == nil
onNewStatus func(s mailbox.ServerConnStatus)
firstConnectionDeadline *time.Timer
firstConnTimout = make(chan struct{})
exitFirstConnDeadline = make(chan struct{})
)

// If this is the first time the session is being spun up then we will
// kick off a timer to revoke the session after a timeout unless an
// initial connection is made. We identify such a session as one that
// we do not yet have a static remote pub key for.
if isFirstConn {
// Start the deadline timer.
firstConnectionDeadline = time.NewTimer(
s.cfg.firstConnectionDeadline,
)

log.Warnf("Kicking off deadline timer for first connection "+
"for session %x. A successful connection must be made "+
"in the next %s",
sess.LocalPublicKey.SerializeCompressed(),
s.cfg.firstConnectionDeadline)

var stopTimerOnce sync.Once
onNewStatus = func(s mailbox.ServerConnStatus) {
// We will only stop the timer if the server status
// indicates that the client has successfully connected.
if s != mailbox.ServerConnStatusInUse {
return
}

// Stop the deadline timer.
stopTimerOnce.Do(func() {
firstConnectionDeadline.Stop()
close(exitFirstConnDeadline)
})
}
}

authData := []byte(fmt.Sprintf("%s: %s", HeaderMacaroon, mac))
sessionClosedSub, err := s.sessionServer.StartSession(
sess, authData, s.db.StoreSession,
sess, authData, s.db.StoreSession, onNewStatus,
)
if err != nil {
return err
}

if isFirstConn {
s.wg.Add(1)
go func() {
defer s.wg.Done()

select {
case <-s.quit:
return

case <-sessionClosedSub:
return

case <-firstConnectionDeadline.C:
close(firstConnTimout)

case <-exitFirstConnDeadline:
log.Debugf("First connection for session %x "+
"made in a timely manner",
sess.LocalPublicKey.
SerializeCompressed())
return
}
}()
}

s.wg.Add(1)
go func() {
defer s.wg.Done()
Expand All @@ -232,22 +297,31 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {

select {
case <-s.quit:
return

case <-sessionClosedSub:
return

case <-ticker.C:
log.Debugf("Stopping expired session %x with "+
"type %d", pubKeyBytes, sess.Type)

err = s.sessionServer.StopSession(pubKey)
if err != nil {
log.Debugf("Error stopping session: "+
"%v", err)
}
case <-firstConnTimout:
log.Debugf("Deadline exceeded for first connection "+
"for session %x. Stopping and revoking.",
pubKeyBytes)
}

err = s.db.RevokeSession(pubKey)
if err != nil {
log.Debugf("error revoking session: "+
"%v", err)
}
err = s.sessionServer.StopSession(pubKey)
if err != nil {
log.Debugf("Error stopping session: "+
"%v", err)
}

err = s.db.RevokeSession(pubKey)
if err != nil {
log.Debugf("error revoking session: "+
"%v", err)
}
}()

Expand Down
1 change: 1 addition & 0 deletions terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ func (g *LightningTerminal) Run() error {
recipe.Permissions, recipe.Caveats,
)
},
firstConnectionDeadline: g.cfg.FirstLNCConnDeadline,
})
if err != nil {
return fmt.Errorf("could not create new session rpc "+
Expand Down

0 comments on commit 96dbc12

Please sign in to comment.