Architecture redesign
This issue encompasses both the client and the server. I decided to post it here in order to have greater exposure.
Since we have released LN, it has become clear that some architectural changes are necessary.
1 - The client comes with a watchtower service. The watchtower can be either local or remote. A remote watchtower is difficult to configure, I think that only a few passionate users are doing that. A local watchtower does not make sense if you are not online regularly. Even then, it is debatable whether the local watchtower really is useful; it only is if the LN wallet is not opened as regularly as Electrum itself.
2 - Lightning payments require finding a path. Synchronizing the network graph locally is resource intensive (unacceptable for a mobile application) and it takes quite some time. We are currently using a workaround to speed it up, but that degrades the reliability of payments. We are going to have trampoline payments (work in progress), but some users might not be comfortable with the privacy trade-off. A better privacy will be achieved with multiple-trampoline paths, but it seems difficult to release that soon, because the specification is not ready (specifically, TRAMPOLINE_FEE_INSUFFICIENT should come with a node_update payload that tells us about the correct fee, but current Eclair implementation returns an empty string and leaves it to the payer to guess the fee with multiple retries)
3 - The user experience of backing up channels on Android is currently unacceptable. It requires two wallets with the same master public key, which is already a very confusing setup (with lightning, those two wallets will differ). The UX is slightly better on desktop.
A fraction of our users run their own full node, with a private Electrum server (ElectrumX or EPS). Since a full node is always online, it would make sense to add the watchtower, path-finding and channel backups services to that server. Of course, this works only if you run your own node, because there are trust issues with delegating those services to a third party.
For users who use public Electrum servers, we should: 1 - delegate the watchtower to a third party service, and get rid of the 'local watchtower' in the settings. It is not very important that all users actually have a watchtower, as long as the other party does not know that. That game theory works well if every user who uses a private Electrum server also has a watchtower in it. 2 - use trampoline routing. (multi-trampoline in the future). 3 - perform channel backups on a third party service (Google Drive on Android), or run such a service ourselves.
We should also make it easier to run your own Electrum server. One issue is that ElectrumX currently uses SSL to authenticate itself and encrypt communications with the client. This makes the installation process difficult, because a certificate cannot be generated in Electrum. In addition, the fraction of public servers that have deployed a CA-signed certificate has always been very small, so we can reasonably assume that CA-signed certificates are not really needed. Therefore, instead of using SSL, I think we should recycle the transport used in Lightning, because it is there anyway (the server will need it to sync gossip). Not requiring a SSL cert will greatly simplify the installation of an Electrum server, and more users will use one. Also, the default installation should be "private", with lightning services enabled. Users could authenticate their mobile device by scanning a QR code displayed on the server.
One thing to keep in mind is design simplicity. We do not want to have too many options, this is why I think those services should come automatically with a private server, and also why I think that we should remove the local watchtower from the client. In the end, there should be a single choice: whether you run your own full node or not.
As a sidenote, we should probably come up with a new name for that new server project.
A fraction of our users run their own full node, with a private Electrum server
And there's a good chance they already run an LN node on that server instead of using Electrum. So I would really, really like being able to just connect Electrum to a remote LN node and use it as a frontend only. Optional of course.
We should also make it easier to run your own Electrum server.
I'm actually working on that via deb.ln-ask.me. It already works quite well for connecting Electrum to electrs but there are some outstanding issues - most importantly tunnels are not automated yet but also the dependency Electrum -> electrs is missing (intentionally as a stop gap).
My plan so far is to provide two ways of tunneling: over Tor (mainly to bypass NAT) and over SSH (faster, for more skilled users). I plan to create a tunnel-providing package for server and a client package. These will connect not just Electrum but also other desktop apps that can benefit from it. While my project is currently focused on Debian 10, I plan to support macOS and Windows at least client side eventually as well.
I was actually thinking about opening an issue to figure out a nice way to support it
Users could authenticate their mobile device by scanning a QR code displayed on the server.
This is starting to get out of hand. Zap has its own QR code, I've seen some full node app with its own QR code, Wasabi has its own QR code... I hope you see the pattern. If someone has a node with 5 different services he needs 5 scans of QR codes. I was already thinking of having some kind of bridge app that would scan the code once and then just hand the connection details to other trusted apps. (Actually with more logic under the hood to improve security, but the idea is same.) The user would still have to explicitly allow it, but better than QR code scanning. I was considering starting discussion with wider community but didn't find the time yet.
And there's a good chance they already run an LN node on that server instead of using Electrum. So I would really, really like being able to just connect Electrum to a remote LN node and use it as a frontend only. Optional of course.
You need funds in order to run a LN node. That is not my idea. There are no funds on the server in what I described.
Also, Electrum is non-custodian. To be a frontend to a LN node would make it custodian. That's not what we want to do.
As I said, I'd like it dual-mode. It's only custodial if the server doesn't belong to you, which is definitely not what I meant. I have my own server it runs bitcoind, electrs, LND and it'd be nice to be able to use LND from Electrum UI. If you're worried about noobs connecting to random servers it can be avoided by making the configuration command-line-only. (just like configuring Electrum server without tls requires :t suffix in command line)
I think the two hard parts are the watchtower and channel backups in the case of public servers. I'm not aware of any services offering such solutions. If realized I would imagine them to collect service fees (offchain). If such a service should be integrated into a public ElectrumX node, the node operator would need to operate an extra Lightning node in order to receive these service fees. As there's a trust issue from the client's perspective, it could ask the server whether it can prove that it has stored the watchtower and backup data and only pay for an update if the data was correctly stored. On the other hand, what happens if there is complete client data loss? You also need to somehow know which server or service you used for the channel backups.
I think the two hard parts are the watchtower and channel backups in the case of public servers.
I agree, and I am not proposing a solution to that. My point is that we should get rid of a few features that we currently have in Electrum, and that are too difficult to use. Specifically, I think it will not be a big loss to get rid of the local watchtower, and to move the remote watchtower to the Electrum server. My point is that although current public server users will no longer be able to use it, more usage will be gained from private server users, because the UX will be simplified in their case. Whether public server operators decide to develop this as a paying service is a different question, out of scope for this redesign. Same goes for channel backups: I am not saying that we should develop a public server infrastructure for that.
move the remote watchtower to the Electrum server
makes sense but please make it an optional feature of the protocol
Same goes for channel backups: I am not saying that we should develop a public server infrastructure for that.
Would it make sense to have the basic (unpaid) version in the protocol as an optional feature?
Since we're discussing new features, I suggest inventing a way for the server to authenticate the client.
Right now if EPS is exposed to the internet, then an attacker who connects to it could in principle figure out all the addresses watched by that server. Because of this the EPS guide tells people to not expose the server to the internet and instead use a SSH tunnel or IP address whitelisting: https://github.com/chris-belcher/electrum-personal-server#exposure-to-the-internet
It would be cool for EPS to be safely runnable from some public IP address that the user points their wallet to, and when they connect either a password dialog pops up or maybe the wallet already has some kind of certificate (similar to certificate login for SSH).
Heh, was thinking about exactly this issue recently. Happy to hear EPS docs covers it. I think @shesek might be interested as well.
I would like authentication to be optional (in protocol, EPS can mandate it if not listening on 127.0.0.1) and Electrum to support loading a secret (whatever kind) from a file to not incentivize people into picking a short password.
similar to certificate login for SSH
@chris-belcher Lightning has already added the requirement for a new transport protocol. Noise has other variants than XK which may function more like SSH, since XK, as far as I remember, assumes you know the public key of who you are connecting to. But updating to support multiple Noise variants could also be seen as complex. I gather you don't think XK is appropriate?
Therefore, instead of using SSL, I think we should recycle the transport used in Lightning
Since we're discussing new features, I suggest inventing a way for the server to authenticate the client.
The idea is that the protocol could just use a BOLT-08-like transport. I am not sure about the noise variants of it that @ysangkok mentions, but with BOLT-08, both the client and the server would have a pubkey. Clearly the server's pubkey would be long term persistent. The question is what to do for the client's pubkey. Naively, for privacy reasons, it would be simplest to keep regenerating random keys, however I guess optionally it could be made persistent too. In which case for authentication for the private server use case, the operator could simply whitelist a list of client pubkeys.
I gather you don't think XK is appropriate?
Not at all. I just wasn't very familiar with it.
The ideas mentioned (BOLT-08-like, noise-xk) both sound fine to me.
The question is what to do for the client's pubkey. Naively, for privacy reasons, it would be simplest to keep regenerating random keys, however I guess optionally it could be made persistent too. In which case for authentication for the private server use case, the operator could simply whitelist a list of client pubkeys.
Obviously, we have a lot of options here. 1. random keys every time ; 2. random keys saved to disk, persistent across restarts ; 3. generated from passphrase/seed ; 3.1 import backup ; 3.2 restore from passphrase/seed ; ?4? derived from wallet master public key or something per-wallet related -- I don't think this one is a good idea as it complicates things when multiple wallets are opened at the same time.
Anyways, there MUST be some kind of client-auth to server especially if we move the watchover part to the server (and we should move it, because Electrum is a SPV wallet that wasn't designed to be always online like a full node), but even without thinking about the watchover service the latest (still ongoing) Botnet attack on our free public servers made it clear that we need something more to map a session to an username/pubkey/whatever than IP address, because 1 IP address != 1 user. I can't find a proper way to identify abusive users (all connect from the same IP address, but not all are abusive), so if I ban that IP address I also ban a lot of innocent users.
Having some kind of client auth schema will significantly contribute to servers ecosystem. It can be optional of course, a feature, but it must be there. One can setup a public server free of cost and whitelist client auth credentials just by requesting to solve a captcha, and if you abuse that server's resources access is gone. It's still something additional that makes it harder for botnets to attack servers, requires more resources, etc. Reliable paid server services might also appear (I am not a fan but it's required in the wild) and it's a good thing since users might want to pay a free for a certain level of trust / uptime / fee estimate / watchover service / etc.
I have a hack for authentication that can work with the current protocol, by abusing the SOCKS5 support that many wallets already have. Basically, have the Electrum server parse the SOCKS5 handshake and require an authentication before making the Electrum RPC available.
The client will then configure the SOCKS5 proxy address to the Electrum server address. The authentication itself can be done using the SOCKS5 username/password, or by using something like <auth-token>.token as the server hostname. The latter option has the advantage of being compatible with wallets that let you set a SOCKS5 server but not a username/password for it.
This of course won't work if you actually need to use a proxy server (though it is compatible with transparent proxying like with the Orbot VPN). And having a proper built-in authentication mechanism would definitely be better. But this works today, and I'm planning to integrate this in bwt as a short term solution, so I thought its worth bringing up.
@shesek that hack is perfectly useful and will do the job yes, at least until we have proper built-in authentication mechanism. since we are off topic here can you fork and make a branch with your patch and also add some documentation in how to use, while keeping it as a "hack temporary solution" until we come up with something native? Also, it would be wise to also patch the over-usage detection mechanism that logs / disconnects abusive addresses to instead log / disconnect usernames so other automated scripts can fetch from time to time the abusive usernames in the log file and permanently remove them access from the server.
Note: two important proposals have been posted to the #lightning-dev mailing list since I opened this issue, that propose a solution to the problem of channels backups, by making it possible to restore channels from seed. I think we should implement that, and take part to the discussion on how to add that to the RFC. I will open a separate issue to keep track of that.
@gits7r The SOCKS5-based authentication mechanism I described is now implemented in bwt: https://github.com/bwt-dev/bwt/blob/master/doc/auth.md
There's, however, a significant limitation with it: SOCKS5 authentication is transmitted in plaintext, making this primarily suitable for LAN or local servers.
I would love for Electrum to add a saner, built-in way to do this :)
Thinking about it, maybe also implement Unix socket? It's secure against various local attacks and shouldn't be too hard to implement I think.
@Kixunil I definitely can, but I'm not aware of any wallet that could connect to it. I do have a local WIP branch for the HTTP API over unix sockets, though.
Edit: That being said, I do agree that unix sockets are very suitable for securing local servers in multi-user host environments. It delegates responsibility for authentication to the OS filesystem permissions mechnaism, which makes a lot of sense. C-lightning does something similar too. It would be great if Electrum supported it!
I meant it as also adding the support to the wallets. :) You're exactly right about multi-user environments. I just want to add that users are often used as isolation mechanism, not just physical human beings. E.g. in my Debian repository each application has its own user out of the box (besides a few rational exceptions).
Following-up on my initial post: release 4.1.0 will have trampoline routing, and on-chain static backups using an op_return (#7112). This solves two of the issues posted above, at least for now. We will no longer need an op_return if f the Diffie-Hellman proposal by Lloyd Fournier makes it into the spec, but that is too far out in the future.
The remaining issues are:
- move the watchtower into the server, reserve it for private use
- get rid of SSL, use LN transport and authentication
- maybe move LN path finding to the server (less urgent now that we have trampoline)
We should be targeting release 4.2.0 for these.