WebRTSP/ReStreamer

Non-host Web Clients can not access streams running in docker (even stops running ones)

Closed this issue ยท 40 comments

Hello,

I am running the latest commit on master 0c3619b in an Ubuntu 20.04 docker image with Gstreamer 1.16.2. I have exposed port 5554 and 5080.

once I run ReStreamer from the container, Web client access from the docker host (i.e. http://localhost:5080/) work as expected but non-host clients they can not access the stream as the ice candidates are very limited now. I tried enabling the stun server but it didn't help.

Here's the log when such access occurs:

[2021-12-15 10:14:46.789] [GstRtStreaming] [trace] [GstWebRTCPeer2] Ice Connection State changed: "GST_WEBRTC_ICE_CONNECTION_STATE_FAILED"
[2021-12-15 10:14:46.789] [GstRtStreaming] [trace] [GstWebRTCPeer2] Connection State changed: "GST_WEBRTC_PEER_CONNECTION_STATE_FAILED"

Could this be solved by a turn server? can we solve it without it?

Thanks in advance!

Do you have STUN server configured? Oops, missed you've already tried it...

Are you trying to connect client and server over internet or it's some local network?

Are you trying to connect client and server over internet or it's some local network?

local network, we also tried WAN via a VPN but that too didn't work!

I don't know docker well enough, but are you sure container has all required ports opened to local network? WebRTC could require UDP ports from Ephemeral range.

Also, did you try run the same code on the same host without Docker container?

Also, did you try run the same code on the same host without Docker container?

yes and it works in that case.

I don't know docker well enough, but are you sure container has all required ports opened to local network? WebRTC could require UDP ports from Ephemeral range.

I only opened the ports that would enable clients to reach the container through the docker host, which are in this case, 5080 for HTTP and 5554 for the WebSocket. All other ports inside the container are available internally but not exposed.

Then I think you need:

  1. All required ports opened on Docker
  2. STUN server running on network through which you want data go through (Docker acts as another one router with NAT). I mean it's definitely will not work if you will use some public STUN server (like Google's one)

Then I think you need:

  1. All required ports opened on Docker
  2. STUN server running on network through which you want data go through (Docker acts as another one router with NAT). I mean it's definitely will not work if you will use some public STUN server (like Google's one)

Regarding point 2, why the public STUN wouldn't work? and if we are to use our STUN server, should it be placed in the container in this case? what difference would it make in this case?

STUN server should give IP visible (and routable) to both parties. If you will use public STUN server it will give your public IP (i.e. IP exposed to internet, and I bet you are behind another NAT), and don't think it will be possible to route UDP packets through that IP.
If you put STUN inside the same Docker container with ReStreamer - it will give you IP from Docker local network (your container local IP), and that IP is accessible only from Docker

And btw, TURN server on public network will work in your case, but then all traffic will always go through it...

STUN server should give IP visible (and routable) to both parties. If you will use public STUN server it will give your public IP (i.e. IP exposed to internet, and I bet you are behind another NAT), and don't think it will be possible to route UDP packets through that IP. If you put STUN inside the same Docker container with ReStreamer - it will give you IP from Docker local network (your container local IP), and that IP is accessible only from Docker

Quick question here, Which STUN server the web client will use to provide an IP for it? the one we configured at ReStreamer? how could it access it or know of its existence?

If you will use HTTP server from ReStreamer - it will expose STUN server through Config.js and it will be used in browser client.

I did some tracing of the ice candidates exchange

  • Running without Docker (Client Accessing from the internet)

    • Candidates received from the client include:
      • 0/candidate:842163049 1 udp 1677729535 156.215.247.251 26465 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag 5f7+ network-cost 999 which is the public IP
      • another irrelevant IPv6
    • Candidates sent from ReStreamer to the client include but not limited to (I count 40 of them):
      • 0/a=candidate:10 1 UDP/TCP 2013266428 192.168.236.14 41282 typ host this is the VPN IP
      • 0/a=candidate:20 2 TCP 1015023358 172.17.0.1 9 typ host tcptype active docker0
      • 0/a=candidate:13 1 UDP/TCP 2013266427 172.18.0.1 53049 typ host docker ip (they show up if you run ifconfig)
      • 0/a=candidate:13 1 UDP/TCP 2013266427 172.19.0.1 53049 typ host another docker ip
      • 0/a=candidate:22 1 UDP/TCP 2013266424 192.168.1.108 44630 typ host local IP
      • bunch of other IPv6
  • Running with Docker (Client Accessing from the internet)

    • Candidates received from the client include:
      • 0/candidate:842163049 1 udp 1677729535 197.58.88.60 33788 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag IKJk network-cost 999 which is the public IP
      • another irrelevant IPv6
    • Candidates sent from ReStreamer to the client including but not limited to (I count 6 only):
      • 0/a=candidate:1 1 UDP/TCP 2013266431 172.21.0.2 38415 typ host tcptype active/passive

Clearly being behind NAT is the issue, simply all the IPs provided by ReStreamer in the container are not accessible. but why there wasn't a public IP provided for ReStreamer in either case?

Without STUN ReStreamer (or any other WebRTC peer) know nothing about IP of host it's running on (i.e. about IPs of routers it's behind, and there can be many of them, like in ๐Ÿช†). STUN server is exactly for that task - to get nearest to STUN server IP not behind NAT.

Without STUN ReStreamer (or any other WebRTC peer) know nothing about IP of host it's running on (i.e. about IPs of routers it's behind, and there can be many of them, like in nesting_dolls). STUN server is exactly for that task - to get nearest to STUN server IP not behind NAT.

yes I understand, but I provided Google's STUN server when running outside docker and still ReStreamer did not figure out the IP of its host. Is this normal?

No, there should be Ice Candidate with your public IP.

And please check if you use STUN server URL with stun:// (i.e. // are important) prefix in ReStreamer config

And please check if you use STUN server URL with stun:// (i.e. // are important) prefix in ReStreamer config

I used it as you provided it in the config file stun-server: "stun://stun.l.google.com:19302"

Kindly, check this log here as I could only find the a public IP for the client and not ReStreamer.

I don't see any srflx candidates from ReStreamer in this log... So it looks like STUN server not working by some reason... Did you try check it with https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ ?

I don't see any srflx candidates from ReStreamer in this log... So it looks like STUN server not working by some reason... Did you try check it with https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ ?

yes, I used stun:stun.l.google.com:19302 and here is the result

What GStreamer version do you have on your host?

What GStreamer version do you have on your host?

1.16.2 all along

1.16.2 is pretty old... so I can imagine 2 reasons:

  1. old GStreamer
  2. bug somewhere in my code.

I'll check the second soon.

I think it's a bug in my code.

I think it's a bug in my code.

Is the bug present with other gstreamer versions as well? or only in 1.16.2?

It's fixed. Please try the latest version.

And no, it was not related to GStreamer version.

It's fixed. Please try the latest version.

And no, it was not related to GStreamer version.

Well, ReStreamer is rocking srflx everywhere now :)

So did it fix Docker support for you?

So did it fix Docker support for you?

I just tested that and unfortunately it didn't work. here's the updated log . It only works from the docker host machine. Other machines on the local network or the internet can't connect.

I can see srflx candidates now... so it's some different issue... Is there your host IP in that srflx candidates?

You can find some details about configuring WebRTC in Docker here: https://habr.com/ru/company/flashphoner/blog/562244/
In two words - you have to open incoming UDP ports too...

I can see srflx candidates now... so it's some different issue... Is there your host IP in that srflx candidates?

Yes, the host's public IP is in there, not the local one though

You can find some details about configuring WebRTC in Docker here: https://habr.com/ru/company/flashphoner/blog/562244/ In two words - you have to open incoming UDP ports too...

I'll do some experimentation and let you know.

I'm confused a little bit. What do you mean by host's public IP and local one?

I'm confused a little bit. What do you mean by host's public IP and local one?

Public IP is the internet IP assigned by the ISP such as 41.237.189.40, local IP is the one assigned by the DHCP server or set manually.

Thanks for the link you provided, the thing that made it click and work for me is when I ran the container using the host's own network i.e. passing --net host when launching the container.

However I started seeing these warnings, I know that I have reported them earlier

** (ReStreamer:15): WARNING **: 08:18:07.608: Failed to GET http://90.90.90.90:1900/gatedesc.xml: Could not connect: Socket I/O timed out, retrying in 20 seconds

** (ReStreamer:15): WARNING **: 08:18:07.608: Failed to GET http://90.90.90.90:1900/gatedesc.xml: Could not connect: Socket I/O timed out, retrying in 20 seconds

** (ReStreamer:15): WARNING **: 08:18:07.608: Failed to GET http://90.90.90.90:1900/gatedesc.xml: Could not connect: Socket I/O timed out, retrying in 20 seconds

** (ReStreamer:15): WARNING **: 08:18:07.608: Failed to GET http://90.90.90.90:1900/gatedesc.xml: Could not connect: Socket I/O timed out, retrying in 20 seconds

** (ReStreamer:15): WARNING **: 08:18:07.609: Failed to GET http://90.90.90.90:1900/gatedesc.xml: Could not connect: Socket I/O timed out, retrying in 20 seconds

** (ReStreamer:15): WARNING **: 08:18:32.612: Maximum number of retries failed, not trying again

Do you know what is 90.90.90.90?

Do you know what is 90.90.90.90?

no, not at all.

For the record, I also tried the IPvLAN method mentioned in the link you provided and it worked as well.

Thank you for your support and assistance, you may close this issue at your discretion!

According to googling http://x.x.x.x:1900/gatedesc.xml is related to UPNP. I do nothing with UPNP myself, so it's something inside libnice I think. And the question is why it's trying to access 90.90.90.90...