mpromonet / webrtc-streamer

WebRTC streamer for V4L2 capture devices, RTSP sources and Screen Capture
https://webrtcstreamer.agreeabletree-365b9a90.canadacentral.azurecontainerapps.io/?layout=2x2
The Unlicense
2.91k stars 595 forks source link

STUN problems #314

Open jonasf21 opened 4 years ago

jonasf21 commented 4 years ago

Hello,

i noticed 2 issues:

1) if you specify a a external STUN server with -s <ip/host> this will not work and instead the server will reply with 127.0.0.1 as STUN server. The problem is the space between -s and IP/host. Its outlined in the help (-h) but this behaviour is confusing.

2) I can use webrtc-streamer fine from most devices and also behind most NAT. However i do have a problem with my cellular provider where i cannot view any stream. I did run the server with -vvv and can see that it seems to be related to a STUN issue (i tried several STUN servers). Webrtc-streamer prints the following messages:

305643518|-]: Sent STUN BINDING request, id=47436877636c764539415a33, use_candidate=0, nomination=0 [007:238] [9931] (connection.cc:1142): Conn[76430420:0:Net[eth0:10.0.201.x/24:Ethernet:id=1]:xkdkHRqg:1:0:local:udp:10.0.201.x:54004->4rLv44IC:1:1685987327:stun:udp:80.187.100.x:17427|C--I|-|0|0|7241260435179978238|-]: Sent STUN BINDING request, id=6b3441474a336e46756a324a, use_candidate=0, nomination=0 [007:287] [9931] (connection.cc:1142): Conn[7642d790:0:Net[eth0:10.0.201.x/24:Ethernet:id=1]:xkdkHRqg:1:0:local:udp:10.0.201.x:54004->LKFw1xt4:1:2122187007:local:udp:10.27.12.x:52341|C--I|-|0|0|9114723795305643518|-]: Sent STUN BINDING request, id=544c3871472b43456c615953, use_candidate=0, nomination=0

(10.0.201.x beeing my local network). It appears it somehow detects 2 external IPs from the client, beeing 10.27.12.255 (which is a NAT address from the cellular provider) and 80.187.100.255 (which is the "real" outgoing IP from the cellular provider). As that no stream will play and things are broken.

I took a capture with wireshark (from the server side) and it looks like the client is providing this wrong ip:

POST /api/addIceCandidate?peerid=0.6038627331126462 HTTP/1.1 Host: xyz User-Agent: Mozilla/5.0 (Android 9; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0 Accept: / Accept-Language: de,de-DE;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Content-Type: text/plain;charset=UTF-8 Content-Length: 133 Connection: keep-alive Referer: http://xyz/webcam/

{"candidate":"candidate:0 1 UDP 2122187007 10.27.12.255 54378 typ host","sdpMid":"2","sdpMLineIndex":2,"usernameFragment":"742e8463"}

I am not sure if this is somehow related to double NAT from the cellular provider etc. Is there anything i can do to debug further?

lthrhx commented 4 years ago

You got a step further than I have. I am using webrtc-streamer 0.2.6 and this works within the LAN, but trying to get it to work on the internet / WAN doesn't. The webpage renders, but the video doesn't show.

Running this command on webrtc-streamer computer: ./webrtc-streamer -H 0.0.0.0:8000 -sstun.l.google.com:19302

I forwarded TCP port 8000 from the router to the webrtc-streamer computer. What else needs to be done in order to view the video from the internet / WAN?

jonasf21 commented 4 years ago

@lthrhx i didnt specify -H. It was working out-of-the-box when trying via internet. However i havent gotten the setup via the cellular networks to work (probably double/CGNAT etc). So i have worked around that by deploying a turn server myself which works great (even on those mobile networks). I had to play around with the settings but after some time got it to work (you need to use user/pw auth, anonymous is not working). For the turn server its only important that its not behing NAT (of course).

lthrhx commented 4 years ago

Thank you, good to know what to do next.

What program / solution did you use for your TURN server?

jonasf21 commented 4 years ago

@lthrhx i used coturn, the regular package included with debian. I used these settings (and only these):

listening-port=3478 tls-listening-port=5349 listening-ip=x.x.x.x external-ip=x.x.x.x (same as above) fingerprint lt-cred-mech user=someusername:somepassword realm=x.x.x.x (needs to be same as external ip) no-tls no-dtls no-loopback-peers no-multicast-peers mobility proc-user=nobody proc-group=nogroup

then configure webrtcstreamer to use someusername:somepassword@x.x.x.x and it should work. Took me a while to find out it requires the realm needs to be the external ip.

mpromonet commented 4 years ago

Hi jonasf31,

It is also possible to use the embeded TURN server. For instance using : ./webrtc-streamer -T0.0.0.0:3478 -tturn:turn@<public-ip>:3478

Using service like ifconfig.me, it could becomes ./webrtc-streamer -T0.0.0.0:3478 -tturn:turn@$(curl ifconfig.me -s):3478

The -T ask to start a local TURN and -t give the TURN url the client will use to reach it. This should also be possible with STUN, I made a small modification to allow -S and -s in the same way.

Best Regards, Michel.

generic-beat-detector commented 4 years ago

Hello Michel and jonasf21,

Some clarification please,

... correcto?

jonasf21 commented 4 years ago

@mpromonet Yes, i know. But my webrtc-streamer instance is behind NAT, so i couldnt use the included TURN server.

@generic-beat-detector thats absolutly correct and thats the reason why i deployed the TURN externally.

mpromonet commented 4 years ago

Hi,

With the modification of STUN https://github.com/mpromonet/webrtc-streamer/commit/bca3ae0ce8c2e75f0f58790d8208836cb1d4e450 (artefacts https://circleci.com/gh/mpromonet/webrtc-streamer/5524#artifacts/containers/0) and running webrtc-streamer behind the NAT (with rule on 8000 & 3478) allow to see webrtc stream without using additional resource. Starting with: ./webrtc-streamer -S -s$(curl ifconfig.me -s):3478

Best Regards, Michel.

generic-beat-detector commented 4 years ago

Dear Michel, sir

I think I can dig it:

Am I interpreting correctly?

mpromonet commented 4 years ago

Dear @generic-beat-detector,

Yes, for port forwarding this needs TCP on 8000 (default port) and TCP+UDP on 3478 for STUN.

Since the beginning it is possible I made a misinterpretation, because (from my test) it is working using google STUN with webrtc-streamer behind a NAT configuring rule to redirect HTTP port. I was wondering the pb was because some country cannot access to stun.l.google.com:19302 or another STUN server available from internet.

After the discussion move to TURN that is a possible way, installing coturn or using an avaible TURN on internet.

If you are using webrtc-streamer behind a NAT with dynamic IP allocation, probably you should look to something like upnp to configure the port forwarding.

Best Regards, Michel.

generic-beat-detector commented 4 years ago

@mpromonet

Maestro, yes, UPnP with NAT traversal looks quite delicious. I'll have to try it out and if it works, this will make the embedded STUN/TURN facility truly nice.

Best Regards, GBD

beniroquai commented 4 years ago

@mpromonet Thanks for your effort to make the setup work! Unfortunately I cannot access the stream from remote even though I forwarded ports TCP:8000 and TCP/UDP:3478. I assume google's STUN is available in Germany. The default webpage renders correctly running this line: ./webrtc-streamer -S -s$(curl ifconfig.me -s):3478 on your proposed artifacts bca3ae0, but the stream doesn't show up. calling the WAN IP from my local network works. Any idea?

mpromonet commented 4 years ago

Hi @beniroquai

From germany probably you do not need to use the embeded STUN server, just use default configuration that use google's STUN. Starting with ./webrtc-streamer and forwarding the http port 8000 to your LAN.

Best Regards, Michel.

generic-beat-detector commented 4 years ago

@beniroquai

I have encountered similar issues (with a Google STUN and port forwarding setup):

Interesting.

jonasf21 commented 4 years ago

@generic-beat-detector check if you can watch: http://home.sslsecured.de/webcam (thats my stream behind coTURN and webrtc-streamer). If it works you should see some bee hives. I havent found any client with problems so far...TURN works great. I dont like uPNP, too many security headaches with that.

beniroquai commented 4 years ago

Hey, I cannot access that. Same from my cellular phone. Do you have any idea what could be the problem? I'm running the same setup with TURN.

Am Mo., 20. Apr. 2020 um 12:32 Uhr schrieb jonasf21 < notifications@github.com>:

@generic-beat-detector https://github.com/generic-beat-detector check if you can watch: http://home.sslsecured.de/webcam (thats my stream behind coTURN and webrtc-streamer). If it works you should see some bee hives. I havent found any client with problems so far...TURN works great. I dont like uPNP, too many security headaches with that.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mpromonet/webrtc-streamer/issues/314#issuecomment-616460701, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBE5OHFK2274TGIDOPUEX3RNQQFTANCNFSM4MHTWKJQ .

mpromonet commented 4 years ago

Hi @jonasf21

Yes I can see the bees, but as you have STUN & TURN configured, I guess this is using STUN. I recently add an option -s- in order to not export STUN url.

Best Regards, Michel.

generic-beat-detector commented 4 years ago

@jonasf21 Yes sir, I can truly see bees, hives and everything! I've tested streaming via my Ubuntu laptop (cable connection) and Android phone (data network). Clear as day with very acceptable jitter -- and somewhat puzzingly a more crispy picture than my local setup!? I am halfway across the world from Europe. Is that a RPi cam? What resolution?

@mpromonet I was about to raise that very STUN/TURN question ... probably the SDP/ICE info on the web console can reveal this? I'm a bit rusty on the subject...

jonasf21 commented 4 years ago

@beniroquai no idea...i havent found any client so far that has problems. From which devices/connections did you try that? Maybe try to capture a trace via wireshark?

@generic-beat-detector I've limited the picture quality by limiting the bandwidth. Its a feed from a axis webcam (at 720p). If there are many bees on the picture (and moving fast) the bandwidth goes insane. Have to look at h265 some day.

@mpromonet Wouldnt the browser try STUN and TURN and see which once succeeds? Or will things break if one of them fails?

generic-beat-detector commented 4 years ago

@jonasf21

True and right on point again! H264 and (sudden) increase in differences between frames make for fluctuations in bandwidth that (more often than not) degrade transmission quality. I'm only doing 640x480 and I often suffer ridiculous jitter when a sizeable object crosses the cam view...

Limiting streaming bandwidth sounds like a clever plan and evidently works as I can see. If your circumstances permit, then I anxiously await hearing how you went about this trickery...

generic-beat-detector commented 4 years ago

@jonasf21

Bandwidth shaping via tc(8) and iptables(8) maybe?

jonasf21 commented 4 years ago

@generic-beat-detector no, that will not work. You need to reduce the bandwidth by using a h264 with variable bitrate (VBR). That way it will still play at 25+fps but quality will be reduced. If you use tc/iptables etc. it will make the stream skip frames or be totally broken at all.

generic-beat-detector commented 4 years ago

@jonasf21 Hmm...so this H.264 with VBR encoding has to be performed at the source of the RTSP stream? In your case, the axis webcam? I don't suppose webrtc-streamer supports this mechanism?

jonasf21 commented 4 years ago

@generic-beat-detector yes and no. The axis webcam can do this and change the encoding according to the desired bitrate. Some other cams can do that, too. Another option would be to grab the stream from your source and decode and re-encode it (for example via ffmpeg). I have also played with that. However it takes quite some CPU to do it for h264 (raspberry pi can do this for regular HD feeds, not 4k). That way you have full control over the bitrate. As for h265 this is not possible as the PI (4+) only has decoding in hw but not encoding. For h265 you need "real" horsepower. But we are leaving this topic... webrtc-streamer is streaming and has nothing to do with encoding, so this is beyond the scope.

generic-beat-detector commented 4 years ago

@jonasf21 Agreed. We have digressed from a STUN discussion. But thanks anyway.

Regards, GBD

lthrhx commented 4 years ago

@mpromonet I used the 2.6.14 g1409ab5 test build listed above, but still wasn't able to use the built in TURN server behind NAT. Trickle-ice website https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ reports it as being unreachable: ./webrtc-streamer -s- -T0.0.0.0:8478 -tturnuser:turnpassword@public.ip.from.isp:8478

NOTE: For some reason my ISP has an issue with port 3478, so I have to run it through port 8478.

When using coturn I need to identify the external ip with the internal ip in order for this to work. I figured I should try that too, but it didn't work either: ./webrtc-streamer -s- -T0.0.0.0:8478 -tturnuser:turnpassword@public.ip.from.isp:8478/192.168.1.99

Coturn turnserver command that works with webrtc-streamer: sudo turnserver -a -v -n -u turnuser:turnpassword -p 8478 -L 192.168.1.99 -r someRealm -X public.ip.from.isp/192.168.1.99 --no-dtls --no-tls --cli-password supersecret --min-port 58000 --max-port 58999 --no-stun

webrtc-streamer command that works with coturn: ./webrtc-streamer -tturnuser:turnpassword@public.ip.from.isp:8478

My server 192.168.1.99 is behind a NAT with both webrtc-streamer and coturn installed on it.

server <ports 8000 & 8478 forwarded> Firewall & router <> INTERNET <> Firewall & router <> client

mpromonet commented 4 years ago

Hi lthrhx, I just a made a test with the embeded TURN, it seems working without problems starting with ./webrtc-streamer -s- -T0.0.0.0:3478 -tturn:turn@$(curl -s ifconfig.me):3478 Adding the internal IP makes fail the initialization of PeerConnection.

Best Regards, Michel.

lthrhx commented 4 years ago

I can't use port 3478 and I think your builtin turnserver doesn't let the port be redefined.

Here is my list of ports when running: ./webrtc-streamer -s- -T0.0.0.0:3478 -tturn:turn@$(curl -s ifconfig.me):3478

sudo lsof -i -P -n | grep LISTEN webrtc-st 30202 adminlocal 10u IPv4 89129581 0t0 TCP *:8000 (LISTEN) turnserve 30285 turnserver 21u IPv4 89130834 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 30285 turnserver 23u IPv4 89130836 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 30285 turnserver 24u IPv4 89128851 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 30285 turnserver 26u IPv4 89129589 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 30285 turnserver 27u IPv6 89130838 0t0 TCP [::1]:3478 (LISTEN) turnserve 30285 turnserver 28u IPv4 89129591 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 30285 turnserver 29u IPv4 89128853 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 30285 turnserver 31u IPv6 89129593 0t0 TCP [::1]:3478 (LISTEN) turnserve 30285 turnserver 32u IPv6 89128855 0t0 TCP [::1]:3478 (LISTEN) turnserve 30285 turnserver 36u IPv4 89130841 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 30285 turnserver 39u IPv4 89130843 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 30285 turnserver 40u IPv6 89130845 0t0 TCP [::1]:3478 (LISTEN)

If I run this: ./webrtc-streamer -s- -T0.0.0.0:8478 -tturn:turn@$(curl -s ifconfig.me):8478

These are the ports and programs:

sudo lsof -i -P -n | grep LISTEN webrtc-st 30537 adminlocal 10u IPv4 89136619 0t0 TCP *:8000 (LISTEN)

All of the turnserve processes are missing when changing the port from 3478 to 8478. I also tried changing it to ports 8847, 8008, and 8080 but the turnserve process doesn't launch. The weird thing is that 'webrtc-streamer' reports it is listening for TURN on 8478 but the process doesn't actually run.

./webrtc-streamer -vvv -s- -T0.0.0.0:8478 -tturn:turn@$(curl -s ifconfig.me):8478 HTTP Listen at 0.0.0.0:8000 TURN Listening at 0.0.0.0:8478

mpromonet commented 4 years ago

Hi lthrhx,

The port doesnot matter, I try with ./webrtc-streamer -s- -T0.0.0.0:8478 -tturn:turn@$(curl -s ifconfig.me):8478 Exposing the port using upnpc ipnpc -r 8000 tcp 8478 udp I can see my raspberry webcam through the NAT redirection. lsof give something like :

webrtc-st 31194   pi    9u     IPv4 417649      0t0    TCP *:8000 (LISTEN)
webrtc-st 31194   pi   60u     IPv4 417650      0t0    UDP *:8478
webrtc-st 31194   pi   63u     IPv4 484260      0t0    TCP 192.168.0.16:44061 (LISTEN)
webrtc-st 31194   pi   66u     IPv4 484259      0t0    UDP 192.168.0.16:43625

The UDP port 43625 is corresponding to the ICE candidate:

        {
                "candidate" : "candidate:2248577876 1 udp 1686052607 X.X.X.X 43625 typ srflx raddr 192.168.0.16 rport 43625 generation 0 ufrag Mh7W network-id 1",
                "sdpMLineIndex" : 0,
                "sdpMid" : "0"
        },

I don't remember well, but I think the WebRTC SDK doesnot support TCP. Maybe your problem is about this ?

Best Regards, Michel.

lthrhx commented 4 years ago

I don't think the issue is TCP or upnp through the router as the turnserver doesn't start on the local computer - long before it goes down the line to the router. The problem is that webrtc-streamer's built in turnserver doesn't fully start when the TURN port is anything other than 3478.

When I run ./webrtc-streamer -s- -T0.0.0.0:3478 -tturn:turn@$(curl -s ifconfig.me):3478 and then run sudo lsof -i -P -n there is an a service running named turnserve

When I run ./webrtc-streamer -s- -T0.0.0.0:8478 -tturn:turn@$(curl -s ifconfig.me):8478 and check the ports with sudo lsof -i -P -n the service turnserve isn't there. It should be, but it isn't.

Another example: When specifying port 3478:

webrtc-st 26771 adminlocal 10u IPv4 89774379 0t0 TCP :8000 (LISTEN) webrtc-st 26771 adminlocal 61u IPv4 89774380 0t0 UDP :3478 turnserve 26829 turnserver 21u IPv4 89775432 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 26829 turnserver 23u IPv4 89774494 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 26829 turnserver 24u IPv4 89771711 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 26829 turnserver 25u IPv4 89775434 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 26829 turnserver 26u IPv4 89774496 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 26829 turnserver 28u IPv4 89771713 0t0 TCP 172.16.0.133:3478 (LISTEN) turnserve 26829 turnserver 29u IPv6 89774498 0t0 TCP [::1]:3478 (LISTEN) turnserve 26829 turnserver 30u IPv6 89775436 0t0 TCP [::1]:3478 (LISTEN) turnserve 26829 turnserver 31u IPv6 89771715 0t0 TCP [::1]:3478 (LISTEN) turnserve 26829 turnserver 37u IPv4 89771718 0t0 TCP 127.0.0.1:3478 (LISTEN) turnserve 26829 turnserver 38u IPv6 89771722 0t0 TCP [::1]:3478 (LISTEN) turnserve 26829 turnserver 39u IPv4 89771720 0t0 TCP 172.16.0.133:3478 (LISTEN)

When specifying port 8478:

webrtc-st 22927 adminlocal 10u IPv4 89689223 0t0 TCP :8000 (LISTEN) webrtc-st 22927 adminlocal 61u IPv4 89689224 0t0 UDP :8478

Notice that the turnserve process isn't running.

lthrhx commented 4 years ago

Sorry, I was wrong. I have coturn installed on this server and that is why turnserve was there. Disregard my last couple of comments about turnserve and the ports.

I still cannot get the built in turnserver to work in webrtc-streamer 2.6.14, but that is not an issue as I am using coturn.

mpromonet commented 4 years ago

Hi,

The TURN server embeded inside webrtc-streamer doesnot fork a process, it is instanciate the class cricket::TurnServer (see https://github.com/mpromonet/webrtc-streamer/blob/master/src/main.cpp). If you have a service turnserve it comes from somewhere else.

Best Regards, Michel.

lthrhx commented 4 years ago

You are correct, the service turnserve was from installing coturn.