Janus gateway behind NAT/firewall signalling

2,146 views
Skip to first unread message

V Venkatesh

unread,
Sep 9, 2017, 4:13:32 PM9/9/17
to meetecho-janus
Is there a way to put the Janus gateway behind a NAT without any port forwarding or other configuration on the firewall?  There are a couple of topics in this forum that talk about NAT/ISP/firewall, but none of the posts offer a good clarification, other than reiterating that Janus is not recommended to be behind a NAT.  This is confusing, because WebRTC/ICE is supposed to provide p2p connectivity across NAT (except in symmetric NATs - lets ignore that case for this topic)

Couple of things are confusing:

 - WebRTC needs a signalling mechanism to convey session information and start the ICE negotiation across the NAT.  No samples or docs I have seen talk about how signalling can be used with Janus.

 - It appears to me that that the http/websockets ports must be port-forwarded across the NAT.  This defeats the purpose of using ICE/STUN/TURN negotiation (yes, ICE is also used for media negotiation, but lets put that aside for the sake of this topic) 

Apologies if I missing something simple.

Firas Abd Alrahman

unread,
Sep 9, 2017, 5:49:29 PM9/9/17
to V Venkatesh, meetecho-janus

--
You received this message because you are subscribed to the Google Groups "meetecho-janus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to meetecho-janus+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Eng. Firas Abd Alrahman
Khartoum, Sudan, Alriad, 60 St.
Mobile : +249126712777
Phone  : +249123334569
              

Lorenzo Miniero

unread,
Sep 10, 2017, 5:54:41 AM9/10/17
to meetecho-janus
Il giorno sabato 9 settembre 2017 22:13:32 UTC+2, V Venkatesh ha scritto:
Is there a way to put the Janus gateway behind a NAT without any port forwarding or other configuration on the firewall?  There are a couple of topics in this forum that talk about NAT/ISP/firewall, but none of the posts offer a good clarification, other than reiterating that Janus is not recommended to be behind a NAT.  This is confusing, because WebRTC/ICE is supposed to provide p2p connectivity across NAT (except in symmetric NATs - lets ignore that case for this topic)



Of course it works. A server behind a NAT is always suboptimal, though, as being on a public and reachable address makes it much easier to eventually succeed, especially in edge cases. If Janus is behind a NAT too, it will also have to take care of STUN etc., which if you can avoid it's better.



Couple of things are confusing:

 - WebRTC needs a signalling mechanism to convey session information and start the ICE negotiation across the NAT.  No samples or docs I have seen talk about how signalling can be used with Janus.

 - It appears to me that that the http/websockets ports must be port-forwarded across the NAT.  This defeats the purpose of using ICE/STUN/TURN negotiation (yes, ICE is also used for media negotiation, but lets put that aside for the sake of this topic) 



Signalling has nothing to do with WebRTC, it's explicitly out of scope. It definitely has nothing to do with ICE/STUN/TURN at all, as that only applies to the media you negotiate.
Making signalling work behind a NAT, via proxying, reverse something, wrapping of the API with something you build is up to you.

L.

V Venkatesh

unread,
Sep 10, 2017, 12:48:26 PM9/10/17
to meetecho-janus


On Sunday, September 10, 2017 at 5:54:41 AM UTC-4, Lorenzo Miniero wrote:
Il giorno sabato 9 settembre 2017 22:13:32 UTC+2, V Venkatesh ha scritto:
Is there a way to put the Janus gateway behind a NAT without any port forwarding or other configuration on the firewall?  There are a couple of topics in this forum that talk about NAT/ISP/firewall, but none of the posts offer a good clarification, other than reiterating that Janus is not recommended to be behind a NAT.  This is confusing, because WebRTC/ICE is supposed to provide p2p connectivity across NAT (except in symmetric NATs - lets ignore that case for this topic)



Of course it works. A server behind a NAT is always suboptimal, though, as being on a public and reachable address makes it much easier to eventually succeed, especially in edge cases. If Janus is behind a NAT too, it will also have to take care of STUN etc., which if you can avoid it's better.


Please bear with me as this reply is a bit long. We are somewhat in agreement.  Yes, agree with you about a publicly available address.  However, respectfully disagree about the NAT comment - once the ICE negotiation has concluded and a p2p direct path is found, performance  can be just as good as a publicly available service.  Of course, as you suggest, there are edge cases where no pathway is found and a TURN server relay needs to be used, but lets put this edge case aside for the moment.  




Signalling has nothing to do with WebRTC, it's explicitly out of scope. It definitely has nothing to do with ICE/STUN/TURN at all, as that only applies to the media you negotiate.
Making signalling work behind a NAT, via proxying, reverse something, wrapping of the API with something you build is up to you.


Again, respectfully disagree, WebRTC (i.e. ICE for all intents and purposes) needs signalling when NATs are involved, but leaves the signalling implementation up to the developer.  WebRTC wraps around ICE, which uses STUN and TURN to find a pathway between two nodes. 

My understanding -  is that for ICE to find a p2p pathway between parties Alice and Bob, this is the workflow - :
 (a)  Alice and Bob determine a set of "local candidates" using a publicly available STUN server.  Simplified, a "candidate" is a combo of IP address and port.
 (b) Alice must send to Bob her candidates.  To Bob, Alice's candidates are Bob's "remote candidates"
 (c) Bob does the same thing - send Alice his candidates (Alice's remote candidates)
 (e) ICE initiates negotiation once all candidates have been exchanged.  ICE then determines at least one local and remote candidate pair that can be used to establish the p2p connection.  If not, the TURN relay is a fallback. 

If both Alice and Bob are behind NATs whose firewall config cannot be touched, then the only way to do (b) and (c) above is to use an external publicly available relay - and not the TURN server  - "signalling" in ICE.  So a method to hook this external signalling channel is the missing tweak in Janus. 


Since Janus uses libnice, so I took a peek there and then at the Janus code:  

 - First, this post seems to confirm that you need a 3rd party custom relay when NATs are involved. https://lists.freedesktop.org/archives/nice/2012-January/000495.html
"libnice does not provide any serialization method, you will still always need a
third party server to do the candidate exchange and that will depend on the
protocol used by this server, could be XMPP, could be SIP, could be custom, it
really all depends on what your needs are and what the server supports/accepts."


// ... Send local candidates to the peer and set the peer's remote candidates
 nice_agent_set_remote_candidates (agent, stream_id, 1, rcands);

And it does appear that janus.c processes incoming messages and setting of remote candidates in janus_process_incoming_request()  so maybe that's a good place to hook in signalling?  

I am wondering whether an api can be exposed (maybe a small header and lib) so that a developer can integrate signalling, and maybe a config option to let Janus know to use external signalling.  Of course, the front end js will also have to be similarly have an exposed signalling api...but one thing at a time.  Just throwing out ideas.

Sorry for the long post, your thoughts are much appreciated!
 

Mirko Brankovic

unread,
Sep 10, 2017, 2:28:26 PM9/10/17
to meetecho-janus
In my humble knowledge, turn server is a relay server. I have seen and worked with other types of relay servers that are just blindly relaying traffic from a:b to c:d, but that is not a turn server since is not able to do discovery.
So when you have a proper turn server that is dtls capable, then your local peerconnection will add it as 'relay' candidate.


Lorenzo Miniero

unread,
Sep 11, 2017, 5:31:39 AM9/11/17
to meetecho-janus
Il giorno domenica 10 settembre 2017 18:48:26 UTC+2, V Venkatesh ha scritto:


On Sunday, September 10, 2017 at 5:54:41 AM UTC-4, Lorenzo Miniero wrote:
Il giorno sabato 9 settembre 2017 22:13:32 UTC+2, V Venkatesh ha scritto:
Is there a way to put the Janus gateway behind a NAT without any port forwarding or other configuration on the firewall?  There are a couple of topics in this forum that talk about NAT/ISP/firewall, but none of the posts offer a good clarification, other than reiterating that Janus is not recommended to be behind a NAT.  This is confusing, because WebRTC/ICE is supposed to provide p2p connectivity across NAT (except in symmetric NATs - lets ignore that case for this topic)



Of course it works. A server behind a NAT is always suboptimal, though, as being on a public and reachable address makes it much easier to eventually succeed, especially in edge cases. If Janus is behind a NAT too, it will also have to take care of STUN etc., which if you can avoid it's better.


Please bear with me as this reply is a bit long. We are somewhat in agreement.  Yes, agree with you about a publicly available address.  However, respectfully disagree about the NAT comment - once the ICE negotiation has concluded and a p2p direct path is found, performance  can be just as good as a publicly available service.  Of course, as you suggest, there are edge cases where no pathway is found and a TURN server relay needs to be used, but lets put this edge case aside for the moment.  



Yep, I agree that functionally it's the same once it works (except if TURN is involved, of course). Still, it's better if you can skip that part. Servers are also meant to make the setup easier in the first place, especially in some edge cases, which is why when possible a direct reachability is always preferred. Consider that, while we can handle trickle candidates from clients, Janus itself doesn't trickle, and so when it needs to do STUN to traverse a NAT, you're delaying the setup for each PeerConnection (we need to have all candidates to return an SDP).





Signalling has nothing to do with WebRTC, it's explicitly out of scope. It definitely has nothing to do with ICE/STUN/TURN at all, as that only applies to the media you negotiate.
Making signalling work behind a NAT, via proxying, reverse something, wrapping of the API with something you build is up to you.


Again, respectfully disagree, WebRTC (i.e. ICE for all intents and purposes) needs signalling when NATs are involved, but leaves the signalling implementation up to the developer.  WebRTC wraps around ICE, which uses STUN and TURN to find a pathway between two nodes. 



Yep, we agree. My point is that STUN/TURN cannot help with signalling, they only help with media. Our HTTP and WebSockets transports work as all HTTP and WebSockets servers do: they're TCP servers, and so if they're behind a NAT you have to take care of them somehow else (implementing some sort of proxy or other mechanisms to make them reachable from the outside). This is orthogonal to Janus, and not really relevant to Janus itself.
 

My understanding -  is that for ICE to find a p2p pathway between parties Alice and Bob, this is the workflow - :
 (a)  Alice and Bob determine a set of "local candidates" using a publicly available STUN server.  Simplified, a "candidate" is a combo of IP address and port.
 (b) Alice must send to Bob her candidates.  To Bob, Alice's candidates are Bob's "remote candidates"
 (c) Bob does the same thing - send Alice his candidates (Alice's remote candidates)
 (e) ICE initiates negotiation once all candidates have been exchanged.  ICE then determines at least one local and remote candidate pair that can be used to establish the p2p connection.  If not, the TURN relay is a fallback. 

If both Alice and Bob are behind NATs whose firewall config cannot be touched, then the only way to do (b) and (c) above is to use an external publicly available relay - and not the TURN server  - "signalling" in ICE.  So a method to hook this external signalling channel is the missing tweak in Janus. 


Since Janus uses libnice, so I took a peek there and then at the Janus code:  

 - First, this post seems to confirm that you need a 3rd party custom relay when NATs are involved. https://lists.freedesktop.org/archives/nice/2012-January/000495.html
"libnice does not provide any serialization method, you will still always need a
third party server to do the candidate exchange and that will depend on the
protocol used by this server, could be XMPP, could be SIP, could be custom, it
really all depends on what your needs are and what the server supports/accepts."


// ... Send local candidates to the peer and set the peer's remote candidates
 nice_agent_set_remote_candidates (agent, stream_id, 1, rcands);

And it does appear that janus.c processes incoming messages and setting of remote candidates in janus_process_incoming_request()  so maybe that's a good place to hook in signalling?  

I am wondering whether an api can be exposed (maybe a small header and lib) so that a developer can integrate signalling, and maybe a config option to let Janus know to use external signalling.  Of course, the front end js will also have to be similarly have an exposed signalling api...but one thing at a time.  Just throwing out ideas.

Sorry for the long post, your thoughts are much appreciated!
 


I think the confusion comes from a misunderstanding on a key concent: Janus is a server, not a client or a generic endpoint. It acts as a signalling server for most transports, so none of those methods apply (libnice is only useful for media anyway). If you want to turn it into a client, you'll have to be creative with the available transports: e.g., a companion helper application, colocated with Janus, that acts as a WebSockets client to connect somewhere (probably with a custom API), and bridges communication with the server in Janus instead. Again, orthogonal to Janus IMHO, and not relevant to Janus itself.

L.

Lorenzo Miniero

unread,
Sep 11, 2017, 5:32:58 AM9/11/17
to meetecho-janus
That said, the transports mechanism is modular. This means you can implement your own transport plugin, and Janus will accept it. You're free to implement whatever transport you want there, if you'd like it to do some traversal by itself.

L.

V Venkatesh

unread,
Sep 11, 2017, 11:21:57 AM9/11/17
to meetecho-janus
(some original posts material removed, getting too crowded) 


On Monday, September 11, 2017 at 5:32:58 AM UTC-4, Lorenzo Miniero wrote:
That said, the transports mechanism is modular. This means you can implement your own transport plugin, and Janus will accept it. You're free to implement whatever transport you want there, if you'd like it to do some traversal by itself.


Interesting, ok, that's great and might work, where in the code would I start on that?

As you point out, Janus does not trickle (libnice limitation?), which could affect latency, which in turn makes the argument for a publicly available server stronger.  Unfortunately, in my case, I am compelled to put Janus on a PI behind a NAT I don't control, so I'll have to explore being creative in turning it into an endpoint.  :-)  Maybe Janus can be front-ended by a custom bridge as you suggest.  NAT<--ICE-->nginx-->Janus? 

Thanks for the good discussion and detailed replies.   

Lorenzo Miniero

unread,
Sep 11, 2017, 11:31:57 AM9/11/17
to meetecho-janus
Il giorno lunedì 11 settembre 2017 17:21:57 UTC+2, V Venkatesh ha scritto:
(some original posts material removed, getting too crowded) 

On Monday, September 11, 2017 at 5:32:58 AM UTC-4, Lorenzo Miniero wrote:
That said, the transports mechanism is modular. This means you can implement your own transport plugin, and Janus will accept it. You're free to implement whatever transport you want there, if you'd like it to do some traversal by itself.


Interesting, ok, that's great and might work, where in the code would I start on that?



The first step would be studying the Transport API, to see which methods you need to implement, which callbacks the core exposes, and so on:

Studying the existing transport plugins (HTTP, WebSockets, RabbitMQ, UnixSockets, MQTT) might give you a clearer idea about how they interact with the core to handle the Janus API and/or Admin API bridging.

 
As you point out, Janus does not trickle (libnice limitation?), which could affect latency, which in turn makes the argument for a publicly available server stronger.  Unfortunately, in my case, I am compelled to put Janus on a PI behind a NAT I don't control, so I'll have to explore being creative in turning it into an endpoint.  :-)  Maybe Janus can be front-ended by a custom bridge as you suggest.  NAT<--ICE-->nginx-->Janus? 



It's not a libnice limitation, we didn't implement it. We might do that in the future, but no short term plan right now (we have other priorities), as in general Janus never collects too many candidates by itself (in most cases it will be host only).

A custom bridge would probably be an easier solution than trying to implement your own custom plugin, as it would give you more freedom on the technologies (language, protocols, custom API to expose, etc.) and you could re-use whatever Janus already provides you with. You can find a list of projects you may want to leverage for the purpose here: https://janus.conf.meetecho.com/docs/resources

L.

V Venkatesh

unread,
Sep 13, 2017, 7:55:54 AM9/13/17
to meetecho-janus
Thanks Lorenzo, appreciate the pointers!  
Reply all
Reply to author
Forward
0 new messages