{"id":28396308,"url":"https://github.com/ssbc/ssb-tunnel","last_synced_at":"2025-10-10T08:38:44.153Z","repository":{"id":54816102,"uuid":"130752749","full_name":"ssbc/ssb-tunnel","owner":"ssbc","description":"create a p2p link tunneled through a pub server","archived":false,"fork":false,"pushed_at":"2021-10-26T19:07:49.000Z","size":497,"stargazers_count":23,"open_issues_count":2,"forks_count":5,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-09-29T12:51:29.853Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ssbc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-23T20:27:29.000Z","updated_at":"2024-09-24T00:13:32.000Z","dependencies_parsed_at":"2022-08-14T03:40:41.363Z","dependency_job_id":null,"html_url":"https://github.com/ssbc/ssb-tunnel","commit_stats":null,"previous_names":["dominictarr/ssb-tunnel"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/ssbc/ssb-tunnel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-tunnel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-tunnel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-tunnel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-tunnel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ssbc","download_url":"https://codeload.github.com/ssbc/ssb-tunnel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-tunnel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003276,"owners_count":26083555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-31T21:37:53.030Z","updated_at":"2025-10-10T08:38:44.138Z","avatar_url":"https://github.com/ssbc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## ssb-tunnel\n\nIndirectly connect to a peer by tunneling through another\nconnection. If A is connected to B, and C is connected to B,\nthis allows C to connect to A by using B as a proxy or \"portal\".\n\nWith this module, a peer `A` with an unstable IP address can\nmake a long term connection to a portal `B`, another peer `C` can then connect\nto that portal, and tunnel back up the client connection `C-\u003eB`,\ngiving us a connect _through_ `B`, `C-(B)-\u003eA`.\n\n```\n,---,      ,---,     ,---,\n|   |-----\u003e|   |\u003c----|   |\n| A |\u003c=====|-B-|\u003c====| C |\n|   |-----\u003e|   |\u003c----|   |\n`---`      `---`     `---`\n```\nA connects to B, and waits to receive tunnel connections.\nC connects to B, and then requests a tunnel through that\nconnection (B-C) to A. B calls A, creating an incoming tunnel,\nand attaches one end to C's request, C then uses the standard\nhandshake to authenticate A.\n\nNotice that for the tunnel, A is the server and C is the client\n(client calls, server answers) but B is just the portal.\nThe tunnel is _inside_ the outer connections,\nwhich means it is encrypted twice. This means A and C can mutually\nauthenticate each other, and B cannot see the content of their connection.\n\nThe arrows represent the _direction_ of the connection - from the client,\npointing to the server. Notice the `B\u003c=C` tunnel is the same direction as the `B\u003c-C` container,\nbut the `A\u003c=B` tunnel is the opposite direction as the `A-\u003eB` container.\n\n# address\n\ntunnel addresses are multiserver style:\n\n`tunnel:\u003cportal_id\u003e:\u003ctarget_id\u003e:\u003cinstance\u003e?` for example:\n`tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw/hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK2ZabI/Re4bYF/Vh3hXasQ=.ed25519~shs:1b9KP8znF7A4i8wnSevBSK2ZabI/Re4bYF/Vh3hXasQ=`\n(instance is optional)\n\nIt is assumed that a peer who wishes to be a client to\n`target` already has a means to connect to `portal`.\nThe address of the portal is left out, so that the client\ncan use anything, and also, to better preserve the privacy\nof the portal.\n\nFor the protocol portion of the multiserver address,\n`tunnel:portal:target:instance`\nthis will include the `shs` portion for the portal.\n`instance` is just an integer that tells the server which\n`ssb-tunnel` instance the client wants to connect to if there are multiple.\n\n`target` is a ssb feed id, which represents the peer.\nThis tells the portal that C wants a connection to A.\n`portal` tells A how to connect to B. \n\n## config\n\nAssuming this plugin is already installed and enabled on your pub\nserver. You need to configure sbot with an incoming section so that it\ncan receive tunnel connections:\n\n```\nincoming: {\n  tunnel: [{scope: 'public', portal: \u003cpub_id\u003e, transform:'shs'}]\n}\n```\n\nthen, another peer will need to have the outgoing config:\n\n```\noutgoing: {\n  tunnel: [{transform:'shs'}]\n}\n```\n\nand have an address for `pub`, can do:\n`sbot.gossip.connect('tunnel:\u003cpub_id\u003e:\u003cyour_id\u003e~shs:your_key',\nfunction (err, rpc) {...})` and they'll have connection through `pub`\nto you!\n\n## privacy ideas\n\nInstead of revealing the id of the portal, just use the `hmac(portal_id, your_id)`\nso peers that do not know of the portal do not learn about it from your address.\nThat way only friends can connect to you.\n\n## how it works behind the scenes\n\nfor 3 peers, A, B, and C. A being the client-side server, which\nwill receive the tunnel connection, B being the portal, and C\nbeing the client who connects to A via B.\n\nFirst A connects to B normally, then calls `B.tunnel.announce()`\nThis informs B that A would like to receive connections tunneled\nthough B. (B puts A into a table of endpoints it can provide tunnels\nto)\n\nThen C connects to B, and then calls `B.tunnel.connect({id: A.id})`\nB then checks if it can provide a connection to A, which it can,\nand calls `endpoints[A.id].tunnel.connect({id: A})` returning this stream\nto B (B is now connected to A via C).\n\nB then initiates a [`secret-handshake`](https://github.com/auditdrivencrypto/secret-handshake) through the tunnel, hiding subsequent content from B.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssbc%2Fssb-tunnel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fssbc%2Fssb-tunnel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssbc%2Fssb-tunnel/lists"}