Skip to content

Commit d5c2604

Browse files
committed
multi: add deadline for first connection of new LNC conn
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.
1 parent d23073f commit d5c2604

File tree

6 files changed

+99
-34
lines changed

6 files changed

+99
-34
lines changed

config.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ const (
7777
// DefaultMacaroonFilename is the default file name for the
7878
// autogenerated lit macaroon.
7979
DefaultMacaroonFilename = "lit.macaroon"
80+
81+
defaultFirstLNCConnTimeout = 10 * time.Minute
8082
)
8183

8284
var (
@@ -153,6 +155,8 @@ type Config struct {
153155

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

158+
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. "`
159+
156160
// Network is the Bitcoin network we're running on. This will be parsed
157161
// before the configuration is loaded and will set the correct flag on
158162
// `lnd.bitcoin.mainnet|testnet|regtest` and also for the other daemons.
@@ -302,21 +306,22 @@ func defaultConfig() *Config {
302306
TLSCertPath: poolDefaultConfig.TLSCertPath,
303307
},
304308
},
305-
Network: DefaultNetwork,
306-
LndMode: DefaultLndMode,
307-
Lnd: &lndDefaultConfig,
308-
LitDir: DefaultLitDir,
309-
LetsEncryptListen: defaultLetsEncryptListen,
310-
LetsEncryptDir: defaultLetsEncryptDir,
311-
MacaroonPath: DefaultMacaroonPath,
312-
ConfigFile: defaultConfigFile,
313-
FaradayMode: defaultFaradayMode,
314-
Faraday: &faradayDefaultConfig,
315-
faradayRpcConfig: &frdrpcserver.Config{},
316-
LoopMode: defaultLoopMode,
317-
Loop: &loopDefaultConfig,
318-
PoolMode: defaultPoolMode,
319-
Pool: &poolDefaultConfig,
309+
Network: DefaultNetwork,
310+
LndMode: DefaultLndMode,
311+
Lnd: &lndDefaultConfig,
312+
LitDir: DefaultLitDir,
313+
LetsEncryptListen: defaultLetsEncryptListen,
314+
LetsEncryptDir: defaultLetsEncryptDir,
315+
MacaroonPath: DefaultMacaroonPath,
316+
ConfigFile: defaultConfigFile,
317+
FaradayMode: defaultFaradayMode,
318+
Faraday: &faradayDefaultConfig,
319+
faradayRpcConfig: &frdrpcserver.Config{},
320+
LoopMode: defaultLoopMode,
321+
Loop: &loopDefaultConfig,
322+
PoolMode: defaultPoolMode,
323+
Pool: &poolDefaultConfig,
324+
FirstLNCConnDeadline: defaultFirstLNCConnTimeout,
320325
}
321326
}
322327

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/improbable-eng/grpc-web v0.12.0
1212
github.com/jessevdk/go-flags v1.4.0
1313
github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62
14-
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha
14+
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha.0.20220822151854-c072f70315d8
1515
github.com/lightninglabs/lndclient v0.15.0-10
1616
github.com/lightninglabs/loop v0.19.1-beta.0.20220623090540-08209f61e304
1717
github.com/lightninglabs/loop/swapserverrpc v1.0.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,8 @@ github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62 h1:t
541541
github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62/go.mod h1:9kcDuyINNf4RB6vrmPLAMGZmYgN0oPxhdt3IicL9sQY=
542542
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc=
543543
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
544-
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha h1:d+jKyAvCQMLq5O1IL6ONWM/l4C7Q3Q00HkdjDIG9uTg=
545-
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha/go.mod h1:dgyhE+O4GpWBhS7yIzKCm8LqFHX8/QRwJ6OWFrN+WnA=
544+
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha.0.20220822151854-c072f70315d8 h1:FYZ63sERRC2RjVbsAeO55uF7kTIYCClHmd59dZSsyx0=
545+
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha.0.20220822151854-c072f70315d8/go.mod h1:dgyhE+O4GpWBhS7yIzKCm8LqFHX8/QRwJ6OWFrN+WnA=
546546
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2 h1:Er1miPZD2XZwcfE4xoS5AILqP1mj7kqnhbBSxW9BDxY=
547547
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2/go.mod h1:antQGRDRJiuyQF6l+k6NECCSImgCpwaZapATth2Chv4=
548548
github.com/lightninglabs/lndclient v0.15.0-0/go.mod h1:ORS/YFe9hAXlzN/Uj+gvTmrnXEml6yD6dWwzCjpTJyQ=

session/server.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ func newMailboxSession() *mailboxSession {
3333

3434
func (m *mailboxSession) start(session *Session,
3535
serverCreator GRPCServerCreator, authData []byte,
36-
onUpdate func(sess *Session) error) error {
36+
onUpdate func(sess *Session) error,
37+
onNewStatus func(s mailbox.ServerStatus)) error {
3738

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

5354
// Start the mailbox gRPC server.
5455
mailboxServer, err := mailbox.NewServer(
55-
session.ServerAddr, keys,
56+
session.ServerAddr, keys, onNewStatus,
5657
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
5758
grpc.WithKeepaliveParams(keepalive.ClientParameters{
5859
Time: 2 * time.Minute,
@@ -104,7 +105,8 @@ func NewServer(serverCreator GRPCServerCreator) *Server {
104105
}
105106

106107
func (s *Server) StartSession(session *Session, authData []byte,
107-
onUpdate func(sess *Session) error) (chan struct{}, error) {
108+
onUpdate func(sess *Session) error,
109+
onNewStatus func(s mailbox.ServerStatus)) (chan struct{}, error) {
108110

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

123125
return sess.quit, sess.start(
124-
session, s.serverCreator, authData, onUpdate,
126+
session, s.serverCreator, authData, onUpdate, onNewStatus,
125127
)
126128
}
127129

session_rpcserver.go

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type sessionRpcServerConfig struct {
3838
registerGrpcServers func(server *grpc.Server)
3939
superMacBaker func(ctx context.Context, rootKeyID uint64,
4040
recipe *session.MacaroonRecipe) (string, error)
41+
firstConnectionDeadline time.Duration
4142
}
4243

4344
// newSessionRPCServer creates a new sessionRpcServer using the passed config.
@@ -214,10 +215,57 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
214215
return nil
215216
}
216217

217-
authData := []byte(fmt.Sprintf("%s: %s", HeaderMacaroon, mac))
218+
var (
219+
onNewStatus func(s mailbox.ServerStatus)
220+
firstConnTimout = make(chan struct{})
221+
)
222+
223+
// If this is the first time the session is being spun up then we will
224+
// kick off a timer to revoke the session after a timeout unless an
225+
// initial connection is made. We identify such a session as one that
226+
// we do not yet have a static remote pub key for.
227+
if sess.RemotePublicKey == nil {
228+
deadline := sess.CreatedAt.Add(s.cfg.firstConnectionDeadline)
229+
if deadline.Before(time.Now()) {
230+
log.Debugf("Deadline for session %x has already "+
231+
"passed. Revoking session", pubKeyBytes)
232+
233+
return s.db.RevokeSession(pubKey)
234+
}
235+
236+
// Start the deadline timer.
237+
deadlineDuration := time.Until(deadline)
238+
deadlineTimer := time.AfterFunc(deadlineDuration, func() {
239+
close(firstConnTimout)
240+
})
241+
242+
log.Warnf("Kicking off deadline timer for first connection "+
243+
"for session %x. A successful connection must be "+
244+
"made in the next %s", pubKeyBytes, deadlineDuration)
245+
246+
var stopTimerOnce sync.Once
247+
onNewStatus = func(s mailbox.ServerStatus) {
248+
// We will only stop the timer if the server status
249+
// indicates that the client has successfully connected.
250+
if s != mailbox.ServerStatusInUse {
251+
return
252+
}
253+
254+
// Stop the deadline timer.
255+
stopTimerOnce.Do(func() {
256+
log.Debugf("First connection for session %x "+
257+
"made in a timely manner",
258+
sess.LocalPublicKey.
259+
SerializeCompressed())
260+
261+
deadlineTimer.Stop()
262+
})
263+
}
264+
}
218265

266+
authData := []byte(fmt.Sprintf("%s: %s", HeaderMacaroon, mac))
219267
sessionClosedSub, err := s.sessionServer.StartSession(
220-
sess, authData, s.db.StoreSession,
268+
sess, authData, s.db.StoreSession, onNewStatus,
221269
)
222270
if err != nil {
223271
return err
@@ -232,22 +280,31 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
232280

233281
select {
234282
case <-s.quit:
283+
return
284+
235285
case <-sessionClosedSub:
286+
return
287+
236288
case <-ticker.C:
237289
log.Debugf("Stopping expired session %x with "+
238290
"type %d", pubKeyBytes, sess.Type)
239291

240-
err = s.sessionServer.StopSession(pubKey)
241-
if err != nil {
242-
log.Debugf("Error stopping session: "+
243-
"%v", err)
244-
}
292+
case <-firstConnTimout:
293+
log.Debugf("Deadline exceeded for first connection "+
294+
"for session %x. Stopping and revoking.",
295+
pubKeyBytes)
296+
}
245297

246-
err = s.db.RevokeSession(pubKey)
247-
if err != nil {
248-
log.Debugf("error revoking session: "+
249-
"%v", err)
250-
}
298+
err = s.sessionServer.StopSession(pubKey)
299+
if err != nil {
300+
log.Debugf("Error stopping session: "+
301+
"%v", err)
302+
}
303+
304+
err = s.db.RevokeSession(pubKey)
305+
if err != nil {
306+
log.Debugf("error revoking session: "+
307+
"%v", err)
251308
}
252309
}()
253310

terminal.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ func (g *LightningTerminal) Run() error {
232232
recipe.Permissions, recipe.Caveats,
233233
)
234234
},
235+
firstConnectionDeadline: g.cfg.FirstLNCConnDeadline,
235236
})
236237
if err != nil {
237238
return fmt.Errorf("could not create new session rpc "+

0 commit comments

Comments
 (0)