pion / turn

Pion TURN, an API for building TURN clients and servers
MIT License
1.87k stars 319 forks source link

Share a port with net/http #418

Open jech opened 1 week ago

jech commented 1 week ago

Hi,

The strict minimum for Galene to be accessible from a retrictive network is two open ports: the webserver's port and the TURN server's port. By default, Galene uses 8443 for the web server, and 1194 for the TURN server, for the simle reason that these ports are guaranteed to be accessible from every Eduroam network1.

Ideally, we should be able to share a single port between the web server and the TURN server: perhaps a demultiplexer coud be examine the first bytes sent over a TCP connection, and dispatch the connection to either the TURN server or the web server. UDP would go to Turn for now, which will obviously break when net/http implementes HTTP/3.

levaitamas commented 1 week ago

hi @jech !

As long as you use different protocols (TCP for the webservice and UDP for TURN), having the same port number will not be an issue. The operating system does the "demultiplexing" for you.

jech commented 1 week ago

Of course. The issue is with TURN over TCP, which is required for videoconferencing to work in restrictive networks that block all UDP.

rg0now commented 1 week ago

So your webservice is doing HTTP/WebSocket/GRPC, while the TCP is of course TURN/TCP or TURN/TLS and you'd like to expose these on the same port, it that right?

Now one way to solve this would be to add a gateway that will do some magic to separate HTTP traffic from pure TCP and route sessions based on that. I've never done that myself, but it certainly seems doable with Envoy (you may need to manually config Envoy though, I'm not sure envoy-gateway or Istio exposes this semi-advanced feature, but who knows?). Here is a seemingly relevant example on how to separate TLS from non-TLS TCP traffic, and here is the the corresponding Envoy API config.

On the long run I'm not sure it's worth the pain. TURN/TCP latency can go terribly bad even without a proxy in front.

jech commented 1 week ago

There is no reason we shouldn't be able to achieve that in pure Go code, without involving a proxy.

rg0now commented 1 week ago

You mean by adding this functionality to STUNner?

jech commented 1 week ago

You mean by adding this functionality to STUNner?

No.

rg0now commented 1 week ago

I'm terribly sorry, I replied to the wrong thread. Please ignore my last comments.

I agree: adding this in Go is absolutely possible. We may not even need to modify the TURN server for this: just pass in a net.Listener that parses the first couple of bytes of each TCP connection, identifies HTTP traffic and forwards it to an HTTP server, and passes the unmodified TCP buffer to the TURN server otherwise.

It is still an interesting question how to reliably tell HTTP from non-HTTP traffic apart, especially that we may need to look into encrypted HTTPS/TLS payload. Perhaps the Envoy HTTP Inspector linked above might be instructive here (at least my stupid comment was not completely in vain).