Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REST hidden service deamon #29

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6f5d222
Fix typo in lnd_connect_uri.md
lukechilds Jan 6, 2021
e1efa37
Fix typo in lnd_connect_uri.md
roshii Sep 19, 2022
59fd1e8
update dependencies
roshii Sep 20, 2022
f61ae69
Use low QR error correction and green background
roshii Sep 20, 2022
8d2fe86
Use low QR error correction and green background
roshii Sep 20, 2022
baa273d
move URI related code
roshii Sep 21, 2022
46f8075
define MockEncrypter
roshii Sep 21, 2022
59e3848
add tor onion service support
roshii Sep 21, 2022
81d8f0b
dev config
roshii Sep 21, 2022
56ade79
add REST onion usage instruction
roshii Sep 21, 2022
6ded8dd
fix option description
roshii Sep 21, 2022
3960a0e
Add tor onion service support
roshii Sep 21, 2022
e990834
set module path to github.com/roshii/lndconnect
roshii Sep 22, 2022
d7def2d
add defaultQRFilePath
roshii Sep 22, 2022
3afb135
move qr code logic to uri
roshii Sep 22, 2022
e9a5be0
fix tag identifier
roshii Sep 22, 2022
d603a2f
fix errors' strings format
roshii Sep 22, 2022
01f8d81
switch from deprecated io/ioutil package
roshii Sep 22, 2022
a8ce1c7
fix attribute name format
roshii Sep 22, 2022
21dc8e4
add comments
roshii Sep 22, 2022
634691f
autoformatting
roshii Sep 22, 2022
581fb70
capture and WriteColorFile return error
roshii Sep 22, 2022
9a71eb8
implement torController goroutine
roshii Sep 22, 2022
11695af
Merge branch 'master' into dev
roshii Sep 23, 2022
1ca2ec5
leverage log pkg
roshii Sep 23, 2022
305afcf
lookup tor.targetipaddress
roshii Sep 23, 2022
8684c68
code cleanup
roshii Sep 23, 2022
74a707d
Revert "dev config"
roshii Sep 23, 2022
9e8a23e
LND REST hidden service daemon
roshii Sep 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ lndconnect
--adminmacaroonpath= Path to read the admin macaroon from
--readonlymacaroonpath= Path to read the read-only macaroon from
--invoicemacaroonpath= Path to read the invoice-only macaroon from

-c, --createonion Create onion hidden service to access REST interface
-r, --tor.restkeypath= The path to the private key of the onion service being created
```
102 changes: 69 additions & 33 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ package main

import (
"fmt"
"log"
"os"
"os/user"
"path/filepath"
"strconv"
"strings"

"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcd/btcutil"
"github.com/jessevdk/go-flags"
"github.com/lightningnetwork/lnd/tor"
)
Expand All @@ -25,36 +27,51 @@ const (
defaultReadMacFilename = "readonly.macaroon"
defaultInvoiceMacFilename = "invoice.macaroon"
defaultRPCPort = 10009
defaultRESTPort = 8080
defaultRESTKeyFileName = "rest_onion_private_key"
defaultQRFileName = "lndconnect-qr.png"
)

var (
defaultLndDir = btcutil.AppDataDir("lnd", false)
defaultConfigFile = filepath.Join(defaultLndDir, defaultConfigFilename)
defaultDataDir = filepath.Join(defaultLndDir, defaultDataDirname)
defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename)
defaultRESTKeyPath = filepath.Join(defaultLndDir, defaultRESTKeyFileName)
defaultQRFilePath = filepath.Join(defaultLndDir, defaultQRFileName)
)

type chainConfig struct {
Active bool `long:"active" description:"If the chain should be active or not"`
Active bool `long:"active" description:"If the chain should be active or not"`
MainNet bool `long:"mainnet" description:"Use the main network"`
TestNet3 bool `long:"testnet" description:"Use the test network"`
SimNet bool `long:"simnet" description:"Use the simulation test network"`
SimNet bool `long:"simnet" description:"Use the simulation test network"`
RegTest bool `long:"regtest" description:"Use the regression test network"`
}

type torConfig struct {
Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"`
V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"`
Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"`
TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"`
Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."`
RESTKeyPath string `long:"restkeypath" description:"The path to the private key of the onion service being created if provided." short:"r"`
}

type arrayFlags []string

type lndConnectConfig struct {
LocalIp bool `short:"i" long:"localip" description:"Include local ip in QRCode"`
Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"`
Host string `long:"host" description:"Use specific host name"`
NoCert bool `long:"nocert" description:"Don't include the certificate"`
Port uint16 `short:"p" long:"port" description:"Use this port"`
Url bool `short:"j" long:"url" description:"Display url instead of a QRCode"`
Image bool `short:"o" long:"image" description:"Output QRCode to file"`
Invoice bool `long:"invoice" description:"Use invoice macaroon"`
Readonly bool `long:"readonly" description:"Use readonly macaroon"`
Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"`
LocalIP bool `short:"i" long:"localip" description:"Include local ip in QRCode"`
Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"`
Host string ` long:"host" description:"Use specific host name"`
NoCert bool ` long:"nocert" description:"Don't include the certificate"`
Port uint16 `short:"p" long:"port" description:"Use this port"`
URL bool `short:"j" long:"url" description:"Display url instead of a QRCode"`
Image bool `short:"o" long:"image" description:"Output QRCode to file"`
Invoice bool ` long:"invoice" description:"Use invoice macaroon"`
Readonly bool ` long:"readonly" description:"Use readonly macaroon"`
Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"`
CreateOnion bool `short:"c" long:"createonion" description:"Create onion v3 hidden service to access REST interface."`
}

// config defines the configuration options for lndconnect.
Expand All @@ -64,27 +81,29 @@ type lndConnectConfig struct {
type config struct {
LndConnect *lndConnectConfig `group:"LndConnect"`

LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"`
DataDir string `short:"b" long:"datadir" description:"The directory to find lnd's data within"`
TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"`
AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"`
ReadMacPath string `long:"readonlymacaroonpath" description:"Path to read the read-only macaroon from"`
InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"`
LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
ConfigFile string `long:"configfile" description:"Path to configuration file" short:"C"`
DataDir string `long:"datadir" description:"The directory to find lnd's data within" short:"b"`
TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"`
AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"`
ReadMacPath string `long:"readonlymacaroonpath" description:"Path to read the read-only macaroon from"`
InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"`
RawRESTListeners []string `long:"restlisten" description:"Interface/Port/Socket listening for REST connections"`

Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"`
Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"`
Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"`

Tor *torConfig `group:"Tor" namespace:"tor"`

// The following lines we only need to be able to parse the
// configuration INI file without errors. The content will be ignored.
BtcdMode *chainConfig `hidden:"true" group:"btcd" namespace:"btcd"`
BitcoindMode *chainConfig `hidden:"true" group:"bitcoind" namespace:"bitcoind"`
NeutrinoMode *chainConfig `hidden:"true" group:"neutrino" namespace:"neutrino"`
LtcdMode *chainConfig `hidden:"true" group:"ltcd" namespace:"ltcd"`
BtcdMode *chainConfig `hidden:"true" group:"btcd" namespace:"btcd"`
BitcoindMode *chainConfig `hidden:"true" group:"bitcoind" namespace:"bitcoind"`
NeutrinoMode *chainConfig `hidden:"true" group:"neutrino" namespace:"neutrino"`
LtcdMode *chainConfig `hidden:"true" group:"ltcd" namespace:"ltcd"`
LitecoindMode *chainConfig `hidden:"true" group:"litecoind" namespace:"litecoind"`
Autopilot *chainConfig `hidden:"true" group:"Autopilot" namespace:"autopilot"`
Tor *chainConfig `hidden:"true" group:"Tor" namespace:"tor"`
Hodl *chainConfig `hidden:"true" group:"hodl" namespace:"hodl"`
Hodl *chainConfig `hidden:"true" group:"hodl" namespace:"hodl"`

net tor.Net
}
Expand All @@ -93,10 +112,10 @@ type config struct {
// line options.
//
// The configuration proceeds as follows:
// 1) Start with a default config with sane settings
// 2) Pre-parse the command line to check for an alternative config file
// 3) Load configuration file overwriting defaults with any specified options
// 4) Parse CLI options and overwrite/add any specified options
// 1. Start with a default config with sane settings
// 2. Pre-parse the command line to check for an alternative config file
// 3. Load configuration file overwriting defaults with any specified options
// 4. Parse CLI options and overwrite/add any specified options
func loadConfig() (*config, error) {
defaultCfg := config{
LndConnect: &lndConnectConfig{
Expand All @@ -106,7 +125,10 @@ func loadConfig() (*config, error) {
ConfigFile: defaultConfigFile,
DataDir: defaultDataDir,
TLSCertPath: defaultTLSCertPath,
net: &tor.ClearNet{},
Tor: &torConfig{
RESTKeyPath: defaultRESTKeyPath,
},
net: &tor.ClearNet{},
}

// Pre-parse the command line options to pick up an alternative config
Expand All @@ -130,6 +152,7 @@ func loadConfig() (*config, error) {
}
preCfg.DataDir = filepath.Join(lndDir, defaultDataDirname)
preCfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
preCfg.Tor.RESTKeyPath = filepath.Join(lndDir, defaultRESTKeyFileName)
}

// Next, load any additional configuration options from the file.
Expand Down Expand Up @@ -176,7 +199,7 @@ func loadConfig() (*config, error) {
networkName = "simnet"
}
if numNets > 1 {
str := "The mainnet, testnet, regtest, and " +
str := "the mainnet, testnet, regtest, and " +
"simnet params can't be used together -- " +
"choose one of the four"
err := fmt.Errorf(str)
Expand Down Expand Up @@ -256,3 +279,16 @@ func cleanAndExpandPath(path string) string {
// but the variables can still be expanded via POSIX-style $VARIABLE.
return filepath.Clean(os.ExpandEnv(path))
}

// updates config with onion host and port
func updateHostAddrConfig(addr string, loadedConfig *config) error {
parsedAddr := strings.Split(addr, ":")
loadedConfig.LndConnect.Host = parsedAddr[0]
parsedPort, err := strconv.ParseUint(parsedAddr[1], 10, 16)
if err != nil {
log.Fatal(err)
}
loadedConfig.LndConnect.Port = uint16(parsedPort)
loadedConfig.LndConnect.NoCert = true
return nil
}
16 changes: 16 additions & 0 deletions crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import "io"

// MockEncrypter is a mocked up structure implementing tor.NewOnionFile required encrypter methods
type MockEncrypter struct{}

// EncryptPayloadToWriter is implementing expected signature
func (m MockEncrypter) EncryptPayloadToWriter(_ []byte, _ io.Writer) error {
return nil
}

// DecryptPayloadFromReader is implementing expected signature
func (m MockEncrypter) DecryptPayloadFromReader(_ io.Reader) ([]byte, error) {
return []byte("hello world!"), nil
}
13 changes: 6 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
module github.com/LN-Zap/lndconnect
module github.com/roshii/lndconnect

go 1.16

require (
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/glendc/go-external-ip v0.0.0-20200601212049-c872357d968e
github.com/jessevdk/go-flags v1.4.0
github.com/lightningnetwork/lnd v0.13.0-beta.rc3
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/btcsuite/btcd/btcutil v1.1.2
github.com/glendc/go-external-ip v0.1.0
github.com/jessevdk/go-flags v1.5.0
github.com/lightningnetwork/lnd/tor v1.1.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
)

replace go.etcd.io/etcd => go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b
require github.com/mattn/go-colorable v0.1.13 // indirect
Loading