Giter Site home page Giter Site logo

multiserver's Issues

address format

Need to figure out an address format.

I'm thinking that something like
(type(:args)?)(,type(:args)?)*

where , is a separator, type is a protocol name (ws or net or utp etc) args is whatever information type needs (optional - for example gzip doesn't need args)

ipfs uses / like a unix path, but I think this is ambigious because you have to know how many arguments a type takes to be able to parse it! That is especially bad for an upgradable system where you may see a descriptor for a thing that you don't support yet, and won't know what it means. It may mean you'll need to do IO while parsing.

instead better to use a different seperator, and allow protocols to format their args however they need, (provided any internal separators are escaped)

'|' would be nice, because it's a lot like piping, but `,' means you couldn't need to escape it on the terminal.

scopes

I'm a bit confused by the scope thing. what i want:

I want a message that indicates your public address, but unlike the current "pub" messages, you should only speak for your self, not claim someone else's pub address. This would be used for pubs, and also, for peers behind tunnels, or introduced, etc...

so, basic pattern will be:

command to advertise public address:
check your public address. (configured or detected)
check if you have already posted a message about this.
if yes, do nothing.
If not, or the address has changed since then,
then publish a message.


when creating a user invite, query for peers (which maybe be someone's pub) that follows you closely (in hops distance) that also has a public address. these are the peers which are likely to service the invite, so attach several of these to the code, say 3.


but poking around, on my laptop I get "net:192.168.43.244:8008~shs:EMovhfIrFk4NihAKnRNhrfRaqIhBv1Wj8pTxJNgvCCY="
which is only a local network address...
but on my pub, I get "net:128.199.132.182:8008~shs:DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ="
which is good, that is a public address... but there is no way to tell from calling that method which sort of address it will be?

For example: I want to advertise the 192.168... address on a local wifi, but not on a public feed, but the other one I want on a public feed. do we need more distinctions than just public and private?

@arj03 what do you think?

create multiple tor services?

@arj03 is it possible to create multilpe tor hidden services via this api?

Oh, hmm - I just realized that this currently sets server: false which means this doesn't even create a server.... this creates the ability to use tor as a client protocol... but how do are you configuring the server?

asking because I am working on a less hardcoded api for using the various network protocols.

Two ssb-servers with plugin/unix-socket cannot run at the same time

Commit faa9526 introduced a module-level variable started (l.6-l.7) that is used to avoid reinitializing the unix socket twice. Unfortunately, when the plugin is used in two different Secret-Stacks running within the same node process, e.g. in unit tests, this strategy prevents the second instance from being initialized properly and is therefore ignored.

Moreover, l.27 returns undefined and therefore upon closing, the second instance fails with the following error:

.../node_modules/multiserver/compose.js:33
    if (f.length) return f(cb)
          ^

TypeError: Cannot read property 'length' of undefined
    at fnAsAsync (.../node_modules/multiserver/compose.js:33:11)
    at closeMultiserverServer (.../node_modules/multiserver/index.js:57:37)
    at close (.../node_modules/secret-stack/lib/core.js:259:82)
    at hooked (.../node_modules/hoox/index.js:10:15)
    at .../node_modules/ssb-db/index.js:90:11
    at .../node_modules/flumedb/index.js:263:25
    at .../node_modules/continuable-hash/index.js:25:25
    at Single._written (.../node_modules/async-single/proto.js:46:12)
    at release (.../node_modules/mutexify/index.js:25:13)
    at .../node_modules/atomic-file/inject.js:27:11
npm ERR! Test failed.  See above for more details.

At least, l.27 should be fixed to avoid an error on closing. Better, the check for avoiding duplicate initialization should be specific to a specific instance of Secret-Stack and not module-wide (which is initialized only once for all node module imports).

@arj03

net throws, when used in browser

in the browser, multiserver should not use net, hopefully they have also provided an address that works in the browser, such as websockets.

net 'external' should be an array

The SSB-Config documentation says that external is an array of external strings, but the Multiserver implementation parses it as a string. We need some tests and fixes around this.

Reported-by: @rbdr

Address format

Looking at: https://github.com/ssbc/multiserver#address-format I see that net is specified as net:, while wss is specified as wss://? Seems as if both should be specified the same way, so wss:wx.larpa.net~shs:DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ=, instead of wss://wx.larpa.net~shs:DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ=?

How should the `server` option be used?

It looks like we're having problems that seem to be resolved by server: true. From skimming the source, I can see opts.server used in three places:

$ git grep opts.server
plugins/onion.js:      if(!opts.server) return
plugins/onion.js:      if(opts && !opts.server) return null
plugins/unix-socket.js:    server: !opts.server ? null : function (onConnection) {
plugins/unix-socket.js:      if(opts && !opts.server) return null
plugins/ws.js:  var secure = opts.server && !!opts.server.key
plugins/ws.js:      var server = opts.server || http.createServer(opts.handler)
plugins/ws.js:      if(!opts.server) {
plugins/ws.js:      if(opts.server)
plugins/ws.js:        port = opts.server.address().port
  • Tor: when opts.server is falsy, it looks like the connection is abandoned and we instead just return.
  • Unix socket: Same as above, but instead of a function that immediately returns the function is being replaced by null. Is there a reason for the difference in these two implementations?
  • Websocket: It looks like opts.server is an object with two expected properties: key and address, and the latter is a function that returns an object with the property port. The full usage is opts.server.address().port, which makes me think there are some moving parts here I don't understand.

@dominictarr Could you add some info to help me better understand what we should be doing with this option? Apologies if this has already been recorded somewhere, so far I've checked #32, ssb-config, and scuttlebot but didn't see any notes about this change. Appreciate your help!

cc: @arj03 @cryptix

IPv6 addresses are not escaped inside net: addresses

If I do

sbot server --host=:: --port=8100 --ws.port=8101&
sbot getAddress -- --host=::1 --port=8100

I get:

net::::8100~ ... ;ws://[::]:8101

Is that desired behaviour because the square brackets are needed because the ws address is actually a URL and the net: address is not? Or is it a bug and it should be net:[::]:8100? cc @dominictarr

Recent versions of pull-stream break WebSocket plugin

It looks like require('pull-stream/pull') no longer has map, but require('pull-stream') does.

/node_modules/multiserver/plugins/ws.js:34
          stream.source = pull(stream.source, pull.map(Buffer))
                                                   ^

TypeError: pull.map is not a function
    at onConnect (/node_modules/multiserver/plugins/ws.js:34:52)
    at WebSocket.<anonymous> (/node_modules/pull-ws/source.js:49:13)
    at WebSocket.onError (/node_modules/ws/lib/WebSocket.js:452:14)
    at emitOne (events.js:116:13)
    at WebSocket.emit (events.js:211:7)
    at ClientRequest.onerror (/node_modules/ws/lib/WebSocket.js:711:10)
    at emitOne (events.js:116:13)
    at ClientRequest.emit (events.js:211:7)
    at Socket.socketErrorListener (_http_client.js:387:9)
    at emitOne (events.js:116:13)

Unix socket with default path exposes username over network

I saw in %94G9B4MPIbhQynNlCApdn88PlT73/PE9l/jKmOsxy84=.sha256 that we're broadcasting the unix socket over UDP, which exposes our username to all network peers. I'd love to avoid this, if possible. Potential solutions:

  1. Don't broadcast unix sockets (?)

  2. Use a temporary socket with mktemp

    $ mktemp
    /tmp/tmp.NrzUtkX6jl

why do multiserver addresses not include the "full" public key?

i notice that multiserver addresses, like

net:wx.larpa.net:8008~shs:DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ=

truncate the "full" public key to

DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ=

instead of

@DTNmX+4SjsgZ7xyDh5xxmNtFqa6pWi5Qtw7cE8aR9TQ=.ed25519

as is the format used everywhere else.

for more context, this became annoying when i wanted to write a jinja template for file managed by Salt Stack, where i had access to the values in ~/.ssb/secret but had no ability to truncate the public key as required to create a multiserver address in the template.

i've now worked around this problem, but i still was wondering on the thinking behind it, i don't know much about how important it is to have the curve in the key, as i think this is also implied when saying shs.

scopes

first some context, (maybe this can become documentation?)

multiserver is designed around plugins. there are two types of plugins, transports and transforms. Then transports make a connection to something, and transforms change something about it, such as encrypting and authenticating it, or compressing it. so far, we've just used the shs transform plugin to encrypt everything.

multiserver gives you a convienent handle to run multiple servers, with multiple protocol versions at the same time. that's why it's called multiserver. So, you can have multiple servers. We started to add that, but then we realized we needed something more: scopes. servers are useful for lots of things, but sometimes you don't want everyone to connect to them (we care about privacy, and would rather someone connect via tor, but local clients can use net), and other times, you know that someone can't connect to them anyway, so we want to avoid telling them about it. (we are running our server on a laptop on wifi, without a stable ip address. so we don't want to advertise our address publically, but maybe we do for another multiserver that is running on cjdns or tor etc)

Each transport plugin now takes a scope option, which is a string: the name of that scope. when a plugin is created, the plugin is passed the scope it will have. eg, Net({host: ..., port: ..., scope: 'public'})
plugins also have a scope() method, which just returns the scope it was configured with, or defaults to. so Plugin({scope: X}).scope() === X

When you call multiserver.stringify(scope) it then returns an address for that scope.
If scope is "private" then public plugins are allowed.

Okay I think I understand all that now. but why isn't my websocket server attaching? hmm...

remove footguns, make it hard to create insecure configurations

Today I gave a talk on designing for security. One of my main messages was "don't make it configurable" or at least "don't make it easier to have an insecure configuration"

I remembered that multiserver noauth is a potential problem here.
It would be easy to set net~noauth and it would be faster! except now anyone can connect to you, and tell you what to do, if you have noauth set.

It's not a responsible design to expect them to understand not to use noauth with a network.
They should have to explicitly enable the footgun.

My idea to approach this: first make sure all the plugins set an address property consistently.
then, have noauth take an address config option, and refuse connections that do not have the correct address. This means to enable noauth, you have to set the address twice!

ws: [{scope: 'device', port: 8989, transform: { name: 'noauth', address: 'ws://localhost:8989' }}]

or something like that. We don't have a way to specify configuration for transforms yet.

I have this about half coded

thoughts? @arj03 @regular

net: bind to internal host, return external host

so i'm working on the ButtCloud infrastructure (butt), i finally figured out a bug that's kept me stuck on that front for over a week.

it seems i need a way for the scuttlebot server to bind to a host like 0.0.0.0 (internal to the Docker Swarm service, which is automatically available to other internal services and exported via an ingress router to the external internet), but then advertise a different public host like party.butt.nz (like when publishing invites and things).

Stringify may be returning the wrong address for net and ws

See: ssbc/patchwork#1035

We have a scenario where config.connections.incoming is specifying the correct IP addresses but it looks like this code is still falling back to multiserver-scopes (i.e. non-private-ip) in the local scope:

var _host = (scope == 'public' && opts.external) || scopes.host(scope)

I'd imagine that this is a bug or maybe I'm completely misunderstanding what this is supposed to do? For example, my config:

{ net:
  [ { host: '127.0.0.1',
    port: 8008,
    scope: [ 'device' ],
    transform: 'shs' },
    { host: '::1', port: 8008, scope: [ 'device' ], transform: 'shs' },
    { host: '192.168.0.109',
      port: 8008,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' },
    { host: '172.18.0.1',
      port: 8008,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' },
    { host: 'fce2:9811:4862:81a7:bb08:91d6:2e41:d220',
      port: 8008,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' } ],
  ws:
  [ { host: '127.0.0.1',
    port: 8989,
    scope: [ 'device' ],
    transform: 'shs' },
    { host: '::1', port: 8989, scope: [ 'device' ], transform: 'shs' },
    { host: '192.168.0.109',
      port: 8989,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' },
    { host: '172.18.0.1',
      port: 8989,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' },
    { host: 'fce2:9811:4862:81a7:bb08:91d6:2e41:d220',
      port: 8989,
      scope: [ 'device', 'local', 'public' ],
      transform: 'shs' } ],
  unix: [ { scope: 'device', transform: 'noauth' } ] } }

But over the network I see:

net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=;net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=;net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=;ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=;ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=;ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=

Replacing the semicolons with newlines (I'd love if this was the default):

net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=
net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=
net:192.168.0.109:8008~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=
ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=
ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=
ws://192.168.0.109:8989~shs:+oaWWDs8g73EZFUMfW37R/ULtFEjwKN/DczvdYihjbU=

Maybe relevant: #22

cc: @dominictarr @arj03 @regular @cryptix

Why does noauth need the public key?

I see this commit, but I don't understand what's the context around that commit. What breaks if we use empty strings instead?

My context: given that I'm using trusted transports (e.g. react native's "bridge" which is closed to other applications in the OS, and obviously closed to remote actors), I believe I don't need the public key, hence I could save the cost of using FS APIs on the frontend looking for secret, but the way noauth plugin is built requires me to pass it a public key.

ws test failing on macos

Brief bug report because I'm on mobile walking home. Spent a few hours today debugging why the Travis tests on MacOS are failing and I'm very confused. I'm seeing this on the 'main' branch and also on my branch with the new Pull-WS.

We're starting a WS client and server, and then connecting to server.stringify(), but when we do the if (err) throw err dance we end up throwing a weird error.

The error originates from a net server on some ungodly high port, but plugs.js isn't listening there. Maybe the problem is caused by multiple tests running at the same time? Anyway, the problem is that we're receiving a TCP + SHS connection but the client connecting doesn't have a public key in their address. I don't know what would cause this.

Tomorrow I'll probably edit the test command so that we're only testing the one file. I'm worriee about why we'd be propagating an error from another server (race condition?), but I wouldn't be surprised.

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.