holepunchto / hyperbeam

A 1-1 end-to-end encrypted internet pipe powered by Hyperswarm
MIT License
505 stars 35 forks source link

Remote closed without sending a FINISH tag (possible MITM vector) #10

Open raphael10-collab opened 2 years ago

raphael10-collab commented 2 years ago

Hi @mafintosh ! In order to understand how to use Hyperbeam for programmatically exchanging messages, I played with a simple Duplex stream as follows:

const Hyperbeam = require('hyperbeam')
const beam = new Hyperbeam('from mafintosh')

const stream = require('stream')

const inOutStream = new stream.Duplex({
  write: function(chunk, encoding, callback) {
      console.log(chunk.toString())
      callback()
  },

  read(size) {
      const smileys = [':)', ':P', ':D', 'xD', '^_^', ':(']
      const randomSmiley = smileys[
          Math.floor(Math.random() * smileys.length)
      ]
      const isSadSmiley = randomSmiley === ':('
      if (isSadSmiley) {
          this.push(null)
          return
      }
      for(i = 0; i < 4; i++) {
          this.push(randomSmiley.toString())
          this.push("\n")
      }
  },

  // https://nodejs.org/dist/latest-v14.x/docs/api/stream.html#stream_class_stream_duplex

  finished(err) {
      if (err) {
          console.error('Stream failed.', err)
      } else {
          console.log('Stream is done reading.')
      }

  }

})

//process.stdin.pipe(beam).pipe(process.stdout)
inOutStream.pipe(beam).on('finish', () => {console.log("All writes are now complete")}).pipe(process.stdout)

On the other side I have the simple "plain" code:

const Hyperbeam = require('hyperbeam')
const beam = new Hyperbeam('from mafintosh')
process.stdin.pipe(beam).pipe(process.stdout)
process.stdin.on('close', () => {
    console.log("closing....")
})

Executing the code I get:

(base) marco@marco-U365SG:~/hypercore/hyperswarm/hypermea$ node hyperseam_chat.js
:D 
:D 
:D 
:D 
^_^
^_^
^_^
^_^

And on the reader side I get this:

    (base) raphy@pc:~/hypercore/hyperswarm/hyperbeam$ node hyperbeam_chat.js
    All writes are now complete

If I close the writer stream with CTRL+C , I get on the reader side:

    (base) raphy@pc:~/hypercore/hyperswarm/hyperbeam$ node hyperbeam_chat.js
    All writes are now complete
    events.js:292
          throw er; // Unhandled 'error' event
          ^

    Error: Remote closed without sending a FINISH tag (possible MITM vector)
        at NoisePeer._onclose (/home/raphy/hypercore/hyperswarm/hyperbeam/node_modules/noise-peer/index.js:304:64)
        at Socket.emit (events.js:327:22)
        at TCP.<anonymous> (net.js:673:12)
    Emitted 'error' event on NoisePeer instance at:
        at emitErrorNT (/home/raphy/hypercore/hyperswarm/hyperbeam/node_modules/readable-stream/lib/internal/streams/destroy.js:87:8)
        at emitErrorAndCloseNT (/home/raphy/hypercore/hyperswarm/hyperbeam/node_modules/readable-stream/lib/internal/streams/destroy.js:57:3)
        at processTicksAndRejections (internal/process/task_queues.js:80:21)
    (base) raphy@pc:~/hypercore/hyperswarm/hyperbeam$ 

How to solve the problem?

ninpnin commented 2 years ago

I consistently get the same error when sending one particular large file.

draeder commented 2 years ago

I haven't tried it, but you might be able to do something like:

process.once('SIGINT', () => {
  beam.destroy()
  process.exit(0)
})