SatoshiPortal / cyphernode

Modular Bitcoin full-node microservices API server architecture and utilities toolkit to build scalable, secure and featureful apps and services without trusted third parties
MIT License
363 stars 68 forks source link

Letsencrypt / Trafik issues. #185

Open cryptoskillz opened 4 years ago

cryptoskillz commented 4 years ago

The outstanding issue with letscenrypt/trafik creates a problem with cyphernode that is not easily solvable without a decent level of knowledge of DNS and how these systems work and lead to two questions.

1) Can we fix it?

Can it be fixed, if so is it an easy fix, a medium one or a hard fix? This, of course, is a subjective question with a lot of factors such as what other work does the cyphernodes devs have to do (let's assume a lot), Does it require major under the hood changes (is the juice worth the squeeze)

2) Should we fix it?

This is the inverse of the other question and is a perfectly valid one to ask. As this is not a showstopper in all but a few use cases for cyphernode and the fixes as well documented for this issues, regardless if it is a complicated fix or not.

An Assumption:

For the remainder of this issue let us assume we should fix it for no other reason it would help my particular use of cyphernode no end, however, if we chose not to fix it that is fine as well (based on the answer to question 2) as long as we justify that decision.

The issues created by this issue

There are several issues created by these issues that I will describe now, please note there may be more issues that I am unaware that (hopefully) will be fixed by the fix.

I will summarise the issues below with their proposed fixes (this can change as I am most likely wrong) and then go into each of these issues in more detail.

Use cyphernode over a domain Easy fix by setting up the domain in letsencrypt that we can provide documentation for Use cyphernode over TOR to access dashboard I think, same as above? Accessing cyphernode via code to extend it functionality Upgrade Trafik on cyphernode (most likely other fixes exist)

A detailed breakdown of the issues:

Use cyphernode over a domain

I have set up a cyphernode testnet at the following URL

https://157.245.13.93/welcome

image

and this shows the SSL issue.

Use cyphernode over TOR to access dashboard

I have set up a Raspberry PI with a test cyphernode to test TOR and we get the same issues as above when accessing the dashboard. You can view it at the following URL:

https://t66jfcrnerds2uydne3ggaw2fdgny2l25acscc5zywhclgvudn7xndad.onion:443/welcome

Accessing cyphernode via code to extend it functionality

This is a complicated issue so let me preface this before I get into to. I am not talking about if you build apps inside the docker images and are accessible on the same box as these will work as they are inside the firewall (for want of a better term) I am speaking about when you try to access it outside of this, for example, an e-commerce cart that wants to retrieve a BTC address to give to a customer for payment.

accessing the RPC over standard SSL

Using bitcoin-core, If we look at the example below we will get an SSL error

const Client = require("bitcoin-core");
client = new Client({
  host: "host",
  port: 18332,
  wallet: "wallet",
  username: "username",
  password: "password",

});
client.getNewAddress().then(address => {});

accessing the RPC over standard TOR

Accessing via TOR

If you want to access it via TOR if you use the following code

process.env.CYPHERNODE_API_KEY="xxxxxxx"
//is this required when connecting over TOR?
//process.env.CYPHERNODE_HTTP_TRANSPORT_PROXY="socks://127.0.0.1:9050"
process.env.CYPHER_GATEWAY_URL="t66jfcrnerds2uydne3ggaw2fdgny2l25acscc5zywhclgvudn7xndad.onion"
const {btcClient} = require('cyphernode-js-sdk');
const client = btcClient();
client.getBalance().then((result) => {
    console.log(result);
}).catch((err) => {
    console.log(err)
})

The following error is presented

image

Now, I could be doing something wrong with my TOR code here (as I am new to TOR in general) in which case this one could be ab easy fix, and in that case, yay.

A final note both of these code issues can be fixed in the following manner, but neither is optimal in my opinion

1) Set NODE_TLS_REJECT_UNAUTHORIZED to 0 which basically ignores SSL, which is fine for dev purposes but madness in a production environment.

2) The code is running on the same instance as cyperhnode, ideally, we would like the abstract the cyphernode instance away from any public-facing boxes.

Kexkey commented 4 years ago

Hey there @cryptoskillz ! Thanks for the writeup. A lot of stuff to address! :) I will take this opportunity to summarize how the Cyphernode network works or is intended to work. I know you already know most of what I'm going to write, but I think it's important to have that written somewhere for others. Maybe it will eventually be part of a doc file.

Cyphernode client applications and Cyphernode networks

An application that is a Cyphernode client can be run wherever you want. The most secure and simple way is to run it "inside" the Cyphernode ecosystem. If you look at the Cyphernode architectural schema, you can see the two Cyphernode networks:

image

If your client application runs outside of the Cyphernode docker network, you will have to expose/publish the gatekeeper port outside the docker network (default port 2009, default to not being exposed, it's one of the questions asked during setup). The gatekeeper is the door to your bitcoins.

Accessing the Cyphernode API, aka the gatekeeper (cyphernodenet)

The Cyphernode API (gatekeeper) should not be published to the Internet: it is not meant to be exposed to potential attacks and be a public API. The layering approach we took in our architecture makes it easier to concentrate on specific tasks on each layer. For example, a reverse proxy with access rules should be used in front of the gatekeeper. Maybe also a monitoring system, a DDoS detection system, some kind of fail2ban app, etc. Cyphernode is meant to be a personal/family/departmental/company (ie intranet) gateway to Bitcoin functionalities.

If you need to access the Cyphernode API from outside the docker network and/or local network, you should take good care of having a VPN, iptables rules, or any secure networking infrastructure around it so you are the only one accessing it.

Since the gatekeeper is not meant to be exposed to the Internet, obviously it is not possible "out of the box" to use Let's Encrypt for the gatekeeper certificates. The gatekeeper certificates are generated during setup and they are self-signed. Of course, you could make the gatekeeper listen to ports 80 and 443 and have forward rules so that Let's Encrypt can take care of its certificates, but then there will be one door between the Internet jungle and your bitcoins. We don't recommend this.

You should take the generated TLS certificates (found in one of the downloadable AES-256 encrypted 7z files on the Cyphernode Welcome app page) and add them to your client applications so you don't have to set NODE_TLS_REJECT_UNAUTHORIZED to false or anything similar that weakens security.

Accessing the CypherApps Zone (cyphernodeappsnet)

This zone is where the applications that are Cyphernode clients run. They most likely are web applications, but it's not required. Those applications have "local" access to the gatekeeper API. They are "authorized" applications, they own API IDs and keys for the API.

Traefik

We chose traefik (https://docs.traefik.io/) to expose the CypherApps to the Internet. Traefik can route the requests coming from the Internet to the right web application running in the cypherapps network. It takes care of the creation and renewal of the Let's Encrypt certificates. It supports multiple domain names and complex and flexible routing rules. It is open source, well known and well tested.

The cypherapps you want accessible from the Internet (like the Cyphernode Welcome app) will tell traefik how to route the requests to them with special docker labeling in the app's docker-compose file. It's very cool to be able to access your web apps with your own domain name and valid TLS certificates.

Traefik is there to access the cypherapps, not the gatekeeper API directly. Once again, you could bypass that by manually configuring the gatekeeper to be routed by Traefik. But it's just a security risk to expose your API.

Having layers of indirection with specific rules is always a good idea to protect your sensitive stuff. The cypherapps are one of those layers. They should have their own authentication, authorization, security implementations and application logging systems. The user is your cypherapp client and your cypherapp is the gatekeeper API client. Two separate things with different auth.

Tor

Another way to access your web applications is through Tor. Using Tor is a convenient way to avoid port forwarding configuration on your router. It is also fully encrypted by default. In Cyphernode, we generate v3 onion addresses that make them also one more layer of secret, as long as you don't publish them.

That is why Cyphernode is generating different onion addresses for the Bitcoin node, the Lightning Network node and Traefik. You can publish your LN onion address without publishing your Traefik web entrypoint address.

Since Tor traffic is encrypted by default, you will notice that most onion sites are HTTP only, not HTTPS. For example, if you ask Let's Encrypt to generate TLS certificates for an onion address, it will fail.

Tor and Traefik communication

To take advantage of the Traefik automatic routing functionality, we decided to make Tor use Traefik to avoid the need to duplicate the routing rules of Traefik in Tor. This means Tor will proxy the requests to Traefik when the Traefik Onion address is used.

Here is where it gets problematic: if we want Tor to serve an HTTP page (instead of HTTPS), we need to activate HTTP on Traefik. If we activate HTTP on Traefik, it will be possible to access it without encryption and potentially leak your passwords. We don't want that.

We tried to write Traefik rules so that it would accept HTTP requests ONLY if they are relayed by the Tor node. Unfortunately, we failed at it. We don't know yet how to do it. We think upgrading Traefik to v2 would allow us to do so though. That's one of our tasks on the huge todo list and it's difficult to estimate when it will be done.

Your Tor URL to the Welcome app would be http://t66jfcrnerds2uydne3ggaw2fdgny2l25acscc5zywhclgvudn7xndad.onion/welcome and you wouldn't have any invalid certs error messages in your browser.

One workaround would be to stop publishing your Traefik 80/443 ports outside docker and allow it to serve HTTP requests. Then, the only way to access your apps would be through Tor. You couldn't use Let's Encrypt with a clearnet domain name.

Let's Encrypt

I already opened an issue (https://github.com/SatoshiPortal/cyphernode/issues/127) where you also made a comment :) but here I will add more details about how to activate the Let's Encrypt functionality in Traefik.

  1. You need a domain name. Let's use cryptoskillz.com here.
  2. You need to add the public IP address used to access Traefik to your DNS records.
  3. You need to open and forward your router's 80 and 443 ports to your Cyphernode/Traefik server, if necessary.

If you built the Cyphernode images from sources:

  1. Change cyphernodeconf_docker/templates/traefik/traefik.toml with the changes below
  2. ./build.sh
  3. From dist/ run ./setup.sh and start Cyphernode

If you are using prebuilt images:

  1. You will unfortunately have to reapply the changes AFTER each ./setup.sh execution. You have to edit the file traefik.toml in the directory where you traefik files are stored. The default is cyphernode/traefik/traefik.toml from where setup.sh resides, but it can be changed during setup.

In both cases, here are the changes to do to the file:

Change yourdomain.com to cryptoskillz.com in the last [[acme.domains]] section and also change the email field for the e-mail you want Let's Encrypt to use to contact you.

Next time you start Cyphernode (./start.sh), Traefik will read that file and do its stuff to create/renew/take care of the Let's Encrypt certs. You should be able to access the Welcome app using https://cyphernode.cryptoskillz.com/welcome.


What a wall of text, sorry about that! Let me know if it helps... or not. :) Thank you for the issue!

Tomtibo commented 4 years ago

Hi, yes It's help me understand the cyphernode networks, you should definitively and this to the doc. One point still remaining. To avoid single point of faillure... What about CN redundency/HighAvailability? A single CN intance could lead to possible downtime and possible lost of funds. And syncing data(wallets, channels, config, cypherapps, etc..) across multiple, physicaly distant, CN instances, can be insecure and hard to implement.(for mirroring) Why cyphernode have docker swarm option in setup?(I've never try it.) Is it for take avantage of docker swarm High Availability fonctionality?

Thanks for your good work!