Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to establish an outbound relay connection #2897

Open
PradaJoaquin opened this issue Dec 16, 2024 · 5 comments
Open

Unable to establish an outbound relay connection #2897

PradaJoaquin opened this issue Dec 16, 2024 · 5 comments
Labels
need/triage Needs initial labeling and prioritization

Comments

@PradaJoaquin
Copy link

PradaJoaquin commented Dec 16, 2024

  • Version:
    libp2p 2.4.2
    circuit-relay-v2 3.1.6

  • Platform:
    Linux & Windows 64-bit

Severity:

Medium

Description:

I am unable to establish an outbound relay connection. Whenever the listener peer receives a new relayed connection, it fails due to the following error:
MuxerClosedError: Muxer closed locally

Below is the log output from the listener peer while testing different transports from the dialer.

Log Output:

2024-12-16T21:54:32.007Z libp2p:connection:outbound:cxrt101734386051371 incoming stream opened on /libp2p/circuit/relay/0.2.0/stop
2024-12-16T21:54:32.009Z libp2p:circuit-relay:transport new circuit relay v2 stop stream from QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ with type CONNECT
2024-12-16T21:54:32.013Z libp2p:circuit-relay:transport new inbound relayed connection /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ/p2p-circuit/p2p/12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K
2024-12-16T21:54:32.266Z libp2p:stream:converter handle: responded with "na" for "/tls/1.0.0"
2024-12-16T21:54:32.535Z libp2p:stream:converter encrypting inbound connection to /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ/p2p-circuit/p2p/12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K using /noise
2024-12-16T21:54:33.058Z libp2p:stream:converter inbound handling muxers [ '/yamux/1.0.0' ]
2024-12-16T21:54:33.058Z libp2p:stream:converter successfully upgraded inbound connection
2024-12-16T21:54:33.059Z libp2p:connection-manager:connection-pruner checking max connections limit 2/300
2024-12-16T21:54:33.059Z libp2p:circuit-relay:transport inbound connection /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ/p2p-circuit/p2p/12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K upgraded
2024-12-16T21:54:33.326Z libp2p:connection:inbound:bwkyd91734386073058 incoming stream opened on /ipfs/id/1.0.0
2024-12-16T21:54:33.334Z libp2p:address-manager:observed-addresses adding observed address /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ/p2p-circuit
2024-12-16T21:54:33.334Z libp2p:identify identify completed for peer 12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K and protocols [ '/ipfs/id/1.0.0', '/ipfs/id/push/1.0.0', '/ipfs/ping/1.0.0', '/libp2p/circuit/relay/0.2.0/stop', '/libp2p/dcutr' ]
2024-12-16T21:54:33.334Z libp2p:identify received identify from 12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K
2024-12-16T21:55:29.947Z libp2p:yamux:error internal error in sink StreamResetError: stream reset
    at YamuxStream.reset (<example_path>/node_modules/@libp2p/utils/dist/src/abstract-stream.js:266:21)
    at YamuxStream.processFlags (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/stream.js:203:18)
    at YamuxStream.handleWindowUpdate (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/stream.js:167:14)
    at YamuxMuxer.handleStreamMessage (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:432:24)
    at YamuxMuxer.handleFrame (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:365:36)
    at YamuxMuxer.sink (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:99:36)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 0)
2024-12-16T21:55:29.948Z libp2p:yamux:error muxer abort reason=2 error=StreamResetError: stream reset
    at YamuxStream.reset (<example_path>/node_modules/@libp2p/utils/dist/src/abstract-stream.js:266:21)
    at YamuxStream.processFlags (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/stream.js:203:18)
    at YamuxStream.handleWindowUpdate (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/stream.js:167:14)
    at YamuxMuxer.handleStreamMessage (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:432:24)
    at YamuxMuxer.handleFrame (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:365:36)
    at YamuxMuxer.sink (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:99:36)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 0)
2024-12-16T21:55:29.948Z libp2p:yamux sending GoAway reason=InternalError
2024-12-16T21:55:30.620Z libp2p:connection-monitor:error error during heartbeat MuxerClosedError: Muxer closed locally
    at YamuxMuxer.newStream (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:148:19)
    at ConnectionImpl.newStream [as _newStream] (<example_path>/node_modules/libp2p/dist/src/upgrader.js:313:49)
    at ConnectionImpl.newStream (<example_path>/node_modules/libp2p/dist/src/connection/index.js:94:35)
    at <example_path>/node_modules/libp2p/dist/src/connection-monitor.js:47:51
2024-12-16T21:55:30.620Z libp2p:connection-monitor:error aborting connection due to ping failure
2024-12-16T21:55:30.620Z libp2p:connection:inbound:bwkyd91734386073058:error aborting connection to /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ/p2p-circuit/p2p/12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K due to error MuxerClosedError: Muxer closed locally
    at YamuxMuxer.newStream (<example_path>/node_modules/@chainsafe/libp2p-yamux/dist/src/muxer.js:148:19)
    at ConnectionImpl.newStream [as _newStream] (<example_path>/node_modules/libp2p/dist/src/upgrader.js:313:49)
    at ConnectionImpl.newStream (<example_path>/node_modules/libp2p/dist/src/connection/index.js:94:35)
    at <example_path>/node_modules/libp2p/dist/src/connection-monitor.js:47:51
2024-12-16T21:55:30.620Z libp2p:connection-manager onDisconnect remove all connections for peer 12D3KooWGnHVGC8umZ9aVtieaSktY6goe3DXRKrWNSJzztF7r54K

Steps to reproduce the error:

  1. Configure a listener peer with libp2p and enable circuit relay v2.

    • I modified the example-circuit-relay to dial to a public relay. Below i leave the code.
    • The public relay was discovered using the DHT.
  2. Dial the listener peer via the relay using a separate libp2p instance.

    • I attempted to connect to the listener peer using check.ipfs.network by providing the listener's multiaddress.

Expected Behavior:
The listener peer should successfully accept the relayed connection, and the connection should remain stable for further communication.

Actual Behavior:
The listener peer fails to maintain the connection, encountering the error, on the debug logs, MuxerClosedError: Muxer closed locally.

Question:

  • Is this an error or misconfiguration on my end?

Thank you for your assistance!

listener:

import { noise } from "@chainsafe/libp2p-noise";
import { yamux } from "@chainsafe/libp2p-yamux";
import { circuitRelayTransport } from "@libp2p/circuit-relay-v2";
import { identify } from "@libp2p/identify";
import { webSockets } from "@libp2p/websockets";
import { multiaddr } from "@multiformats/multiaddr";
import { createLibp2p } from "libp2p";
import { webRTC, webRTCDirect } from "@libp2p/webrtc";
import { webTransport } from "@libp2p/webtransport";
import { tcp } from "@libp2p/tcp";
import * as filters from "@libp2p/websockets/filters";
import { dcutr } from "@libp2p/dcutr";

const relayAddr = multiaddr(
  "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ"
);
if (!relayAddr) {
  throw new Error("the relay address needs to be specified as a parameter");
}

const node = await createLibp2p({
  addresses: {
    listen: ["/ip4/0.0.0.0/tcp/4001", "/p2p-circuit", "/webrtc"],
  },
  transports: [
    circuitRelayTransport(),
    tcp(),
    webRTC(),
    webRTCDirect(),
    webTransport(),
    webSockets({
      filter: filters.all,
    }),
  ],
  connectionEncrypters: [noise()],
  streamMuxers: [yamux()],
  services: {
    identify: identify(),
  },
  dcutr: dcutr(),
});

console.log(`Node started with id ${node.peerId.toString()}`);

const conn = await node.dial(relayAddr);

console.log(`Connected to the relay ${conn.remotePeer.toString()}`);

// Wait for connection and relay to be bind for the example purpose
node.addEventListener("self:peer:update", (evt) => {
  // Updated self multiaddrs?
  console.log("Advertising with a relay addresses:");
  let multiaddrs = node.getMultiaddrs();
  for (const ma of multiaddrs) {
    if (ma.toString().includes("p2p-circuit")) {
      console.log(`${ma}`);
    }
  }
});

package.json

{
  "name": "example",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "vite": "^6.0.3"
  },
  "dependencies": {
    "@chainsafe/libp2p-gossipsub": "^14.1.0",
    "@chainsafe/libp2p-noise": "^16.0.0",
    "@chainsafe/libp2p-yamux": "^7.0.1",
    "@helia/delegated-routing-v1-http-api-client": "^4.2.1",
    "@libp2p/autonat": "^2.0.15",
    "@libp2p/bootstrap": "^11.0.16",
    "@libp2p/circuit-relay-v2": "^3.1.6",
    "@libp2p/dcutr": "^2.0.14",
    "@libp2p/identify": "^3.0.14",
    "@libp2p/kad-dht": "^14.1.6",
    "@libp2p/ping": "^2.0.14",
    "@libp2p/pubsub-peer-discovery": "^11.0.1",
    "@libp2p/tcp": "^10.0.14",
    "@libp2p/upnp-nat": "^3.0.3",
    "@libp2p/webrtc": "^5.0.22",
    "@libp2p/websockets": "^9.1.0",
    "@libp2p/webtransport": "^5.0.21",
    "@orbitdb/core": "^2.4.3",
    "blockstore-fs": "^2.0.2",
    "datastore-fs": "^10.0.2",
    "helia": "^5.1.1"
  }
}
@PradaJoaquin PradaJoaquin added the need/triage Needs initial labeling and prioritization label Dec 16, 2024
@PradaJoaquin PradaJoaquin changed the title Unable to dial using public relay Unable to establish an outbound relay connection Jan 16, 2025
@PradaJoaquin PradaJoaquin reopened this Jan 16, 2025
@silkroadnomad
Copy link

@PradaJoaquin what was the reason for this issue. I have it too! Can you help?

@PradaJoaquin
Copy link
Author

Hey @silkroadnomad, unfortunately, I wasn’t able to resolve the issue.

The issue occurred because I was trying to connect from a browser peer to a non-local Node.js peer. Currently, the only supported transport I found for this scenario is WebRTC, which requires a third node to act as a relay. However, I couldn't get the browser peer to connect in any way, except when using unsecured WebSockets, which only worked in a local environment.

Initially, I closed the issue, assuming it was a problem on my end since no one else seemed to be experiencing it. I’ll leave it open now to see if anyone can help.

I’m currently waiting for support for WebRTC-Direct, which might help resolve this specific problem.

Any insights or suggestions would be greatly appreciated!

@PradaJoaquin PradaJoaquin reopened this Jan 29, 2025
@silkroadnomad
Copy link

silkroadnomad commented Jan 29, 2025

@PradaJoaquin , you have the same tech stack as me. I am also using orbitdb, helia, and I do browser code only. And Svelte, which uses vite too. There is no server code on my site, but I need to switch off the ssr and do some other little tweaks.

I could resolve my issue by simply upgrading all packages to the latest versions. As far as I remember. But it took the whole day. My browser connects with the relay. I am using PubSubPeerDiscovery, which is used to connect the browser directly with esch other directly via circuit-relay and dcutr via WebRTC peer-to-peer.

There's another bug in the latest versions here which somehow prevented to deliver Multiaddresses to the other browser! So no connects! #2883

But your browser should definitely connect with your relay without waiting for WebRTC-direct.

There's a simple chat example I tried today it works too.
If you have a public websocket relay it needs a certificate for wss! There are two possibilities today how to achieve this. Have a look on the AutoSSL example. Or create a docker with certbot and ngnix. I have this example here somewhere in case you need it.

Check out the universal connectivity example, which has a rust and a go relay as alternativ, which are easy to start. The js-frontend unfortunately has a bug at the moment, too, but this seemed to work like a sharm in an older version.

I am tomorrow trying to find the older libp2p version where PubSubPeerDiscovery worked. Let's see.

@PradaJoaquin
Copy link
Author

PradaJoaquin commented Jan 29, 2025

Hey @silkroadnomad, glad to hear you resolved the issue! I already tried upgrading all packages to the latest versions but had no luck.

My browser peers can successfully connect to a relay without any issues. In my case, I have Node.js peers that discover public relays via the DHT, connect to them, and announce their WebRTC addresses. However, the issue arises when I try to connect from the browser to a Node.js peer using its relayed WebRTC address.

That's why I think WebRTC-Direct or WebTransport could help with this, similar to how the browser is already directly connecting to Go and Rust peers. Until then, I’ve stopped trying with WebRTC and recently started looking for alternatives—like you suggested, AutoSSL—as a potential way to establish browser-to-Node.js connections. However, I couldn't get the example to work. It never prints the multiaddr(s) that include the Server Name Indication (SNI), though I still need to do more testing.

Unfortunately, the universal connectivity example does not include a Node.js peer—only a browser peer—so I couldn't use it to test my specific case.

I’d love to check out the example you mentioned!

@silkroadnomad
Copy link

silkroadnomad commented Jan 30, 2025

@PradaJoaquin checkout release v0.2(!) of this websocket relay with nginx and letsencrypt. It is libp2p 1.3.0 from 10 months ago.

Follow the instructions which work on a public hosted IP with configured domain name. (Don't use higher version, it is highly experimental and a bit out of your described scope)

https://github.com/silkroadnomad/libp2p-relay/tree/v0.2/

I call all NodeJS libp2p nodes relay, I know its not always correct, but in my case, I run them always in the public internet to play relay for browser peers.

Take care, that the syntax of libp2p config at the time was different, which still leads to some confusion on my end from time to time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need/triage Needs initial labeling and prioritization
Projects
None yet
Development

No branches or pull requests

2 participants