loopd: add SOCKS proxy config option to dial swap server over Tor

This allows Loop users to further improve their privacy by not revealing
their source IP address. Note that the identity of the lnd node behind
Loop can still be revealed when performing a Loop In due to the swap
server extending an off-chain HTLC to the user.

Onion addresses don't yet exist for the swap servers, but they will be
added at a later time.
pull/165/head
Wilmer Paulino 4 years ago
parent a473ab5d79
commit 5b732d9012
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F

@ -78,7 +78,7 @@ type Client struct {
}
// NewClient returns a new instance to initiate swaps with.
func NewClient(dbDir string, serverAddress string, insecure bool,
func NewClient(dbDir string, serverAddress, proxyAddress string, insecure bool,
tlsPathServer string, lnd *lndclient.LndServices, maxLSATCost,
maxLSATFee btcutil.Amount) (*Client, func(), error) {
@ -92,8 +92,8 @@ func NewClient(dbDir string, serverAddress string, insecure bool,
}
swapServerClient, err := newSwapServerClient(
serverAddress, insecure, tlsPathServer, lsatStore, lnd,
maxLSATCost, maxLSATFee,
serverAddress, proxyAddress, insecure, tlsPathServer, lsatStore,
lnd, maxLSATCost, maxLSATFee,
)
if err != nil {
return nil, nil, err

@ -45,7 +45,8 @@ type config struct {
MaxLSATCost uint32 `long:"maxlsatcost" description:"Maximum cost in satoshis that loopd is going to pay for an LSAT token automatically. Does not include routing fees."`
MaxLSATFee uint32 `long:"maxlsatfee" description:"Maximum routing fee in satoshis that we are willing to pay while paying for an LSAT token."`
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
Proxy string `long:"proxy" description:"The host:port of a SOCKS proxy through which all connections to the swap server will be established over."`
View viewParameters `command:"view" alias:"v" description:"View all swaps in the database. This command can only be executed when loopd is not running."`
}

@ -50,6 +50,8 @@ func daemon(config *config, lisCfg *listenerCfg) error {
// If no swap server is specified, use the default addresses for mainnet
// and testnet.
if config.SwapServer == "" {
// TODO(wilmer): Use onion service addresses when proxy is
// active.
switch config.Network {
case "mainnet":
config.SwapServer = mainnetServer

@ -19,7 +19,7 @@ func getClient(config *config, lnd *lndclient.LndServices) (*loop.Client,
}
swapClient, cleanUp, err := loop.NewClient(
storeDir, config.SwapServer, config.Insecure,
storeDir, config.SwapServer, config.Proxy, config.Insecure,
config.TLSPathSwapSrv, lnd, btcutil.Amount(config.MaxLSATCost),
btcutil.Amount(config.MaxLSATFee),
)

@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"net"
"time"
"github.com/btcsuite/btcd/btcec"
@ -15,6 +16,7 @@ import (
"github.com/lightninglabs/loop/lsat"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/tor"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
@ -52,8 +54,8 @@ type grpcSwapServerClient struct {
var _ swapServerClient = (*grpcSwapServerClient)(nil)
func newSwapServerClient(address string, insecure bool, tlsPath string,
lsatStore lsat.Store, lnd *lndclient.LndServices,
func newSwapServerClient(address, proxyAddress string, insecure bool,
tlsPath string, lsatStore lsat.Store, lnd *lndclient.LndServices,
maxLSATCost, maxLSATFee btcutil.Amount) (*grpcSwapServerClient, error) {
// Create the server connection with the interceptor that will handle
@ -62,7 +64,7 @@ func newSwapServerClient(address string, insecure bool, tlsPath string,
lnd, lsatStore, serverRPCTimeout, maxLSATCost, maxLSATFee,
)
serverConn, err := getSwapServerConn(
address, insecure, tlsPath, clientInterceptor,
address, proxyAddress, insecure, tlsPath, clientInterceptor,
)
if err != nil {
return nil, err
@ -243,9 +245,11 @@ func (s *grpcSwapServerClient) Close() {
s.conn.Close()
}
// getSwapServerConn returns a connection to the swap server.
func getSwapServerConn(address string, insecure bool, tlsPath string,
interceptor *lsat.Interceptor) (*grpc.ClientConn, error) {
// getSwapServerConn returns a connection to the swap server. A non-empty
// proxyAddr indicates that a SOCKS proxy found at the address should be used to
// establish the connection.
func getSwapServerConn(address, proxyAddress string, insecure bool,
tlsPath string, interceptor *lsat.Interceptor) (*grpc.ClientConn, error) {
// Create a dial options array.
opts := []grpc.DialOption{grpc.WithUnaryInterceptor(
@ -273,6 +277,17 @@ func getSwapServerConn(address string, insecure bool, tlsPath string,
opts = append(opts, grpc.WithTransportCredentials(creds))
}
// If a SOCKS proxy address was specified, then we should dial through
// it.
if proxyAddress != "" {
log.Infof("Proxying connection to %v over Tor SOCKS proxy %v",
address, proxyAddress)
torDialer := func(_ context.Context, addr string) (net.Conn, error) {
return tor.Dial(addr, proxyAddress, false)
}
opts = append(opts, grpc.WithContextDialer(torDialer))
}
conn, err := grpc.Dial(address, opts...)
if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v",

Loading…
Cancel
Save