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

[Bug] Cross device Peers are not discoverable #215

Closed
vedhavyas opened this issue Dec 10, 2023 · 23 comments
Closed

[Bug] Cross device Peers are not discoverable #215

vedhavyas opened this issue Dec 10, 2023 · 23 comments
Labels
bug Something isn't working self-hosted WebRTC

Comments

@vedhavyas
Copy link

Describe the bug
I'm able to see each other peers between two macs but when I open it on mobile browser, mobile peer is not shown even though I can see peer connected through logs. Also, I'm able to pair the mac and android as well and it doesn't show up. I see the attached screenshot on android and on mac under peer list, android peer also shows undefined.

Expected behavior
I expected peer from android is showed up on macs and vice-verse

Screenshots
pairdrop_error

Smartphone (please complete the following information):

  • Device: Nothing Phone
  • OS: Android 13
  • Browser: Brave
  • Version: 1.61.100

Bug occurs on official PairDrop instance https://pairdrop.net/
No
Version: v1.9.4

Bug occurs on self-hosted PairDrop instance
Yes

Self-Hosted Setup
Proxy: Caddy
Deployment: docker-compose
Version: v1.9.4

Additional context
I have a vpn and all the services are under this vpn

@vedhavyas vedhavyas added the bug Something isn't working label Dec 10, 2023
@vedhavyas
Copy link
Author

Yes I did setup local turn server but same result. I can see the logs and connection seems to be established but not shown on the UI though

----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.3
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.3
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----
----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.3
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.3
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----
----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.22
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.22
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----

@vedhavyas
Copy link
Author

Visit this page with your device to check if WebRTC is supported:
webrtc-experiment.com/DetectRTC/#isWebRTCSupported

It does say Yep so it must be supporting

You can also try to use pairdrop.net with your VPNs enabled. If this breaks the functionality, probably your VPN is blocking WebRTC

It works on pairdrop.net but not my self hosted one

Any ideas how I can debug this ?

@vedhavyas
Copy link
Author

To make deploying a TURN server alongside PairDrop the docs will be updated in v1.10.0. This will be deployed later today but you can also find it here:

I have already deployed coturn alsong side the pairdrop. This is how my docker compose looks like

pairdrop:
    image: lscr.io/linuxserver/pairdrop:latest
    container_name: pairdrop
    hostname: pairdrop
    restart: unless-stopped
    environment:
      - PUID
      - PGID
      - TZ
      - WS_FALLBACK=true
      - DEBUG_MODE=true
      - RTC_CONFIG=/etc/pairdrop/rtc_config.json
    networks:
      - docker-direct
    volumes:
      - $CONF_DIR/rtc_config.json:/etc/pairdrop/rtc_config.json
    labels:
      caddy: pairdrop.hub
      caddy.tls: internal
      caddy.reverse_proxy: "{{upstreams 3000}}"

  turnserver:
    image: coturn/coturn:latest
    container_name: turnserver
    hostname: turnserver
    restart: unless-stopped
    user: $PUID:$PGID
    volumes:
      - $CONF_DIR/turnserver.conf:/etc/coturn/turnserver.conf
      - "${DATA_DIR}/turnserver/data/:/var/db/"
      - "${DATA_DIR}/turnserver/log:/var/log/"
      - "${DATA_DIR}/turnserver/run:/var/run/"
    networks:
      docker-direct:
        ipv4_address: 10.10.2.10
    expose:
      - "10000-20000"
    labels:
      caddy: turnserver.hub
      caddy.tls: internal
      caddy.reverse_proxy: "{{upstreams 3478}}"

Here are my configs for coturn and pairdrop respectively

# TURN server name and realm
realm=turnserver.hub
server-name=turnserver.hub

# Use fingerprint in TURN message
fingerprint

# IPs the TURN server listens to
listening-ip=0.0.0.0

# Main listening port
listening-port=3478

# Further ports that are open for communication
min-port=10000
max-port=20000

# Log file path
log-file=/var/log/turnserver.log

# Enable verbose logging
verbose

# sqlite
userdb=/var/db/turndb
{
  "sdpSemantics": "unified-plan",
  "iceServers": [
    {
      "urls": "turn:turnserver:3478"
    }
  ]
}

Also, have you tried using other browsers than Brave?

I will in different browsers and get back on this

@vedhavyas
Copy link
Author

Okay. I was able to test on chrome browser instead of Brave and it works.
It is also showing peer from the brave browser as well.

So i'm confused why everything works on pairdrop.net but not brave mobile does not work on my self hosted one

@schlagmichdoch
Copy link
Owner

Have you fixed your turnserver.conf?

@vedhavyas
Copy link
Author

Yeap. Updated my turnserver.conf to include static user and removed DB
Updated my rtc_config.json to include such credentials.

Funny thing is on brave browser and mac, both get notification that it got connected but it wont show in the peers

@schlagmichdoch
Copy link
Owner

So the issue only happens on Brave and only with your self hosted version behind a VPN, correct?

Is your TURN server publicly available? Then you could also test it with this tool: https://icetest.info/
After setting turn server and credentials you must click on "Add TURN" and then "Start Test". If your results include a relay candidate your TURN server is working correctly.

If your TURN server is behind the VPN too, maybe there is a way to run the icetest library on your device behind the VPN: https://github.com/tgabi333/ice-test

Funny thing is on brave browser and mac, both get notification that it got connected but it wont show in the peers

This is due to the signaling server working as expected but the WebRTC connection failing. As the (edited) deviceNames are transferred between the devices only without ever being sent to the server, the Edit Dialog shows "undefined" as long as there hasn't been a successful WebRTC connection.

Probably, we should prefill the IndexedDB with the generated device names though. I'll create a separate issue for that.

@vedhavyas
Copy link
Author

Ok, So I tested on icetest.info and it seems to be okay.
Here is the log from the UI

IceGatheringState: complete
host udp 8079c19b-942a-4955-be43-2a61c7aff97c.local:51603 N/A
srflx udp 10.10.1.3:51603 0.0.0.0:0
relay udp 213.133.103.207:11309 10.10.1.3:51603

@vedhavyas
Copy link
Author

Your self hosted instance works correctly using Google Chrome and pairdrop.net also works using Brave.

Yes that is correct.
Right now I tested with Chrome and brave on android. I can check on other browsers if you want to

When it is not shown on Brave is the Brave device shown on your Mac or does it fail on both devices then?

It fails on both devices. I have manually connected each one and both the sides it always show undefined for another

@vedhavyas
Copy link
Author

Also, try using this instance pairdrop-next.onrender.com to rule out Brave is somehow whitelisting pairdrop.net as it is quite popular but blocks something on other instances.

Works here as well

@schlagmichdoch
Copy link
Owner

I can check on other browsers if you want to

Sure, that's always a good idea.

Do you have any extensions installed on Brave?

@vedhavyas
Copy link
Author

vedhavyas commented Dec 13, 2023

I just tested on Firefox and opera and they both work fine.

I think i found the problem. It with the rtc_config.json

here is the original

{
  "sdpSemantics": "unified-plan",
  "iceServers": [
    {
      "urls": "turn:turnserver:3478",
      "username": "<>",
      "credential": "<>"
    }
  ]
}

here is the one that fixed the issue

{
  "sdpSemantics": "unified-plan",
  "iceServers": [
    {
      "urls": "turn:10.10.2.10:3478",
      "username": "<>",
      "credential": "<>"
    }
  ]
}

I was looking though the console and found some requests failing with stun:turnserver:3478 which is not accecible since that turnserver:3478 will only resolve within docker network. I made it a static IP and now both the devices are connected.
Stupid mistake on my part. and Thank you for helping me with this

@vedhavyas
Copy link
Author

This also brings another question
In the logs websocket was also failing for brave mobile and I guess fallback worked fine for the rest of the browsers

@schlagmichdoch
Copy link
Owner

Good catch! Glad it works now!

Beware that you can additionally implement TURN over TLS which would make the url turn:10.10.2.10:5349

In the logs websocket was also failing for brave mobile and I guess fallback worked fine for the rest of the browsers

I'm not sure what you question is. What fallback are you talking about? Are you maybe confusing Websockets and WebRTC?

@vedhavyas
Copy link
Author

I'm not sure what you question is. What fallback are you talking about? Are you maybe confusing Websockets and WebRTC?

I saw in the console logs once the turn connection failed, I think it tried websockets as I enabled WS_FALLBACK=true if you look at the docker compose file above. These websocket connections as well failed.

But this WS_FALLBACK might have worked in the other browsers ,say chrome etc... maybe ?

@vedhavyas
Copy link
Author

I'll close this as this is fixed. Thanks again for all the help and amazing work!

@schlagmichdoch
Copy link
Owner

I think it tried websockets as I enabled WS_FALLBACK=true if you look at the docker compose file above. These websocket connections as well failed.

Currently the websocket fallback is implemented in such a way that it is only used if one of the devices is not able to use WebRTC at all. Only if window.RTCPeerConnection is not present in the browser websockets are used otherwise a WebRTC connection should be the better option. This way the WebRTC connection can be retried if it fails.

As this led to confusion another time we should maybe change the behavior into a real fallback: If the WebRTC connection fails (3 times?) the websockets fallback is used instead. What do you think?

@vedhavyas
Copy link
Author

Ahh I see. I assumed otherwise.

If the WebRTC connection fails (3 times?) the websockets fallback is used instead. What do you think?

This makes sense and seems like the behavior I would expect when I see WS_FALLBACK. So the server would open up a websocket connection with each peer then ?

@schlagmichdoch
Copy link
Owner

So the server would open up a websocket connection with each peer then ?

It already does but it is mainly used for grouping peers together and signaling the WebRTC information.

With the WS_FALLBACK active, files and messages are sent to the server as well and relayed by the server to the selected peer, so the transfer is not peer to peer.
Currently, this is also done without encrypting the traffic which will be changed in the future.

I like the idea of implementing it as a real fallback but the traffic will need to be encrypted first.

@terrytw
Copy link

terrytw commented Feb 4, 2024

@schlagmichdoch Sorry for digging this a little old issue. I know that you are working on a enhancement to make ws fallback the real fallback, at the same time, is there a way for the server to enforce websocket?
I have a self hosted instance, and I don't want to run a turn server as well, it is only my wife and I who uses it, so why bother, I want everything to be via websocket. I used to be able to do so by using a dummy rfc config file which points to a non existent turn server. But after updating to the lastest version it does not seem to work anymore...The logs show that clinent joined the public room, but either side is able to discover each other....

@schlagmichdoch
Copy link
Owner

I have not changed the connection logic everything should work as before. In many cases no TURN server is needed to connect devices via WebRTC so I guess that is what happened. If the ws fallback is used, connected devices are marked with a red border. Was that the case for you?

I'm reluctant to enforce the ws fallback via a config file as the WebRTC solution is much faster (esp. in the next version 1.11.0) and more secure.
Making the fallback a real fallback would be enough for your use case though: devices would connect p2p via WebRTC if possible and would use the ws fallback if a TURN server was needed. Don't you think?

@schlagmichdoch
Copy link
Owner

Also, let's continue the discussion over at #228 as this issue is closed and not related.

Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
Repository owner deleted a comment from schlagmichdoch Feb 17, 2024
@schlagmichdoch
Copy link
Owner

The following comments were deleted by GitHub (via hubot) as part of mistakenly marking this account as spam on 17th February 2024. The correct thread order and the creation date is unclear. I decided to manually restore them anyway in order to complete the information this issue holds even though the restored information might be outdated:

Comment by @schlagmichdoch:

If this only happens on your self hosted instance: Have you set up a TURN server for PairDrop? This is needed for some cross-device connections to work

Comment by @schlagmichdoch:

It may be, that your VPN blocks WebRTC completely. Can you try to switch it off or check if there is an option for allowing WebRTC?

Your devices must be able to create WebRTC connections to be able to use PairDrop.

Visit this page with your device to check if WebRTC is supported:
https://www.webrtc-experiment.com/DetectRTC/#isWebRTCSupported

Next to Browser Supports WebRTC (Either 1.0 or 1.1)? it must say Yep. Some networks or VPN connections somehow disable all WebRTC connections.

You can also try to use pairdrop.net with your VPNs enabled. If this breaks the functionality, probably your VPN is blocking WebRTC

Comment by @schlagmichdoch:

----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.3
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.3
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----
----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.3
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.3
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----
----DEBUGGING-PEER-IP-START----
remoteAddress: ::ffff:10.10.2.4
x-forwarded-for: 10.10.1.22
cf-connecting-ip: undefined
PairDrop uses: 10.10.1.22
IP is private: true
if IP is private, '127.0.0.1' is used instead
----DEBUGGING-PEER-IP-END----

It appears your VPN is hosted on the same device as PairDrop sees local IP addresses. All devices with paired devices will always see each other mutually so there would be no need for pairing.

If two macs can connect to each other, this should normally work with a mobile device too.

It may be though, that the macs only need the STUN server (easy) and the mobile needs to use the TURN server. So if your TURN server is not configured correctly it may only be a problem for some connections.

To make deploying a TURN server alongside PairDrop the docs will be updated in v1.10.0. This will be deployed later today but you can also find it here:
https://github.com/schlagmichdoch/PairDrop/blob/next/docs/host-your-own.md#coturn-and-pairdrop-via-docker-compose

Also, have you tried using other browsers than Brave?
With Google Chrome you could try to remotely debug and check the browser console log: https://developer.chrome.com/docs/devtools/remote-debugging

Comment by @schlagmichdoch:

Thanks for the logs and confs.

If turnserver.hub and pairdrop.hub is either controlled by you or resolved by the vpn to sth else everything looks good.

# sqlite
userdb=/var/db/turndb

I believe the issue is that you use a credential database but don't specify these credentials in your rtc_config.json.

You will probably create a new user for your TURN server like so:

sudo turnadmin -a -u username -p password --db /var/db/turndb

Your rtc_config.json then needs to be:

{
  "sdpSemantics": "unified-plan",
  "iceServers": [
    {
      "urls": "turn:turnserver:3478",
      "username": "username",
      "credential": "password"
    }
  ]
}

See here: https://dev.to/masanori_msl/coturn-add-turn-users-into-a-database-1bga

If you don't want to use the database you can also specify credentials directly in the turnserver.conf by removing the database line and adding:

# Specify the user for the TURN authentification
user=username:password

Comment by @schlagmichdoch:

Ok, thanks for testing.

So the issue only happens on Brave and only with your self hosted version behind a VPN, correct?

Your self hosted instance works correctly using Google Chrome and pairdrop.net also works using Brave.

Is this correct?


When it is not shown on Brave is the Brave device shown on your Mac or does it fail on both devices then?

Comment by @schlagmichdoch:

Also, try using this instance https://pairdrop-next.onrender.com to rule out Brave is somehow whitelisting pairdrop.net as it is quite popular but blocks something on other instances.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working self-hosted WebRTC
Projects
None yet
Development

No branches or pull requests

3 participants