mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
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.
This commit is contained in:
parent
d23073f8b0
commit
d5c26045f7
6 changed files with 99 additions and 34 deletions
35
config.go
35
config.go
|
|
@ -77,6 +77,8 @@ const (
|
|||
// DefaultMacaroonFilename is the default file name for the
|
||||
// autogenerated lit macaroon.
|
||||
DefaultMacaroonFilename = "lit.macaroon"
|
||||
|
||||
defaultFirstLNCConnTimeout = 10 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -153,6 +155,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.
|
||||
|
|
@ -302,21 +306,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: defaultFirstLNCConnTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/improbable-eng/grpc-web v0.12.0
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/lightninglabs/faraday v0.2.8-alpha.0.20220624141723-ddd3cd123e62
|
||||
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha
|
||||
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha.0.20220822151854-c072f70315d8
|
||||
github.com/lightninglabs/lndclient v0.15.0-10
|
||||
github.com/lightninglabs/loop v0.19.1-beta.0.20220623090540-08209f61e304
|
||||
github.com/lightninglabs/loop/swapserverrpc v1.0.1
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -541,8 +541,8 @@ 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 v0.1.11-alpha.0.20220822151854-c072f70315d8 h1:FYZ63sERRC2RjVbsAeO55uF7kTIYCClHmd59dZSsyx0=
|
||||
github.com/lightninglabs/lightning-node-connect v0.1.11-alpha.0.20220822151854-c072f70315d8/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=
|
||||
|
|
|
|||
|
|
@ -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.ServerStatus)) error {
|
||||
|
||||
tlsConfig := &tls.Config{}
|
||||
if session.DevServer {
|
||||
|
|
@ -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,
|
||||
|
|
@ -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.ServerStatus)) (chan struct{}, error) {
|
||||
|
||||
s.activeSessionsMtx.Lock()
|
||||
defer s.activeSessionsMtx.Unlock()
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -214,10 +215,57 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
authData := []byte(fmt.Sprintf("%s: %s", HeaderMacaroon, mac))
|
||||
var (
|
||||
onNewStatus func(s mailbox.ServerStatus)
|
||||
firstConnTimout = 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 sess.RemotePublicKey == nil {
|
||||
deadline := sess.CreatedAt.Add(s.cfg.firstConnectionDeadline)
|
||||
if deadline.Before(time.Now()) {
|
||||
log.Debugf("Deadline for session %x has already "+
|
||||
"passed. Revoking session", pubKeyBytes)
|
||||
|
||||
return s.db.RevokeSession(pubKey)
|
||||
}
|
||||
|
||||
// Start the deadline timer.
|
||||
deadlineDuration := time.Until(deadline)
|
||||
deadlineTimer := time.AfterFunc(deadlineDuration, func() {
|
||||
close(firstConnTimout)
|
||||
})
|
||||
|
||||
log.Warnf("Kicking off deadline timer for first connection "+
|
||||
"for session %x. A successful connection must be "+
|
||||
"made in the next %s", pubKeyBytes, deadlineDuration)
|
||||
|
||||
var stopTimerOnce sync.Once
|
||||
onNewStatus = func(s mailbox.ServerStatus) {
|
||||
// We will only stop the timer if the server status
|
||||
// indicates that the client has successfully connected.
|
||||
if s != mailbox.ServerStatusInUse {
|
||||
return
|
||||
}
|
||||
|
||||
// Stop the deadline timer.
|
||||
stopTimerOnce.Do(func() {
|
||||
log.Debugf("First connection for session %x "+
|
||||
"made in a timely manner",
|
||||
sess.LocalPublicKey.
|
||||
SerializeCompressed())
|
||||
|
||||
deadlineTimer.Stop()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -232,22 +280,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)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
|||
|
|
@ -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 "+
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue