This repository has been archived by the owner on Mar 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5eed64e
commit 7171f76
Showing
5 changed files
with
381 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,115 @@ | ||
# js-libp2p-hop-relay-server | ||
A out of the box libp2p relay server with HOP | ||
# js-libp2p-hop-relay-server <!-- omit in toc --> | ||
|
||
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai) | ||
[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) | ||
[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) | ||
[![](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) | ||
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-hop-relay-server/ci?label=ci&style=flat-square)](https://github.com/libp2p/js-libp2p-hop-relay-server/actions?query=branch%3Amaster+workflow%3Aci+) | ||
|
||
> An out of the box libp2p relay server with HOP | ||
## Lead Maintainer <!-- omit in toc --> | ||
|
||
[Vasco Santos](https://github.com/vasco-santos) | ||
|
||
## Table of Contents<!-- omit in toc --> | ||
|
||
- [Background](#background) | ||
- [Usage](#usage) | ||
- [Install](#install) | ||
- [CLI](#cli) | ||
- [Docker](#docker) | ||
- [Contribute](#contribute) | ||
- [License](#license) | ||
|
||
## Background | ||
|
||
Libp2p nodes acting as circuit relay aim to establish connectivity between libp2p nodes (e.g. IPFS nodes) that wouldn't otherwise be able to establish a direct connection to each other. | ||
|
||
A relay is needed in situations where nodes are behind NAT, reverse proxies, firewalls and/or simply don't support the same transports (e.g. go-libp2p vs. browser-libp2p). The circuit relay protocol exists to overcome those scenarios. Nodes with the `auto-relay` feature enabled can automatically bind themselves on a relay to listen for connections on their behalf. | ||
|
||
You can read more in its [SPEC](https://github.com/libp2p/specs/tree/master/relay). | ||
|
||
## Usage | ||
|
||
### Install | ||
|
||
```bash | ||
> npm install --global libp2p-hop-relay-server | ||
``` | ||
|
||
Now you can use the cli command `libp2p-hop-relay-server` to spawn an out of the box libp2p hop relay server. | ||
|
||
### CLI | ||
|
||
After installing the relay server, you can use its binary. It accepts several arguments: `--peerId`, `--listenMultiaddrs`, `--announceMultiaddrs`, `--metricsMultiaddr`, `--disableMetrics`, `--delegateMultiaddr` and `--disableAdvertise`. | ||
|
||
```sh | ||
libp2p-hop-relay-server [--peerId <jsonFilePath>] [--listenMultiaddrs <ma> ... <ma>] [--announceMultiaddrs <ma> ... <ma>] [--metricsMultiaddr <ma>] [--disableMetrics] [--delegateMultiaddr <ma>] [--disableAdvertise] | ||
``` | ||
|
||
#### PeerId | ||
|
||
You can create a [PeerId](https://github.com/libp2p/js-peer-id) via its [CLI](https://github.com/libp2p/js-peer-id#cli). | ||
|
||
```sh | ||
libp2p-hop-relay-server --peerId id.json | ||
``` | ||
|
||
#### Multiaddrs | ||
|
||
You can specify the libp2p rendezvous server listen and announce multiaddrs. This server is configured with [libp2p-tcp](https://github.com/libp2p/js-libp2p-tcp) and [libp2p-websockets](https://github.com/libp2p/js-libp2p-websockets) and addresses with this transports should be used. It can always be modified via the API. | ||
|
||
```sh | ||
libp2p-hop-relay-server --peerId id.json --listenMultiaddrs '/ip4/127.0.0.1/tcp/15002/ws' '/ip4/127.0.0.1/tcp/8000' --announceMultiaddrs '/dns4/test.io/tcp/443/wss/p2p/12D3KooWAuEpJKhCAfNcHycKcZCv9Qy69utLAJ3MobjKpsoKbrGA' '/dns6/test.io/tcp/443/wss/p2p/12D3KooWAuEpJKhCAfNcHycKcZCv9Qy69utLAJ3MobjKpsoKbrGA' | ||
``` | ||
|
||
By default it listens on `/ip4/127.0.0.1/tcp/15002/ws` and has no announce multiaddrs specified. | ||
|
||
#### Metrics | ||
|
||
Metrics are enabled by default on `/ip4/127.0.0.1/tcp/8003` via Prometheus. This address can also be modified with: | ||
|
||
```sh | ||
libp2p-hop-relay-server --metricsMultiaddr '/ip4/127.0.0.1/tcp/8000' | ||
``` | ||
|
||
Moreover, metrics can also be disabled with: | ||
|
||
```sh | ||
libp2p-hop-relay-server --disableMetrics | ||
``` | ||
|
||
#### Advertise | ||
|
||
The relay server will advertise its HOP capability by default, using a delegate node on `/dns4/node0.delegate.ipfs.io/tcp/443/https`. This is important for peers that will try to find HOP relays on the network to bind themselves. | ||
|
||
This advertise can be disabled with: | ||
|
||
```sh | ||
libp2p-hop-relay-server --disableAdvertise | ||
``` | ||
|
||
You can also customize the delegate node to use with: | ||
|
||
```sh | ||
libp2p-hop-relay-server --delegateMultiaddr '/dns4/node1.delegate.ipfs.io/tcp/443/https' | ||
``` | ||
|
||
Note: In the future this will leverage libp2p's [DHT](https://github.com/libp2p/js-libp2p-kad-dht). | ||
|
||
### Docker | ||
|
||
TODO | ||
|
||
## Contribute | ||
|
||
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-hop-relay-server/issues)! | ||
|
||
This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). | ||
|
||
[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) | ||
|
||
## License | ||
|
||
MIT - Protocol Labs 2020 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#!/usr/bin/env node | ||
|
||
'use strict' | ||
|
||
// Usage: $0 [--peerId <jsonFilePath>] [--listenMultiaddrs <ma> ... <ma>] [--announceMultiaddrs <ma> ... <ma>] | ||
// [--metricsMultiaddr <ma>] [--disableMetrics] [--delegateMultiaddr <ma>] [--disableAdvertise] | ||
|
||
/* eslint-disable no-console */ | ||
|
||
const debug = require('debug') | ||
const log = debug('libp2p:hop-relay:bin') | ||
|
||
const fs = require('fs') | ||
const http = require('http') | ||
const menoetius = require('menoetius') | ||
const argv = require('minimist')(process.argv.slice(2)) | ||
|
||
const multiaddr = require('multiaddr') | ||
const PeerId = require('peer-id') | ||
|
||
const { getAnnounceAddresses, getListenAddresses } = require('./utils') | ||
const createRelay = require('./index') | ||
|
||
async function main () { | ||
// Metrics | ||
let metricsServer | ||
const metrics = !(argv.disableMetrics) | ||
const metricsMa = multiaddr(argv.metricsMultiaddr || argv.ma || '/ip4/127.0.0.1/tcp/8003') | ||
const metricsAddr = metricsMa.nodeAddress() | ||
|
||
// multiaddrs | ||
const listenAddresses = getListenAddresses(argv) | ||
const announceAddresses = getAnnounceAddresses(argv) | ||
|
||
// Should advertise | ||
const shouldAdvertise = !(argv.disableAdvertise) | ||
|
||
// Delegate | ||
let delegateOptions | ||
if (argv.delegateMultiaddr || argv.dm) { | ||
const delegateAddr = multiaddr(argv.delegateMultiaddr || argv.dm).toOptions() | ||
delegateOptions = { | ||
host: delegateAddr.host, | ||
protocol: delegateAddr.port === '443' ? 'https' : 'http', | ||
port: delegateAddr.port | ||
} | ||
} | ||
|
||
// PeerId | ||
let peerId | ||
if (argv.peerId) { | ||
const peerData = fs.readFileSync(argv.peerId) | ||
peerId = await PeerId.createFromJSON(JSON.parse(peerData)) | ||
} else { | ||
peerId = await PeerId.create() | ||
log('You are using an automatically generated peer.') | ||
log('If you want to keep the same address for the server you should provide a peerId with --peerId <jsonFilePath>') | ||
} | ||
|
||
// Create Relay | ||
const relay = await createRelay({ | ||
peerId, | ||
listenAddresses, | ||
announceAddresses, | ||
shouldAdvertise, | ||
delegateOptions | ||
}) | ||
|
||
relay.peerStore.on('change:multiaddrs', ({ peerId: changedPeerId, multiaddrs }) => { | ||
if (peerId.equals(changedPeerId)) { | ||
console.log('Relay server listening on:') | ||
multiaddrs.forEach((m) => console.log(m)) | ||
} | ||
}) | ||
|
||
await relay.start() | ||
|
||
if (metrics) { | ||
log('enabling metrics') | ||
metricsServer = http.createServer((req, res) => { | ||
if (req.url !== '/metrics') { | ||
res.statusCode = 200 | ||
res.end() | ||
} | ||
}) | ||
|
||
menoetius.instrument(metricsServer) | ||
|
||
metricsServer.listen(metricsAddr.port, metricsAddr.address, () => { | ||
console.log(`metrics server listening on ${metricsAddr.port}`) | ||
}) | ||
} | ||
|
||
const stop = async () => { | ||
console.log('Stopping...') | ||
await relay.stop() | ||
metricsServer && await metricsServer.close() | ||
process.exit(0) | ||
} | ||
|
||
process.on('SIGTERM', stop) | ||
process.on('SIGINT', stop) | ||
} | ||
|
||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
'use strict' | ||
|
||
const Libp2p = require('libp2p') | ||
const TCP = require('libp2p-tcp') | ||
const Websockets = require('libp2p-websockets') | ||
const Muxer = require('libp2p-mplex') | ||
const { NOISE: Crypto } = require('libp2p-noise') | ||
const DelegatedContentRouting = require('libp2p-delegated-content-routing') | ||
const ipfsHttpClient = require('ipfs-http-client') | ||
|
||
/** | ||
* @typedef {import('peer-id')} PeerId | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} DelegateOptions | ||
* @property {string} host | ||
* @property {string} protocol | ||
* @property {number} port | ||
*/ | ||
|
||
const defaulDelegateOptions = { | ||
host: 'node0.delegate.ipfs.io', | ||
protocol: 'https', | ||
port: 443 | ||
} | ||
|
||
/** | ||
* @typedef {Object} HopRelayOptions | ||
* @property {PeerId} peerId | ||
* @property {DelegateOptions} [delegateOptions = defaulDelegateOptions] | ||
* @property {string[]} [listenAddresses = []] | ||
* @property {string[]} [announceAddresses = []] | ||
* @property {boolean} [shouldAdvertise = true] | ||
*/ | ||
|
||
/** | ||
* Create a Libp2p Relay with HOP service | ||
* | ||
* @param {HopRelayOptions} options | ||
* @returns {Promise<Libp2p>} | ||
*/ | ||
function create ({ peerId, delegateOptions = defaulDelegateOptions, listenAddresses = [], announceAddresses = [], shouldAdvertise = true }) { | ||
let contentRouting = [] | ||
|
||
if (shouldAdvertise) { | ||
const httpClient = ipfsHttpClient(delegateOptions) | ||
contentRouting.push(new DelegatedContentRouting(peerId, httpClient)) | ||
} | ||
|
||
return Libp2p.create({ | ||
peerId, | ||
modules: { | ||
transport: [Websockets, TCP], | ||
streamMuxer: [Muxer], | ||
connEncryption: [Crypto], | ||
contentRouting | ||
}, | ||
peerId, | ||
addresses: { | ||
listen: listenAddresses, | ||
announce: announceAddresses | ||
}, | ||
config: { | ||
relay: { | ||
enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay. | ||
hop: { | ||
enabled: true, // Allows you to be a relay for other peers | ||
active: true // You will attempt to dial destination peers if you are not connected to them | ||
}, | ||
advertise: { | ||
enabled: shouldAdvertise // Allows you to advertise the Hop service | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
|
||
module.exports = create |
Oops, something went wrong.