Closed TheDiscordian closed 1 week ago
Forgot to add, here's a minimal test for js-ipfs
that returns the following error: Uncaught (in promise) AggregateError: No Promise in Promise.any was resolved
HTML:
<!DOCTYPE html>
<html lang="en">
<head><title>js-ipfs minimal relay test</title>
<script src="https://cdn.jsdelivr.net/npm/ipfs-core@0.15.2/dist/index.min.js"></script>
<script>
var ipfs;
async function main() {
ipfs = await window.IpfsCore.create();
await ipfs.swarm.connect("/dns6/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A");
}
main()
</script>
</head>
</html>
Why are you using a reverse proxy? The WebSocket transport now supports WSS.
@marten-seemann can you link me to docs for how to point it to my cert please? ❤️ I wasn't aware that I could ditch the reverse proxy now.
Here's the option: https://github.com/libp2p/go-libp2p/blob/707100a521dace4a7a87fd17c04042ea483380b5/p2p/transport/websocket/websocket.go#L56-L62
In code, this would look something like:
libp2p.New(
libp2p.Transport(ws.New, ws.WithTLSConfig(tlsConf)),
....
)
@TheDiscordian you will not be able to connect to a WSS node from go-ipfs without doing a bunch of work (meaning custom builds with custom TLS verification) because go-libp2p could not dial WSS addresses authenticated by DNS addresses until we merged https://github.com/libp2p/go-libp2p/pull/1592 which was recent and therefore not yet released.
I ran vole.exe bitswap check bafkqaaa /dns/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
(using
https://github.com/aschmahmann/vole/pull/18) and got a connection just fine. There's a protocol not supported
error but that's just because it doesn't speak Bitswap which is... correct for the relay 😄.
Without the PR above vole instead fails with the message below because of the WSS issue that was recently resolved:
* [/ip4/172.105.8.48/tcp/4430/wss] x509: cannot validate certificate for 172.105.8.48 because it doesn't contain any IP SANs
@marten-seemann Thanks! I'll work on ditching the reverse proxy today, and see if that narrows anything down (it'll be nice to axe Nginx)
@aschmahmann Ah thanks! This explains why go-ipfs failed, but not js-ipfs 🤔. Will try again with Marten's tip... (Edit: Or does the relay need bitswap for js-ipfs to be happy?)
I followed @marten-seemann's advice, you can see the code here: https://github.com/TheDiscordian/go-libp2p-relay-daemon/blob/master/cmd/libp2p-relay-daemon/main.go#L82
js-ipfs now returns a very unexpected error: Uncaught (in promise) Error: no protocol with name: "'dns'". Must have a valid family name: "{ip4, ip6, dns4, dns6}".
To confirm I'm trying the exact same thing: await ipfs.swarm.connect("/dns6/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A");
/dns4/
returns the same error.
I also tested with websocat, and it seems to be happy (exact same result as previous).
Is this a bug with js-ipfs?
Edit: For completeness, here's my config.json:
{
"RelayV2": {
"Enabled": false
},
"RelayV1": {
"Enabled": true
},
"TLS": {
"KeyPairPaths": [["/etc/letsencrypt/live/ipfs.thedisco.zone/fullchain.pem", "/etc/letsencrypt/live/ipfs.thedisco.zone/privkey.pem"]]
},
"Network": {
"ListenAddrs": [
"/ip4/0.0.0.0/tcp/4011/ws",
"/ip6/::/tcp/4011/ws",
"/ip4/0.0.0.0/tcp/4430/wss",
"/ip6/::/tcp/4430/wss"
],
"AnnounceAddrs": [
"/dns6/ipfs.thedisco.zone/tcp/4430/wss",
"/dns4/ipfs.thedisco.zone/tcp/4430/wss"
]
},
"Daemon": {
"PprofPort": -1
}
}
js-ipfs now returns a very unexpected error: Uncaught (in promise) Error: no protocol with name: "'dns'". Must have a valid family name: "{ip4, ip6, dns4, dns6}".
Looks like JS expects an IP address, not a domain name. The domain name is needed though to allow the browser to verify the certificate. @achingbrain, this seems like bug in js-libp2p, doesn't it?
Related /dns/
issues:
@TheDiscordian given that Kubo 0.14 has the updated go-libp2p already, one should be able to connect to relay via /dns
just fine:
$ ipfs swarm connect /dns/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
connect 12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A success
Can you confirm things work on your end, and if so, close this issue?
@TheDiscordian after JS part is shipped in JS-IPFS (https://github.com/ipfs/js-ipfs/pull/4178), please make sure you update to libp2p-relay-daemon v0.2.0 before you re-test things end-to-end. This way, we also confirm the latest go-libp2p works fine :crossed_fingers:
/dns/.../wss
from js-ipfs and Kubo (tbd if this should live in their respective repos, or in https://github.com/ipfs/interop)@lidel @achingbrain this appears to be unresolved for js-ipfs, any theories?
Repo used: https://github.com/TheDiscordian/go-libp2p-relay-daemon
Code:
<!DOCTYPE html>
<html lang="en">
<head><title>js-ipfs minimal relay test</title>
<script src="https://cdn.jsdelivr.net/npm/ipfs-core@0.16.1/dist/index.min.js"></script>
<script>
var ipfs;
async function main() {
ipfs = await window.IpfsCore.create();
await ipfs.swarm.connect("/dns6/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A");
}
main()
</script>
</head>
</html>
I can confirm this works fine /w Kubo. Error is the same as before /w js-ipfs, Chrome:
Firefox:
I can confirm this works fine /w Kubo. Error is the same as before /w js-ipfs, Chrome:
So both Kubo and js-ipfs daemons are able to connect to /dns6/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
But js-ipfs in the browser fails to connect?
@2color I haven't actually tested the js-ipfs daemon, only the browser. However yes, Kubo definitely works fine, I can connect and see the node in my list of peers.
jsipfs daemon fails too:
$ ipfs swarm connect /dns/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
connect 12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A success
$ jsipfs swarm connect /dns/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
(node:16151) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
fetch failed
@achingbrain I wonder if JS side of things needs to implement the /sni/
fix from https://github.com/libp2p/go-libp2p/pull/1719 ?
@achingbrain I wonder if JS side of things needs to implement the /sni/ fix from https://github.com/libp2p/go-libp2p/pull/1719 ?
It's only used internally, although one could announce addresses containing /sni
.
kubo fails to contact a websocket server behind a reverse proxy, should it be a ws or wss. From my understanding, it comes from the following part in go-libp2p
// 1. initial addr is /dns/example.com/tcp/443/ws
resolvedAddrs, err := resolver.Resolve(ctx, a)
// 2. resolvedAddrs is /dns/example.com/tcp/443/ws
...
resolved, err := s.resolveAddrs(ctx, peer.AddrInfo{...})
// 3. resolved is /ip4/1.2.3.4/tcp/443/ws
// the information about the DNS host is lost, preventing a reverse proxy from directing the HTTP connection to the right host
The above is similar, but recoverable (not recovered) with wss. WSS adds /tls/sni/example.com/ws
, which could be used by the websocket transport when dialing the resolved IP.
I think the multiaddr resolution is the component at fault here. /dns/example.com/tcp/443/ws
is not equivalent to /ip4/1.2.3.4/tcp/443/ws
. The IP is correct, but it's missing the domain name. websocket transport dial would be able to use an IP resolved by the Swarm resolver, but doesn't know the domain name to pass to the reverse proxy.
To address the issue (in go-libp2p), we could consider the following:
sni
component in the multiaddr resolved by websocket transport, even for non wss connection. Then, use this multiaddr component as the host for the connection, while NetDial dials the IP resolved by swarmdnsname
component in the swarm resolved multiaddr. This would be a new multiaddr component. This dnsname should be ignored by other transports, but could be leveraged should they need to use the domain name.I would be glad to contribute to an implementation. This caused issue on a server of mine, which cannot swarm connect with vanilla kubo. The fix I have is to use the sni component as Host (here), but this bypasses Swarm resolution.
- [ ] After we confirm this is fixed, we need to add smoke/regression test that dialls
/dns/.../wss
from js-ipfs and Kubo (tbd if this should live in their respective repos, or in https://github.com/ipfs/interop)
@lidel : I wish I knew the answer myself, but would you please be able to outline what tests are needed where so we don't regress on this in the future? I am then game to engage with the teams to make sure we harder ourselves here. Thanks.
go-libp2p v0.23.3 has been released https://github.com/libp2p/go-libp2p/releases/tag/v0.23.3 which incorporates @thibmeu 's fix for the missing HTTP Host header in /wss
Commit: a32147234644cfef5b42a9f5ccaf99b6e6021fd4
Issue:
Both js-ipfs and go-ipfs refuse to connect to this relay node over wss, works fine over ws.
What was tried:
Both go-ipfs and js-ipfs were tried, or simply:
ipfs swarm connect /dns/ipfs.thedisco.zone/tcp/4430/wss/p2p/12D3KooWCyiHXACQpZxnvLTHXjFcFPPv69qPrX6svgdcmREZuS8A
:Kubo 0.12 fails to connect:
To debug @lidel tried
websocat
:But it indicates it should be working correctly. We also tried regular websockets, and those work fine. The reverse proxy server in use is Nginx.
Just in case, I tried to also update the cert, but this didn't change anything. It's worth noting that this is the exact same setup I was using with go-ipfs for relaying, and it was working fine. Config files provided below.
Configs:
config.json:
/etc/nginx/sites-enabled/ipfs: