Giter VIP home page Giter VIP logo

libp2p-nodetrust's Introduction

libp2p-nodetrust

Why not give every libp2p node an IP.ip.libp2p.io address and certificate?

Why

Currently the browser communicates over ONE signalling server and a few bootstrapper nodes (which then get used as releays for all the other TCP nodes)

When a large number of browser nodes using the default configuration joins the network those nodes and the server get overloaded pretty quickly. Additionally they can be all blocked by some malicious government (china, russia, ...) thus creating a single point of failure.

The only solution would be to make the browser connect to some other websocket-capable nodes.

Problem: HTTP on HTTPS is disabled due to security

Solution: HTTPS enabled websocket nodes

How

A libp2p node (the "server") will run a special dns server that resolves ips encoded in subdomains to real ips. Example: ip48-8-8-8.ip.libp2p-nodetrust.tk => [A] 8.8.8.8

This server will additionally offer letsencrypt certificates for the domain over the /nodetrust/2.0.0 protocol which requires the client to connect over tcp in order to determine it's ip address.

Nodes will then announce themselves over floodsub in the _nodetrust_discovery_v2 channel. Those messages will get relayed by the server.

Additionally the clients will relay each others floodsub messages so there is no single point of failure after the certificate has been obtained.

Development

Might be outdated

Server

The configs for development have already been created for you. In order to launch the 3 services in 1 terminal we recommend Overmind

Go to server/src and run overmind s

Certificate

You need a certificate for ip4127-0-0-1.ip.libp2p-nodetrust.tk to use the server-stub. You can either generate a self-signed using server/gencert.sh or request a valid one from me at mkg20001 at gmail dot com.

Usage

Run nodemon src/bin.js ./config.dev.json in the server/ directory

Client

Run nodemon -x env NODETRUST_IGNORE_ID_FILTER=1 SKIP_NAT=1 USE_LOCAL=1 node test-client.js

libp2p-nodetrust's People

Contributors

mkg20001 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

libp2p-nodetrust's Issues

Make DNS server spec-compilant

Currently the command dig ip48-8-8-8.ip.libp2p-nodetrust.tk @ns.libp2p-nodetrust.tk yields a warning about malformed message packets.

Validate peer-id based on cn?

In feat/protocol-improvments the common name for the certificate is the hashed peer-id (mixed with a suffix and prefix).
Possibly considering to validate that one too in order to make things more secure...

Wildcard Certificate Improvements

Once lets encrypt supports wildcard certificates, consider:

  1. Having everyone use the same wildcard cert + key.
  2. Putting the key + cert in IPFS and creating a dnslink record (with a really long TTL) mapping /ipns/your.domain to the IPFS directory with the cert+key.
  3. Configuring the DHS server to map IP.your.domain to IP (with a really long TTL).

This will:

  1. Reduce the load on the DNS server (long TTLs).
  2. Require only the special DNS server + an IPFS server.
  3. Allow peers to use this service without having to contact any external service when they change their IP address.
  4. Allow us to ship IPFS with built-in support for this system. The only necessary configuration will be some setting telling IPFS to use some set of SSL domains.

Get rid of the hacks

This module currently uses some libp2p hacks
Things that libp2p needs to support:

  • Changing transports at runtime
  • Changing listeners at runtime

Problems with domains

https://sentry.zion.host/libp2p/nodetrust-server/issues/128/

Error: authorizations were not fetched
  File "/home/maciej/libp2p-nodetrust/server/node_modules/acme-v2/node.js", line 573, in null.<anonymous>
    return Promise.reject(new Error('authorizations were not fetched'))
  ?, in null.<anonymous>
  File "internal/process/next_tick.js", line 228, in process._tickDomainCallback

Error: authorizations were not fetched

Logs:

2018-07-05T14:09:40.845Z libp2p:secio 3. finish - finish
2018-07-05T14:09:40.994Z nodetrust:dns [208.69.32.73:47432#52502]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:41.015Z nodetrust:dns [45.76.11.166:43656#49084]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:41.020Z libp2p:switch:dial dialing QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:41.020Z libp2p:floodsub dialing QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:41.022Z nodetrust:dns [74.125.44.83:61157#29253]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:41.022Z libp2p:switch:dial dialing QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:41.036Z nodetrust:dns [8.0.38.143:27508#6022]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:41.052Z nodetrust:protocol cert for QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:41.053Z nodetrust:letsencrypt:acme get certificate QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk, ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.138Z nodetrust:letsencrypt:acme:queue execute task @QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B,id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk@id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.138Z nodetrust:letsencrypt:acme:queue lock domain id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk for @QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B,id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk@id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.139Z nodetrust:letsencrypt:acme:queue lock domain ip488-99-218-136.ip.libp2p-nodetrust.tk for @QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B,id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk@id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.139Z nodetrust:letsencrypt:acme obtain certificate id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk, ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.139Z acme-v2 DEBUG get cert 1
2018-07-05T14:09:42.139Z acme-v2 certificates.create
2018-07-05T14:09:42.170Z acme-v2 newOrder
2018-07-05T14:09:42.171Z nodetrust:dns [74.125.44.65:55063#230]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.171Z nodetrust:dns [199.7.60.213:35688#46727]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.172Z nodetrust:dns [208.69.32.73:32977#58008]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.172Z nodetrust:dns [208.69.32.77:53818#15516]	ip4136-243-32-225.ip.libp2p-nodetrust.tk	=>	[A]	136.243.32.225
2018-07-05T14:09:42.173Z nodetrust:dns [199.7.60.213:25873#64241]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.173Z nodetrust:dns [192.221.167.13:12864#32555]	ip4136-243-32-225.ip.libp2p-nodetrust.tk	=>	[A]	136.243.32.225
2018-07-05T14:09:42.173Z nodetrust:dns [208.69.32.73:5329#34619]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.173Z nodetrust:dns [208.69.32.77:38833#48286]	ip4136-243-32-225.ip.libp2p-nodetrust.tk	=>	[A]	136.243.32.225
2018-07-05T14:09:42.174Z nodetrust:dns [192.221.167.6:33124#37700]	ip4136-243-32-225.ip.libp2p-nodetrust.tk	=>	[A]	136.243.32.225
2018-07-05T14:09:42.174Z nodetrust:dns [74.125.44.84:48953#527]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.174Z nodetrust:dns [199.7.60.213:4982#63189]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.180Z libp2p:floodsub new peer QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:42.182Z libp2p:floodsub connected QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:42.183Z libp2p:floodsub rpc from QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:42.186Z libp2p:circuit:dialer HOP supported adding as relay - QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B
2018-07-05T14:09:42.272Z nodetrust:dns [208.69.32.73:39966#14329]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×
2018-07-05T14:09:42.363Z acme-v2 undefined
2018-07-05T14:09:42.364Z acme-v2 { statusCode: 400,
  body: 
   { type: 'urn:ietf:params:acme:error:malformed',
     detail: 'Error creating new order :: Invalid character in DNS name',
     status: 400 },
  headers: 
   { server: 'nginx',
     'content-type': 'application/problem+json',
     'content-length': '142',
     'boulder-requester': '35968123',
     'replay-nonce': 'kFSgAAUG9UwxVllhM58GlVnYLIP0xtV6r6R_I9lCmpY',
     expires: 'Thu, 05 Jul 2018 14:09:42 GMT',
     'cache-control': 'max-age=0, no-cache, no-store',
     pragma: 'no-cache',
     date: 'Thu, 05 Jul 2018 14:09:42 GMT',
     connection: 'close' },
  request: 
   { uri: 
      Url {
        protocol: 'https:',
        slashes: true,
        auth: null,
        host: 'acme-v02.api.letsencrypt.org',
        port: 443,
        hostname: 'acme-v02.api.letsencrypt.org',
        hash: null,
        search: null,
        query: null,
        pathname: '/acme/new-order',
        path: '/acme/new-order',
        href: 'https://acme-v02.api.letsencrypt.org/acme/new-order' },
     method: 'POST',
     headers: 
      { 'User-Agent': 'Greenlock/1.0.9 (Linux; x64 linux 4.4.0-97-generic) Node.js/v8.11.3',
        'Content-Type': 'application/jose+json',
        accept: 'application/json',
        'content-length': 874 } } }
authorizations were not fetched:
{ type: 'urn:ietf:params:acme:error:malformed',
  detail: 'Error creating new order :: Invalid character in DNS name',
  status: 400 }
2018-07-05T14:09:42.365Z nodetrust:letsencrypt:acme:queue finished task @QmTiZztTh33nuMFq5ZyW8mCrnzDbPP9zvaGV5UPXrcKR1B,id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk@id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk!ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.365Z nodetrust:letsencrypt:acme:queue unlock domain id0elhowuyg5nr5yrodcm58r9dn7p5qrujz-lspg-.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.365Z nodetrust:letsencrypt:acme:queue unlock domain ip488-99-218-136.ip.libp2p-nodetrust.tk
2018-07-05T14:09:42.365Z nodetrust:protocol Error: authorizations were not fetched
    at /home/maciej/libp2p-nodetrust/server/node_modules/acme-v2/node.js:573:31
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)
2018-07-05T14:09:42.368Z nodetrust:dns [208.69.32.73:42068#59819]	id0elg2wqm91z50kp2a8ratswm-bk1i9guixoqkpp.ip.libp2p-nodetrust.tk	=>	×

Rewrite letsencrypt part using acme-v2

Currently this module uses greenlock to obtain letsencrypt certificates

Greenlock seems a bit buggy and has also likely problems with race conditions, as seen in #20

I'm going to rewrite this using acme-v2 directly (which is the module greenlock relies on)

Race conditions

  • Two peers from the same IP try to aquire a certificate at roughly the same time.
  • Two test nodes change the TXT records for a domain at the same time because tests run in parallel

Both result in a failure to aquire a certificate

Add tests

Tests:

  • Client:
    • Get certificate from server
    • Start wss server
    • Dial wss server
  • Server:
    • Check if DNS works
    • Get certificate from letsencrypt (via client)
  • Browser client:
    • Connect to server
    • Discover and dial wss nodes

Handle both ipv4 and ipv6

Currently a cert is issued for the current TCP/IP address of the client
Instead the certificate issuance and IP address proof should be seperated.

New workflow draft:

  • Client connects to v4.libp2p-nodetrust.tk, protocol /p2p/nodetrust/proof/1.0.0, server responds with a signed proof.
  • Client connects to v6.libp2p-nodetrust.tk, protocol /p2p/nodetrust/proof/1.0.0, server responds with a signed proof.
  • Client connects to fc00.libp2p-nodetrust.tk, protocol /p2p/nodetrust/proof/1.0.0, server responds with a signed proof.
  • Client connects to issuer.libp2p-nodetrust.tk, protocol /p2p/nodetrust/issue/1.0.0 and sends both proofs (if the client failed to aquire some of them because v4/v6/fc00 wasn't available the client sends the one it got).
  • Server verifies both tokens by verifying the proofs the v4, v6 and fc00 proof servers generated (they need to be seperate, TODO: split this into microservices) and issues a cert.

Edit: Now using signed proofs instead of tokens
Edit: Added CJDNS!

Improvments

  • Cache certificates based on IP+ID pairs instead of just IP.
  • Improve the protobuf protocol for better upgradability (such as changing from PEM to other encodings)
  • Be more transparent about caching

Rethink id0 addresses

Currently ever cert's CN is id0.
The hash isn't really used anywhere. It could be left in as a way to distinguish different certs for the same ip that are for multiple nodes.

Deploy to libp2p-nodetrust.tk for demo

Todos:

  • Finish pdns dns provider
  • Add different cert methods (csr-ca: The current certificate signing method, drop-wildcard: Just return the same wildcard certificate without requiring a csr)
  • Tests
  • Wait for letsencrypt to add wildcard cert support (Jan 7th dev, Feb 27th production) Use dev-ca for demo
  • Add website & deploy

Split this into microservices

In order to clean some of the mess in this module it should be split up into multiple micro services:

  • DNS
  • Certificate Issuance
  • Proof generation (#24)

Detect IP changes

Sometimes the IP of a client may change. The client should periodically check for IP changes as the cert-renewal time is 90 days

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.