sonosaurus / sonobus

Source code for SonoBus, a real-time network audio streaming collaboration tool.
https://sonobus.net
GNU General Public License v3.0
1.49k stars 106 forks source link

Support for UPnP #82

Open j-santander opened 3 years ago

j-santander commented 3 years ago

In my choir we've been testing Sonobus and we're fairly happy at the quality of sound. I'm concerned about the scalability over 10 participants with requirements for bandwidth and CPU usage growing O(n*(n-1)) with the number of participants. But I digress,

The biggest hurdle we're finding is connectivity. We understand that most of the issues can be overcome by setting up appropriate port-forwarding at the home routers of each participant. However, for a non-technical audience, explaining about accessing the router config, setting up port mapping, oh, by they way did I tell you you should probably have fixed IP addresses assigned?... could an insurmountable task.

I was thinking if adding UPnP capabilities could help. To tell the truth I'm not sure how many routers would have UPnP, and from those how many would have it turned on by default.

I can try my hand at the implementation. I would require a third-party library (e.g miniupnp) but I'm sure how that should be handled in your development environment (which seems slightly different from my cmake experience). So if you could provide some advice on how to do that, I can try to provide a pull request.

Thanks

Julian

P.S. We're also using jamulus and I believe both projects will benefit from learning from each other. I opened a discussion at https://github.com/jamulussoftware/jamulus/discussions/1313

essej commented 3 years ago

Are you actually having issues with symmetric NATs for the people you are trying it with? Usually that's the only time you'll need to get into setting up manual port forwarding....

As for integrating other 3rd party libs, it takes a bit of effort right now. I have plans to move the build setup from JUCE's ProJucer over to cmake (which JUCE supports now)... probably best to wait until then before trying to integrate another dependency....

j-santander commented 3 years ago

Are you actually having issues with symmetric NATs for the people you are trying it with? Usually that's the only time you'll need to get into setting up manual port forwarding....

Well, yes. In our test we joined 13 people. Four of them could not be connected. However, it was not that clean, some of the rest could connect to them, some could after disconnecting and connecting multiple times.

I asked them to provide details on their network provider and router model, looking for a pattern. The 9 people where the connection just worked, were almost all in the same provider and with their latest router. 2 of the non working people where in a different provider and the other 2 were in the same provider as the 9 but with a different (older) router model.

We set up individual sessions with the 4 to teach them how to do the port mapping. It was successful, but at least with one of them I had to open my port (I was in the group of lucky 9) for the bidirectional connection to work.

I'm a software engineer, and although I believe I more or less understand NAT and its problems, I'm not that expert with connection plumbing. However, our experience was very much random with some people just working and some people not, requiring actions on both sides.

We're (or we were) a symphonic choir of 80+. Although we have not returned to in in-person rehearsals and we survive with a mixture of zoom sessions for explanation and instructions and optional Jamulus sessions for some singing. In Jamulus, due to the technical difficulties we gather around 30+.

Now, to me, the technical guy, getting all the them set up and ready on Sonobus will be quite a lot of work.

Spacechild1 commented 3 years ago

In Jamulus, due to the technical difficulties we gather around 30+.

IRRC, Jamulus uses a server client architecture: participants send their audio data to a public server where the streams are mixed and sent back to all participants. The advantage is that it scales to many participants (the only bottleneck is the server) and connectivity is not a problem. The disadvantage is that the extra trip to the server adds additional latency.

I was thinking if adding UPnP capabilities could help

Does Upnp even work with symmetric NATs?


@essej I remember that AOO had a bug where sometimes people couldn't establish the connection to another peer. I have fixed it on develop since then. Maybe this is the cause of @j-santander's problems? I'll try to find the commit.

j-santander commented 3 years ago

IRRC, Jamulus uses a server client architecture: participants send their audio data to a public server where the streams are mixed and sent back to all participants. The advantage is that it scales to many participants (the only bottleneck is the server) and connectivity is not a problem. The disadvantage is that the extra trip to the server adds additional latency.

Yes, that's correct. As you indicated it scales much better at the price of additional latency and the price of having to set up a server.

A central server set up probably matches my use case better, but, for some reason, the people I've trialed with opinion is that Sonobus has much better sound quality.

Does Upnp even work with symmetric NATs?

People were using home routers provided by their network provider, not sure whether they had symmetric NAT. Actually one of my concerns is whether those routers would have UPnP or whether it would have it enabled by default.

Other alternatives is exploring support for STUN/TURN/ICE type of things. TURN, I guess, would impact roundtrip.

AtmanActive commented 3 years ago

Yeah, I still don't get it... how is SonoBus establishing peer-to-peer connections without UPnP or similar?

Spacechild1 commented 3 years ago

how is SonoBus establishing peer-to-peer connections without UPnP or similar?

It uses a connection server which broadcasts the participant's public IP address and port to all its peers. It's basically a homegrown, simplified STUN server. So I don't think that Upnp would give any benefits, as it is just another STUN alternative.

If nobody is behind a symmetric NAT and the connectivity problems are more or less random, I think it could really be the before mentioned bug in AOO. I'll investigate.

Regarding TURN: the development version of AOO already allows the connection server to act as a relay server if required. Maybe Jesse will enable this feature in a future Sonobus version. Of course, relay shouldn't be enabled on a public connection server with thousands of users, but individuals (with a good internet plan) could use it on their own private server.

AtmanActive commented 3 years ago

how is SonoBus establishing peer-to-peer connections without UPnP or similar?

It uses a connection server which broadcasts the participants' public IP address and port to all its peers. It's basically a homegrown, simplified STUN server. So I don't think that Upnp would give any benefits, as it is just another STUN alternative.

I apologize if I am being dumb here and wasting everyone's time, but I still don't get it. Yes, broadcasting of everyone's IP is useful, no doubt, but if user A is behind a NAT and user B is behind a NAT, then, how does them knowing each other's IP help? They still can't talk directly to each other. Or am I missing something here?

Spacechild1 commented 3 years ago

@AtmanActive check out https://en.wikipedia.org/wiki/UDP_hole_punching

Spacechild1 commented 3 years ago

Here's a more detailled explanation: https://bford.info/pub/net/p2pnat/

AtmanActive commented 3 years ago

Now I get it, UDP-bombarding each other. That's how. Thanks @Spacechild1 .

But, as we saw, this doesn't work in 100% of cases. In some cases, it looks like it is working but is unusable (I guess carrier-grade-NATs). So, having UPnP on top, or as a fallback, could be useful.

Spacechild1 commented 3 years ago

In some cases, it looks like it is working but is unusable (I guess carrier-grade-NATs).

UDP hole punching works for all types of NATs except for symmetric NATs. For the latter, UPnP doesn't work either. So I don't think that adding UPnP support would buy us anything. I think the only thing you can do is a) relay or b) port guessing (here's a clever, but rather complex approach: https://www.researchgate.net/publication/228411948_A_New_Method_for_Symmetric_NAT_Traversal_in_UDP_and_TCP)

Spacechild1 commented 3 years ago

@essej You've independently tried to fix the peer ping race condition with b3754dd5f055953c66db19a0763a6f2c4e35d303 and 92d65bbd4f317d2bfd188d3fd7e6a7a6e18fac36

My solution (on the develop branch) is this: https://git.iem.at/cm/aoo/-/commit/59eaf05a6809dc7e3c424e536684ef88ee89ccba

Maybe yours is not 100% bullet proof? Dunno...

j-santander commented 3 years ago

In some cases, it looks like it is working but is unusable (I guess carrier-grade-NATs).

UDP hole punching works for all types of NATs except for symmetric NATs. For the latter, UPnP doesn't work either. So I don't think that adding UPnP support would buy us anything. I think the only thing you can do is a) relay or b) port guessing (here's a clever, but rather complex approach: https://www.researchgate.net/publication/228411948_A_New_Method_for_Symmetric_NAT_Traversal_in_UDP_and_TCP)

Umm, please bear with me on this one. I don't understand why you think UPnP will not work. As I said, I don't know much about low level connectivity.

The only way of traversing a NAT for an incoming connection is when there's a port mapping in place, i.e. a map from external port ( + external address) to internal port and internal address. This happens when:

I understand that symmetric NATs set up those temporary outgoing portmaps so that they are valid only for a specific peer (the third server) and in that case the hole cannot be used by our peer.

If UPnP-ICD is equivalent to static plain-configuration, it has nothing to do with temporary mappings and it should work in exactly the same ways as configured open port.

Spacechild1 commented 3 years ago

To be honest, I don't know much about UPnP. I just did a quick research and the results I've found (including the paper above) say that UPnP doesn't work with symmetric NATs. But maybe that info is wrong or out of date. If you can point me to a source about using UPnP for traversing symmetric NATs, I would be very interested!

AtmanActive commented 3 years ago

I read through that whole document and I'm certain that authors are wrong about UPnP. In section 3.1 on page 3, for example, the claim:

However, one of the disadvantages of UPnP is that it requires that all the devices in the network should support UPnP. Even if a single device does not conform to the UPnP standard, we cannot realize a peer-to-peer network.

is simply not true. If we are talking about TCP communications, then, in reality, it is enough that the listening side has UPnP enabled, both in software and in the gateway NAT router and the connection can be established successfully.

UPnP is just a temporary static NAT port forwarding rule added programmatically. That's all.

Some advanced routers would allow you to see the UPnP table created by intranet clients. By inspecting my own, I can see Skype, Syncthing, Jami and others creating their own port forwards. Some admins turn it off intentionally out of fear of malware abuse.

The only reason why UPnP wouldn't work on a symmetric NAT (carrier-grade NAT) would be if the NAT router itself is ignoring UPnP calls. UPnP-IGD requires two sides to be able to work:

  1. a listener on the NAT device
  2. a client in the program

A program asks for a port number to be forwarded, and the NAT device grants that request by actually creating a NAT/Firewall rule. Of course, if the listener is disabled or absent, then UPnP just silently fails.

Now, if we are talking about big public networks like 4G/5G or public WiFis, where carrier-grade NATs are employed, then, we can surely kiss UPnP goodbye. There is no way in hell a public service provider would leave UPnP enabled and running on their carrier-grade-NAT. These NATs are an absolute necessary evil as they pick random IPs and random ports to relay the traffic, making any external connectivity impossible.

Hence, UPnP in SonoBus wouldn't be a magic bullet, but it could help in some situations.

Spacechild1 commented 3 years ago

@AtmanActive thanks for the explanation!

AtmanActive commented 3 years ago

Let me just add that big public networks like 4G/5G or public WiFis are not doomed forever. All of these limitations come from IPv4. IPv6 has none of those problems, has abundance of available IP addresses and does not use NAT at all. So as IPv6 is deployed more and more around the world, peer to peer connectivity should be fixing itself as well.

IljaN commented 3 years ago

We also seem to have encountered some problems due to DS-Lite. https://www.juniper.net/documentation/us/en/software/junos/nat/topics/topic-map/security-ipv6-dual-stack-lite.html

strk commented 1 year ago

IPv6 has none of those problems

This is why I'm asking to get visibility of connected users IPs as I'm not even sure we're using IP4 or IP6, see #157

Digressing but... did you notice higher latencies with IPv6 (because I did, for some addresses, but not for others)

essej commented 1 year ago

See other issue, you can still see IPs. The current version of SB only supports IPv4 I’m pretty sure. That will change eventually.