Skip to content

Commit e52141e

Browse files
committed
terminal: direct calls to remote daemons
If any of the daemons is configured to be running in remote mode, the RPC proxy only acts as a gRPC web reverse proxy and just forwards any requests to the correct backend. For non-remote daemons the requests shouldn't get to the director in the first place but instead be handled by the main gRPC server.
1 parent 71fb8e5 commit e52141e

File tree

2 files changed

+169
-23
lines changed

2 files changed

+169
-23
lines changed

rpc_proxy.go

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/improbable-eng/grpc-web/go/grpcweb"
14+
"github.com/lightningnetwork/lnd/lncfg"
1415
"github.com/lightningnetwork/lnd/macaroons"
1516
grpcProxy "github.com/mwitkow/grpc-proxy/proxy"
1617
"google.golang.org/grpc"
@@ -111,6 +112,9 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
111112
// v authenticated call | - pool |
112113
// +---+----------------------+ +--------------------+
113114
// | lnd (remote or local) |
115+
// | faraday remote |
116+
// | loop remote |
117+
// | pool remote |
114118
// +--------------------------+
115119
//
116120
type rpcProxy struct {
@@ -119,7 +123,11 @@ type rpcProxy struct {
119123

120124
macValidator macaroons.MacaroonValidator
121125

122-
lndConn *grpc.ClientConn
126+
lndConn *grpc.ClientConn
127+
faradayConn *grpc.ClientConn
128+
loopConn *grpc.ClientConn
129+
poolConn *grpc.ClientConn
130+
123131
grpcServer *grpc.Server
124132
grpcWebProxy *grpcweb.WrappedGrpcServer
125133
}
@@ -135,6 +143,41 @@ func (p *rpcProxy) Start() error {
135143
return fmt.Errorf("could not dial lnd: %v", err)
136144
}
137145

146+
// Make sure we can connect to all the daemons that are configured to be
147+
// running in remote mode.
148+
if p.cfg.faradayRemote {
149+
p.faradayConn, err = dialBackend(
150+
"faraday", p.cfg.Remote.Faraday.RPCServer,
151+
lncfg.CleanAndExpandPath(
152+
p.cfg.Remote.Faraday.TLSCertPath,
153+
),
154+
)
155+
if err != nil {
156+
return fmt.Errorf("could not dial remote faraday: %v",
157+
err)
158+
}
159+
}
160+
161+
if p.cfg.loopRemote {
162+
p.loopConn, err = dialBackend(
163+
"loop", p.cfg.Remote.Loop.RPCServer,
164+
lncfg.CleanAndExpandPath(p.cfg.Remote.Loop.TLSCertPath),
165+
)
166+
if err != nil {
167+
return fmt.Errorf("could not dial remote loop: %v", err)
168+
}
169+
}
170+
171+
if p.cfg.poolRemote {
172+
p.poolConn, err = dialBackend(
173+
"pool", p.cfg.Remote.Pool.RPCServer,
174+
lncfg.CleanAndExpandPath(p.cfg.Remote.Pool.TLSCertPath),
175+
)
176+
if err != nil {
177+
return fmt.Errorf("could not dial remote pool: %v", err)
178+
}
179+
}
180+
138181
return nil
139182
}
140183

@@ -149,6 +192,27 @@ func (p *rpcProxy) Stop() error {
149192
}
150193
}
151194

195+
if p.faradayConn != nil {
196+
if err := p.faradayConn.Close(); err != nil {
197+
log.Errorf("Error closing faraday connection: %v", err)
198+
return err
199+
}
200+
}
201+
202+
if p.loopConn != nil {
203+
if err := p.loopConn.Close(); err != nil {
204+
log.Errorf("Error closing loop connection: %v", err)
205+
return err
206+
}
207+
}
208+
209+
if p.poolConn != nil {
210+
if err := p.poolConn.Close(); err != nil {
211+
log.Errorf("Error closing pool connection: %v", err)
212+
return err
213+
}
214+
}
215+
152216
return nil
153217
}
154218

@@ -188,7 +252,7 @@ func (p *rpcProxy) isHandling(resp http.ResponseWriter,
188252
// backend, depending on what kind of authentication information is attached to
189253
// the request.
190254
func (p *rpcProxy) director(ctx context.Context,
191-
_ string) (context.Context, *grpc.ClientConn, error) {
255+
requestURI string) (context.Context, *grpc.ClientConn, error) {
192256

193257
// If this header is present in the request from the web client,
194258
// the actual connection to the backend will not be established.
@@ -199,7 +263,29 @@ func (p *rpcProxy) director(ctx context.Context,
199263

200264
outCtx := metadata.NewOutgoingContext(ctx, mdCopy)
201265

202-
return outCtx, p.lndConn, nil
266+
// Direct the call to the correct backend. For lnd we _always_ have a
267+
// client connection, no matter if it's running in integrated or remote
268+
// mode. For all other daemons the request shouldn't get here in
269+
// integrated mode (after all, the director only picks up calls that the
270+
// gRPC server itself would throw a 404 for) so we throw an error
271+
// message for them if they're not in remote mode.
272+
switch {
273+
case isLndURI(requestURI):
274+
return outCtx, p.lndConn, nil
275+
276+
case isFaradayURI(requestURI) && p.cfg.faradayRemote:
277+
return outCtx, p.faradayConn, nil
278+
279+
case isLoopURI(requestURI) && p.cfg.loopRemote:
280+
return outCtx, p.loopConn, nil
281+
282+
case isPoolURI(requestURI) && p.cfg.poolRemote:
283+
return outCtx, p.poolConn, nil
284+
285+
default:
286+
return ctx, nil, fmt.Errorf("unknown gRPC web request: %v",
287+
requestURI)
288+
}
203289
}
204290

205291
// UnaryServerInterceptor is a gRPC interceptor that checks whether the
@@ -313,13 +399,25 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
313399
_, _, _, macPath = p.cfg.lndConnectParams()
314400

315401
case isLoopURI(requestURI):
316-
macPath = p.cfg.Loop.MacaroonPath
402+
if p.cfg.loopRemote {
403+
macPath = p.cfg.Remote.Loop.MacaroonPath
404+
} else {
405+
macPath = p.cfg.Loop.MacaroonPath
406+
}
317407

318408
case isFaradayURI(requestURI):
319-
macPath = p.cfg.Faraday.MacaroonPath
409+
if p.cfg.faradayRemote {
410+
macPath = p.cfg.Remote.Faraday.MacaroonPath
411+
} else {
412+
macPath = p.cfg.Faraday.MacaroonPath
413+
}
320414

321415
case isPoolURI(requestURI):
322-
macPath = p.cfg.Pool.MacaroonPath
416+
if p.cfg.poolRemote {
417+
macPath = p.cfg.Remote.Pool.MacaroonPath
418+
} else {
419+
macPath = p.cfg.Pool.MacaroonPath
420+
}
323421

324422
default:
325423
return ctx, fmt.Errorf("unknown gRPC web request: %v",
@@ -328,7 +426,7 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
328426

329427
// Now that we know which macaroon to load, do it and attach it to the
330428
// request context.
331-
macBytes, err := readMacaroon(macPath)
429+
macBytes, err := readMacaroon(lncfg.CleanAndExpandPath(macPath))
332430
if err != nil {
333431
return ctx, fmt.Errorf("error reading macaroon: %v", err)
334432
}

terminal.go

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -310,24 +310,31 @@ func (g *LightningTerminal) startSubservers() error {
310310
return err
311311
}
312312

313-
// Both connection types are ready now, let's start our subservers.
314-
err = g.faradayServer.StartAsSubserver(g.lndClient.LndServices)
315-
if err != nil {
316-
return err
313+
// Both connection types are ready now, let's start our subservers if
314+
// they should be started locally as an integrated service.
315+
if !g.cfg.faradayRemote {
316+
err = g.faradayServer.StartAsSubserver(g.lndClient.LndServices)
317+
if err != nil {
318+
return err
319+
}
320+
g.faradayStarted = true
317321
}
318-
g.faradayStarted = true
319322

320-
err = g.loopServer.StartAsSubserver(g.lndClient)
321-
if err != nil {
322-
return err
323+
if !g.cfg.loopRemote {
324+
err = g.loopServer.StartAsSubserver(g.lndClient)
325+
if err != nil {
326+
return err
327+
}
328+
g.loopStarted = true
323329
}
324-
g.loopStarted = true
325330

326-
err = g.poolServer.StartAsSubserver(basicClient, g.lndClient)
327-
if err != nil {
328-
return err
331+
if !g.cfg.poolRemote {
332+
err = g.poolServer.StartAsSubserver(basicClient, g.lndClient)
333+
if err != nil {
334+
return err
335+
}
336+
g.poolStarted = true
329337
}
330-
g.poolStarted = true
331338

332339
return nil
333340
}
@@ -338,9 +345,23 @@ func (g *LightningTerminal) startSubservers() error {
338345
// the same server instance.
339346
func (g *LightningTerminal) RegisterGrpcSubserver(grpcServer *grpc.Server) error {
340347
g.lndGrpcServer = grpcServer
341-
frdrpc.RegisterFaradayServerServer(grpcServer, g.faradayServer)
342-
looprpc.RegisterSwapClientServer(grpcServer, g.loopServer)
343-
poolrpc.RegisterTraderServer(grpcServer, g.poolServer)
348+
349+
// In remote mode the "director" of the RPC proxy will act as a catch-
350+
// all for any gRPC request that isn't known because we didn't register
351+
// any server for it. The director will then forward the request to the
352+
// remote service.
353+
if !g.cfg.faradayRemote {
354+
frdrpc.RegisterFaradayServerServer(grpcServer, g.faradayServer)
355+
}
356+
357+
if !g.cfg.loopRemote {
358+
looprpc.RegisterSwapClientServer(grpcServer, g.loopServer)
359+
}
360+
361+
if !g.cfg.poolRemote {
362+
poolrpc.RegisterTraderServer(grpcServer, g.poolServer)
363+
}
364+
344365
return nil
345366
}
346367

@@ -383,6 +404,12 @@ func (g *LightningTerminal) ValidateMacaroon(ctx context.Context,
383404
// checked as they'll have their own interceptor.
384405
switch {
385406
case isLoopURI(fullMethod):
407+
// In remote mode we just pass through the request, the remote
408+
// daemon will check the macaroon.
409+
if g.cfg.loopRemote {
410+
return nil
411+
}
412+
386413
if !g.loopStarted {
387414
return fmt.Errorf("loop is not yet ready for " +
388415
"requests, lnd possibly still starting or " +
@@ -394,6 +421,12 @@ func (g *LightningTerminal) ValidateMacaroon(ctx context.Context,
394421
)
395422

396423
case isFaradayURI(fullMethod):
424+
// In remote mode we just pass through the request, the remote
425+
// daemon will check the macaroon.
426+
if g.cfg.faradayRemote {
427+
return nil
428+
}
429+
397430
if !g.faradayStarted {
398431
return fmt.Errorf("faraday is not yet ready for " +
399432
"requests, lnd possibly still starting or " +
@@ -405,6 +438,18 @@ func (g *LightningTerminal) ValidateMacaroon(ctx context.Context,
405438
)
406439

407440
case isPoolURI(fullMethod):
441+
// In remote mode we just pass through the request, the remote
442+
// daemon will check the macaroon.
443+
if g.cfg.poolRemote {
444+
return nil
445+
}
446+
447+
if !g.poolStarted {
448+
return fmt.Errorf("pool is not yet ready for " +
449+
"requests, lnd possibly still starting or " +
450+
"syncing")
451+
}
452+
408453
return g.poolServer.ValidateMacaroon(
409454
ctx, requiredPermissions, fullMethod,
410455
)
@@ -514,6 +559,9 @@ func (g *LightningTerminal) shutdown() error {
514559
// v authenticated call | - pool |
515560
// +---+----------------------+ +--------------------+
516561
// | lnd (remote or local) |
562+
// | faraday remote |
563+
// | loop remote |
564+
// | pool remote |
517565
// +--------------------------+
518566
//
519567
func (g *LightningTerminal) startMainWebServer() error {

0 commit comments

Comments
 (0)