[
  {
    "path": ".gitignore",
    "content": "package-lock.json\nnode_modules\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# hyperssh\n\nSSH and SSHFS over the [Hyperswarm DHT](https://github.com/holepunchto/hyperdht)!\n\n## Installation\n```\nnpm install -g hyperssh // ssh / fuse client stubs\nnpm install -g hypertele // hyperswarm server proxy\nnpm install -g hyper-cmd-utils // keygen utils\n```\n\n## Usage\n\n### Server\n\nOn a server\n\n```sh\nhyper-cmd-util-keygen --gen_seed\n-> SEED\n\nhypertele-server --seed SEED -l 22\n-> PEER_KEY\n```\n\nThis will start announcing the server on the DHT.\n\n### Client\n\nOn the client\n\n```sh\nhyperssh -s ab01f... -u maf\nhyperssh -s ab01f... -u maf -i keypair.json\n```\n\nRead more about using identities here: https://github.com/prdn/hyper-cmd-docs/blob/main/identity.md\n\nSSHFS (mount a remove fs/folder via ssh)\n\n```sh\nhyperssh-fuse -s ab01f... -u maf -m ~/mnt\n```\n\nHyperswarm will do UDP holepunching under the hood, so even if your server is located on a home network it should be accessible.\n\n### Windows RDP\n\nYou can also use hyperssh with Windows RDP to remotely log in to your windows machines.\n\nOn the server\n```sh\nhypertele-server --seed SEED -l 3389\n```\n\nOn the client\n```sh\nhyperssh --rdp -s ...\n```\n\n## The hyper-cmd system\n\nhyperssh supports the hyper-cmd system!\n\nIdentity management: https://github.com/prdn/hyper-cmd-docs/blob/main/identity.md\n\nHost resolution: https://github.com/prdn/hyper-cmd-docs/blob/main/resolve.md\n\n## License\n\nMIT\n"
  },
  {
    "path": "client.js",
    "content": "#!/usr/bin/env node\n\nconst { spawn } = require('child_process')\nconst os = require('os')\nconst HyperDHT = require('hyperdht')\nconst net = require('net')\nconst argv = require('minimist')(process.argv.slice(2))\nconst libNet = require('@hyper-cmd/lib-net')\nconst libUtils = require('@hyper-cmd/lib-utils')\nconst libKeys = require('@hyper-cmd/lib-keys')\nconst connPiper = libNet.connPiper\n\nconst helpMsg = 'Usage:\\nhyperssh ?-i identity.json ?-s peer_key ?-u username ?-e ssh_command ?--rdp'\n\nif (argv.help) {\n  console.log(helpMsg)\n  process.exit(-1)\n}\n\nconst conf = {}\n\nif (argv.s) {\n  conf.peer = libUtils.resolveHostToKey([], argv.s)\n}\n\nif (!conf.keepAlive) {\n  conf.keepAlive = 5000\n}\n\nconst peer = conf.peer\nif (!peer) {\n  console.error('Error: peer is invalid')\n  process.exit(-1)\n}\n\nconst sshCommand = argv.e || ''\n\nfunction sshArgs (username, port) {\n  return [\n    '-o', 'StrictHostKeyChecking=no',\n    '-o', 'UserKnownHostsFile=/dev/null',\n    '-p', port,\n    username + '@localhost'\n  ].concat(sshCommand)\n}\n\nlet keyPair = null\nif (argv.i) {\n  keyPair = libUtils.resolveIdentity([], argv.i)\n\n  if (!keyPair) {\n    console.error('Error: identity file invalid')\n    process.exit(-1)\n  }\n\n  keyPair = libKeys.parseKeyPair(keyPair)\n}\n\nconst username = argv.u || os.userInfo().username\n\nconst dht = new HyperDHT({\n  keyPair\n})\n\nconst proxy = net.createServer(c => {\n  return connPiper(c, () => {\n    const stream = dht.connect(Buffer.from(peer, 'hex'))\n    stream.setKeepAlive(conf.keepAlive)\n\n    return stream\n  }, {}, {})\n})\n\nif (argv.rdp) {\n  proxy.listen(3389, function () {\n    console.log('Client listening on port 3389 (default RDP port)\\nOpen your RDP client and connect to localhost')\n  })\n} else {\n  proxy.listen(0, function () {\n    const { port } = proxy.address()\n\n    spawn('ssh', sshArgs(username, port), {\n      stdio: 'inherit'\n    }).once('exit', function (code) {\n      process.exit(code)\n    })\n  })\n}\n\nprocess.once('SIGINT', () => {\n  dht.destroy().then(() => {\n    process.exit()\n  })\n})\n"
  },
  {
    "path": "fuse.js",
    "content": "#!/usr/bin/env node\n\nconst { spawn } = require('child_process')\nconst os = require('os')\nconst HyperDHT = require('hyperdht')\nconst net = require('net')\nconst argv = require('minimist')(process.argv.slice(2))\nconst libNet = require('@hyper-cmd/lib-net')\nconst libUtils = require('@hyper-cmd/lib-utils')\nconst libKeys = require('@hyper-cmd/lib-keys')\nconst connPiper = libNet.connPiper\n\nconst helpMsg = 'Usage:\\nhyperssh-fuse ?-i identity.json ?-s peer_key ?-u username'\n\nif (argv.help) {\n  console.log(helpMsg)\n  process.exit(-1)\n}\n\nconst conf = {}\n\nif (argv.s) {\n  conf.peer = libUtils.resolveHostToKey([], argv.s)\n}\n\nconst peer = conf.peer\nif (!peer) {\n  console.error('Error: peer is invalid')\n  process.exit(-1)\n}\n\nif (!argv.m) {\n  console.error('Error: mount point invalid')\n}\n\nconst mount = argv.m\n\nfunction sshArgs (username, port) {\n  return [\n    username + '@localhost:',\n    mount,\n    '-p', port\n  ]\n}\n\nlet keyPair = null\nif (argv.i) {\n  keyPair = libUtils.resolveIdentity([], argv.i)\n\n  if (!keyPair) {\n    console.error('Error: identity file invalid')\n    process.exit(-1)\n  }\n\n  keyPair = libKeys.parseKeyPair(keyPair)\n}\n\nconst username = argv.u || os.userInfo().username\n\nconst dht = new HyperDHT({\n  keyPair\n})\n\nconst proxy = net.createServer(c => {\n  return connPiper(c, () => {\n    return dht.connect(Buffer.from(peer, 'hex'))\n  }, {}, {})\n})\n\nproxy.listen(0, function () {\n  const { port } = proxy.address()\n\n  spawn('sshfs', sshArgs(username, port), {\n    stdio: 'inherit'\n  }).once('exit', function (code) {\n    // stay alive\n  })\n})\n\nprocess.once('SIGINT', () => {\n  dht.destroy().then(() => {\n    process.exit()\n  })\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"hyperssh\",\n  \"version\": \"5.0.4\",\n  \"description\": \"Run SSH over Hyperswarm Beta!\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@hyper-cmd/lib-net\": \"git+https://github.com/holepunchto/hyper-cmd-lib-net#v0.1.0\",\n    \"@hyper-cmd/lib-keys\": \"git+https://github.com/holepunchto/hyper-cmd-lib-keys#v0.1.1\",\n    \"@hyper-cmd/lib-utils\": \"git+https://github.com/holepunchto/hyper-cmd-lib-utils#v0.1.0\",\n    \"hyperdht\": \"^6.20.1\",\n    \"minimist\": \"1.2.8\"\n  },\n  \"bin\": {\n    \"hyperssh-fuse\": \"./fuse.js\",\n    \"hyperssh\": \"./client.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/mafintosh/hyperssh.git\"\n  },\n  \"author\": \"Mathias Buus (@mafintosh)\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/mafintosh/hyperssh/issues\"\n  },\n  \"homepage\": \"https://github.com/mafintosh/hyperssh\"\n}\n"
  }
]