[NKP-0003] Providing https/wss endpoint for EVERY NKN node

Currently NKN node only expose plain websocket/http endpoint at port 30002/30003 without ssl. But since most website are using https, it is not allowed to access any NKN node through ws/http protocol without ssl. For nkn wallet, this is kind of solvable (but not ideal) by using a few API nodes provided by us or any nodes linked with a domain and valid ssl certificate. But for nkn client, it’s very difficult to use because a client does not know in advance which node he will be connecting to. To make nkn client practically usable in most web apps, we have to make EVERY NKN node https/wss compatible.

The current code already supports wss and https, but the major reason that people don’t do it is because ssl certificate. By design, ssl certificate should be assigned to domain rather than IP address (see some discussion at https://stackoverflow.com/questions/2043617/is-it-possible-to-have-ssl-certificate-for-ip-address-not-domain-name), not to mention the tedious process of creating certificate and renew on expire.

Https itself is a centralized design, and the easiest way I can think of to make it work for every node is to use the help of another centralized system. What I’m proposing is to set up a site, e.g. x.com, and it’s doing 2 things:

  1. Making request to x.com/A.B.C.D or x.com/A-B-C-D from IP address A.B.C.D will give you a ssl certificate valid for A-B-C-D.ipv4.x.com
  2. DNS query to A-B-C-D.ipv4.x.com will get A.B.C.D as result

Then each NKN node, when starting, will get or update the ssl certificate for domain A-B-C-D.ipv4.x.com assuming his ip address is A.B.C.D, and serve https/wss endpoint at A-B-C-D.ipv4.x.com and separate port (e.g. 30004/30005) which is configurable.

Generating a unique certificate for each subdomain corresponding to an IP address may not be feasible, so I was thinking may we could just provide a single wildcard certificate that is valid for *.ipv4.x.com, but we need to be very careful here because it means the data is essentially not encrypted (since anyone can get the private key), which is OK in NKN because we are assuming every node could be malicious and can no sensitive data should be send to NKN node without encryption and signature.

Although this is a centralized solution that relies on x.com, we can make it an open protocol such that any domain (e.g. yyy.com) that implements the 2 functions above can serve this purpose, and user can choose whether to use x.com or yyy.com such that there is really no single entity that can take control.

To be more general, this could be a quite general solution for any permission-less and (real) decentralized system that has a problem in ssl certificate.

It’d be good if we can discuss about the security, feasibility, or other aspect of the proposal, or even better if we can come up with a better solution.

1 Like

There is ACME protocol which automates getting SSL certificate for domain: https://letsencrypt.org/docs/client-options/
Every node can generate unique id (maybe using combination of public key and IP or public key and some user-specified id) and register SSL for that domain. That way each node will exclusively own their SSL certificate’s private key (and certificate generation will be kinda more decentralized that way).

Then we only need to provide centralized DNS server (could be open source), where any node could register it’s domain for SSL certificate.
We can also ask node to sign something with it’s private key for it to be able to register itself in DNS to guarantee that some domain name was registered exactly by that node (and not some other node).

If I remember correctly, ACME requires http challenge (basically statically hosted file with given content/code) which is a problem, because it requires nodes to have access to port 80.
We might be able to get the challenge to different subdomain (acme.A-B-C-D.ipv4.xxx.com) and this would actually point to xxx.com which would be able to handle the :80 http request. However, there would have to be some url like xxx.com/setChallenge/A-B-C-D/:data so the node can set what this “master” should respond to challenge.

there’s also dns challenge, which requires you to set TXT record. basically you still need some kind of set challenge command on dns server, but no need for xxx.com to handle :80.

After thinking about it more I like suggested wildcard solution better (since everything is e2e already we don’t care about someone owning SSL’s private key). Though I suggest to simplify it a bit more.

We can just bundle SSL’s private key together with the node and have xxx.com as default in config for parent domain parameter.
Also we should extend NodeData with node’s hostname (that will be given to clients through getwsaddr). Basically this new field in NodeData is just ip+specified parent domain (like 127-0-0-1.xxx.com).
If node operator doesn’t like xxx.com for some reason he can generate it’s own certificate for *.yyy.com and specifiy yyy.com in config instead.

The only simple thing we need to provide is open-sourced dns server which will return ip contained in the resolved hostname, e.g. 127.0.0.1 for 127-0-0-1.what.ever

What are your thoughts? @yilun @JohnSmith

Let’s encrypt is what we are using now, but it has really strict limits and restrictions (e.g. 50 certificates per domain per week, see more at https://letsencrypt.org/docs/rate-limits/ ) which makes it not quite feasible to obtain a certificate for each IP (subdomain).

Actually I’m not aware of any service that can give us such high number of certificate fully automatically with a affordable price :joy: That’s why I now think wildcard solution is probably the only practical solution so far…

Hi,

I want to point out that the current situation makes it impossible to use the nkn client software in a https web context. That is, in my opinion, a really severely limiting factor of even considering nkn in a enterprise context.

That being said, i do now understand somewhat why this is a big technical issue with no real solution (yet). You don’t want to be dependent on centralized authorities for a decentralized system. It kinda beats the point of an otherwise awesome decentralized system.

So… now the kicker.
Why not make NKN a Decentralized Certificate Authority!? Really, why not?
NKN in particular seems quite suited to take on that role. It has a large node network, it has different transaction types (where a new type for certificate authority should then be added) and it has a quite speedy network as opposed to loads of other blockchains out there.
On top of that, using NKN with it’s certificate authority would really help distributed app (dapp) developers to go one more step in a truly decentralized world if their certificate comes from a decentralized network too. It will also help other decentralized network for their decentralized connection points!

A system like this seems desperately needed. Or rather, it seems if i read https://habr.com/en/company/encry/blog/473548/ and https://tools.ietf.org/html/draft-iab-web-pki-problems-01#section-3.2.1

It would also fit in really well with nCDN as you would probably want to have those resources served from secured environments, just like you have CDN’s on the regular weg that offer (obviously) https connections to get those resources.

I think (if i understand the issue correctly) that this would solve the whole issue of having every node have a certificate to allow for a secured connection, will it not?

As for payment, the NKN token can be used for that i suppose. Or the same model can be used like is currently in use on NKN (no payment at all).

Go for it! :smiley:

1 Like

I agree with your point. But for the solution, it’s not about if we want to be a CA, but whether browser trust us as a CA. Technically we can indeed provide a decentralized CA, but unless our solution is accepted and integrated into major browsers, it’s still not usable because what prevents us from using https is the browser :sweat_smile: This could be a good long term goal, but probably not a short term one…

That is a chicken and egg problem. You won’t know until you try :slight_smile:
I would just go for it and see how far it gets. Why wouldn’t they accept you as a CA?

But this is easier said then done. I suppose if you folks actually go for this it might be a quite long intensive plan to get it implemented and approved by other CA’s.

If Let’s encrypt could manage it then you folks definitely can too.

Haha I think you probably haven’t realized the true difficulty yet :sweat_smile:

The problem here cannot be solved by any CA, not even we are now a CA. The reason is very simple: any CA, including us, cannot assign certificates on bare IP address on reusable bare IP address because of security. So unless every NKN node has its domain (which is not practical), it’s not going to work, even if NKN is a CA.

To solve this problem in a decentralized way, we need to start from changing the current DNS protocol. That is, do not rely on a few name server to return the IP address of a domain, but get from decentralized source like a blockchain. Then we need to change the current certs protocol and, instead of using certs signed by CA, fetch certs from decentralized sources like a blockchain. Both of them requires huge protocol change that needs to be supported by every major browser, https library, etc. This will take decades even if it’s lead by any major company or alliance in the world :sweat_smile:

Ahh, i see!
Now that you said that, i too was under the impression that certificates need to be bound to an IP or Domain.

But… :slight_smile:
I googled a bit and now i’m not so sure anymore. Don’t take my word for it though, i’m no expert at all and merely google around a bit to look for information. What i have found might actually be something interesting for this case… or i might interpret it wrongly and it results in not being applicable in this case.

Anyhow, the specs “seem” to provide for a load of different ways to bind a certificate to something unique. The options are:

GeneralName ::= CHOICE {
    otherName                       [0]     OtherName,
    rfc822Name                      [1]     IA5String,
    dNSName                         [2]     IA5String,
    x400Address                     [3]     ORAddress,
    directoryName                   [4]     Name,
    ediPartyName                    [5]     EDIPartyName,
    uniformResourceIdentifier       [6]     IA5String,
    iPAddress                       [7]     OCTET STRING,
    registeredID                    [8]     OBJECT IDENTIFIER }

(be sure to read https://stackoverflow.com/a/35682183 !!)
If i follow that post then using something like the wallet address (or the public key) as unique name would actually be an option here!

If that isn’t an option (due to for example browser support?) then SNI might still be a viable option. In that scenario the nkn wallet address (or again the public key) would be the “hostname”. If that works, i have no clue!

I do hope either of these options brings you a step closer in supporting “wss” (secure websockets) though.

Again this is not about how to generate certificate (like the link you sent), but about how everyone’s browser resolve address and get certificate. Since wss is based on https, the only options are browser-supported https certificate, which don’t have any room for decentralization yet.

This NKP has been implemented