Volition Labs

Tor-only Bitcoin & Lightning Guide

May 16, 2021

A detailed guide to improving privacy as a Lightning Network user by Jameson Lopp.

Discover more at https://blog.lopp.net.

To receive further Cyber Musings, subscribe to the VOLITION ZINE.

When the average person hears the term "cryptocurrency," they may assume that every aspect of the protocol is encrypted and thus completely private, allowing users to safely remain anonymous.

This is most certainly not the case, and privacy-conscious users will need to take additional steps to protect themselves. One particular threat vector that Bitcoin and Lightning users should consider is that of the network observer.

By sending data in the clear via default IPV4 and IPV6 networks, sophisticated entities can look for patterns to correlate your financial activity and they can use the IP address of your machine to probe it for weaknesses and attempt to learn your location and identity.

How are we to protect ourselves?

  1. By sharing as little data with third parties as possible.
  2. By ensuring that all of the data our nodes send and receive is routed over a privacy preserving network.

Full nodes offer the best privacy model when it comes to preventing data leaks. With a full node, you download all the blockchain data and only query for addresses / transactions locally — network observers can’t see what you’re interested in.

But if we run our own nodes, we still have to share data (such as for sending transactions) with peers on the network – how do we protect ourselves from them? Enter Tor. Tor Project maintainers say that you can think of what Tor does as "using a twisty, hard-to-follow route in order to throw off somebody who is tailing you — and then periodically erasing your footprints." Your traffic gets intermingled with the traffic of other Tor users. As the global Tor userbase grows, the path gets twistier.

In order for you to make networked services (anything from a web server to a peer to peer node) work on Tor, you need to create a hidden service that acts as a bridge from the Tor network to the specific software running on your machine.

Bitcoin Core

As of Bitcoin Core 0.12, a node will automatically run a hidden service if it is able to connect to a local Tor daemon. However, we have to make sure that a few things are configured correctly so that the node and daemon can talk to each other. As such, back in 2016 I first looked into how to get my Bitcoin nodes operating on the Tor network and I wrote this guide:

Volition Labs

The above guide will get you most of the way there, though additional configuration needs to be made in order to disable communication via IPV4 and IPV6. When you set up Bitcoin Core to power a Lightning node you'll want to have the following lines in your bitcoin.conf file:

# [core]

# Maintain a full transaction index (improves lnd performance)

txindex=1

daemon=1

disablewallet=1

maxuploadtarget=1000


# [rpc]

# Accept command line and JSON-RPC commands.

server=1

rpcauth=[redacted]:[redacted]


# [zeromq]

# Enable publishing of transactions to [address]

zmqpubrawtx=tcp://127.0.0.1:28333

# Enable publishing of raw block hex to [address].

zmqpubrawblock=tcp://127.0.0.1:28332


# Privacy

bind=127.0.0.1:8333

# Allow DNS lookups for -addnode, -seednode and -connect values.

dns=0

# Query for peer addresses via DNS lookup, if low on addresses.

dnsseed=0

# Specify your own public IP address.

externalip=[redacted].onion

# Use separate SOCKS5 proxy to reach peers via Tor

onion=127.0.0.1:9050

proxy=127.0.0.1:9050

proxyrandomize=1

# Only connect to peers via Tor.

onlynet=onion

listenonion=1

listen=0

# helps bootstrap peers for initial sync

addnode=gyn2vguc35viks2b.onion

addnode=kvd44sw7skb5folw.onion

addnode=nkf5e6b7pl4jfd4a.onion

addnode=yu7sezmixhmyljn4.onion

addnode=3ffk7iumtx3cegbi.onion

addnode=3nmbbakinewlgdln.onion

addnode=4j77gihpokxu2kj4.onion

addnode=546esc6botbjfbxb.onion

addnode=5at7sq5nm76xijkd.onion

addnode=77mx2jsxaoyesz2p.onion

addnode=7g7j54btiaxhtsiy.onion

addnode=a6obdgzn67l7exu3.onion

addnode=ab64h7olpl7qpxci.onion

addnode=am2a4rahltfuxz6l.onion

addnode=azuxls4ihrr2mep7.onion

addnode=bitcoin7bi4op7wb.onion

addnode=bitcoinostk4e4re.onion

addnode=bk7yp6epnmcllq72.onion

addnode=bmutjfrj5btseddb.onion

addnode=ceeji4qpfs3ms3zc.onion

addnode=clexmzqio7yhdao4.onion

addnode=gb5ypqt63du3wfhn.onion

addnode=h2vlpudzphzqxutd.onion

Note that the two lines with [redacted] info need to be set dynamically by you.

rpcauth=[redacted]:[redacted]

The rpcauth value should be set by running this python script.

externalip=[redacted].onion

You can find your Bitcoin hidden service address that you should set as the externalip by running this command while your node is running: bitcoin-cli getnetworkinfo | grep \"address

Now you'll just have to wait for bitcoind to finish syncing. This will take at least a few days, depending upon a variety of factors.

LND

LND is similarly smart like Bitcoin Core in that it can talk to the Tor daemon; you just need to tell it to do so. I suggest the following lnd.conf parameters:

[Application Options]

minchansize=100000

listen=localhost

accept-keysend=1

allow-circular-route=1

watchtower.active=1


# Mark unpayable, unpaid invoices as deleted

gc-canceled-invoices-on-startup=1

gc-canceled-invoices-on-the-fly=1


# Avoid historical graph data sync

ignore-historical-gossip-filters=1


# gRPC socket binding

rpclisten=0.0.0.0:10009

restlisten=0.0.0.0:8080


# Avoid slow startup time

sync-freelist=1


# Avoid high startup overhead

stagger-initial-reconnect=1


# Auto regenerate RPC TLS certificate

tlsautorefresh=1


# Do not include IPs in the RPC TLS certificate

tlsdisableautofill=1


[Bitcoin]

bitcoin.active=true

bitcoin.mainnet=true

bitcoin.node=bitcoind

bitcoin.minhtlc=1000

bitcoin.basefee=1000

bitcoin.feerate=100


[Bitcoind]

bitcoind.rpcuser=[redacted]

bitcoind.rpcpass=[redacted]

bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332

bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333

bitcoind.estimatemode=ECONOMICAL


[routerrpc]

# Set default chance of a hop success

routerrpc.apriorihopprob=0.5


# Start to ignore nodes if they return many failures

routerrpc.aprioriweight=0.75


# Set minimum desired savings of trying a cheaper path

routerrpc.attemptcost=10

routerrpc.attemptcostppm=10


# Set the number of historical routing records

routerrpc.maxmchistory=10000


# Set the min confidence in a path worth trying

routerrpc.minrtprob=0.005


# Set the time to forget past routing failures

routerrpc.penaltyhalflife=6h0m0s


[tor]

tor.active=true

tor.v3=true

tor.streamisolation=true

Note that bitcoind.rpcuser and bitcoind.rpcpass should be the values that you fed into the rpcauth python script when configuring Bitcoin Core, not the output value of the script.

LND has a ton of config options; you may wish to browse the sample lnd.conf here. Alex Bosworth also has some fairly in-depth recommendations for configuring your machine.

Be sure to set automatic off-site channel backups for disaster recovery! Believe me, you'll want to avoid having to perform a wallet recovery on corrupted data. I've written extensively about some of the edge cases I've run into.

Here's a simple utility script that you can tweak to send channel backups to another machine via any bash command you can conjure up (such as scp.) Alternatively you can use this script that I found and modified to automatically back up your channels to Dropbox.

Mobile Node Control via Zeus

Getting your nodes set up is great, but what if you want to actually use them to make a payment when you're out on the town and not lugging a laptop around?

At time of writing it appears that Zeus is the only mobile app available on both iOS and Android that supports talking directly to remote LND, Eclair, and c-lightning nodes.

While it's possible for Zeus to talk to your node via IPV6, we might as well stick to Tor! You'll first want to create a separate Tor hidden service for lnd's REST interface.

sudo vim /etc/tor/torrc

Add these two lines:

HiddenServiceDir /var/lib/tor/lnd_rest/

HiddenServicePort 8080 127.0.0.1:8080

Restart tor and find your new onion service hostname that you'll paste into Zeus.

sudo service tor restart

sudo cat /var/lib/tor/lnd_rest/hostname

Create a macaroon for authentication.

/path/to/lncli bakemacaroon address:read address:write info:read info:write invoices:read invoices:write message:read message:write offchain:read offchain:write onchain:read onchain:write peers:read peers:write signer:generate signer:read

This command will output a bunch of hex that you'll need to paste into Zeus. You'll also want to make sure you have the "use Tor" option checked in the Zeus config.

Now you should be all set!

But one more thing…

Liquidity Management

We are still in the early days of understanding best practices for managing Lightning Network liquidity; I expect that entire books will be written on the subject. You should learn the basics, however. I'd suggest joining some of the discussion forums to stay up to date on best practices.

There are several tools available to help manage liquidity across your channels.

There are plenty of liquidity management functions in the Balance of Satoshis tool; if you read through the documentation you'll find some automation examples under the "Linux Fu" section.

Just remember: a balanced channel is a useful channel!