gortc / gortcd

Fast TURN and STUN server: cross-platform, hot reload, flexible config

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to find Peer Transport Address through Client related Transport Address

songjiayang opened this issue · comments

As we known, client create a Permission need the peer's transport address (Server-Reflexive), but I want to known the peer transport address is for which port in TURN server ?

If it is the default 3478. As code allocator.go#L130 , it should not have ability to send data to peer through the relayed transport address for Symmetric NAT.

If it is the client relayed transport address port, how can we get peer's server-reflexive transport address for this relayed port , HandlePeerData no about this logic.

Maybe there is something I misunderstand, let me known please.

Let's sync in our view of TURN Process.
We have 3 entities:

  1. TURN Server (S): gortcd listening on public IP
  2. TURN Client (C): somebody behind NAT that wants to have public IP
  3. Peer (P): somebody behind NAT that wants to talk with C

The process is like follows:

  1. C goes to S and asks for IP:PORT
  2. S allocates IP:PORT. It is called RELAYED ADDRESS. All data received on that address will be sent back to C. Also, C can use TURN to send data from that address to allowed peers.
  3. Now, C sends to P its RELAYED ADDRESS via some signaling
  4. P sends data to RELAYED ADDRESS, and S is relaying data to C.

On allocator.go#L130 we are on step 4.

I think I got what you are talking about. Please see allocation.go#L51, the Allocation struct is basically a TURN Allocation that is created on step 2.
It has a RelayedAddr which is allocated transport address for client.
Also, if you take a look on Allocation.ReadUntilClosed, you can see HandlePeerData call.

Feel free to ask more questions on this topic if it is not 100% clear.

Thanks for your reply.

My question is that for TURN's different port watched the Peer P's address is different if the P is behind Symmetric NAT. If the Peer P 's address is for the TURN default port watched, step 3 will fail.

@ernado, thanks for your explanation, but it's still not clear to me, let me explain it in detail as the following.
C needs to know P's reflexive transport address (a binding from NAT allocation between P and S) in the following two cases:
a. P's reflexive transport address is required for C Send data to S,Please see

if err := ctx.request.Parse(&data, &addr); err != nil {

b. P's reflexive transport address is required when C invoke createPermission of S, Please refer:

Please note that P's reflexive transport address is variety In Symmetric NAT case, NAT definition:https://tools.ietf.org/html/rfc3489#page-5, let assume that Pa is P's transport address between P and S , Pb is P's transport address between P and signal server, Pa is not equal with Pb in Symmetric NAT environment. C needs to know Pa for steps #a and #b in order to fulfill the whole traffic relay, but I can't get how it resolved both from source code and your explanation.

Any help will be appreciated.
Thanks in advance.

@songjiayang you are right, if P and C are both behind symmetric NAT, both need an TURN allocation for connectivity establishment.

@henryZhangDev
Yes, P should explicitly obtain it's server-reflexive address via STUN and send it to C, if P is behind NAT. However, it will not work if NAT is symmetric.

but I can't get how it resolved both from source code and your explanation

I think that case can't be resolved without TURN allocation for P.

The only automatic way to do it is ICE, which is still in WIP for gortc project.

UPD: Feel free to ask further if something is not clear, it is pretty complicated topic and sometimes my wording can be not ideal.

@ernado I find a way for this case, can we add a BindRequest handler in C 's HandlePeerData, if it's a BindRequest, just response the P 's server-reflexive address rather than sending data to C.

I think that we can't do this because we should comply to TURN specification.
Actually it looks like a job for signaling server and is already handled by ICE, TURN server is not designed to solve all connectivity problems.

I'm not sure, maybe https://github.com/coturn/coturn is doing something like that.
If yes, I will add that feature.

I'm just trying to be as close to spec as possible and keep everything simple.

@ernado, thanks for your quick reply, really appreciated!
I go through ICE spec:https://tools.ietf.org/html/rfc5245, I think it mainly focus on selecting the best connectivity and would not help in this case.
and I agree with you that the TURN spec should be followed strictly, and process BindRequest in HandlerPeerData seemly breaks the rule.
I think the best way is P send BindRequest to S, and gets P's reflexive transport address between P and S, then send it through signaling server, since P has STUN client capability(implements STUN BindRequest).
We can solve it without break spec in such way, what do you think?

I think it mainly focus on selecting the best connectivity and would not help in this case.

It will eventually make both P and C attempt to reach each other via server-reflexive addresses, so it should help in this case.

I think the best way is P send BindRequest to S, and gets P's reflexive transport address between P and S, then send it through signaling server, since P has STUN client capability.

Yes, S is both STUN and TURN server, so it can respond P with P' address. And actually I think this will happen eventually if ICE is used.

Diagram

To make Cr allocation with permission for P’, C should know about P1’=NAT1(S1, P).
If NAT1 is symmetric, P2’ != P1’, because S1 and S2 differ.

Yes, it would work if ICE implements such behavior(I don't think the ICE spec point it out explicitly, correct me if I am wrong ), is there any ICE implementation related to this repository which makes it as whole fully traversal solution? another concern is that P1’ should be sent to C which will increase setup time, do you have any performance data?
Thanks in advance.

There is WIP ICE implementation, but it is not ready: https://github.com/gortc/ice

The pion project is pretty similar to gortc, but is already usable, so you can try it instead: https://github.com/pion/webrtc

@ernado I read the pion/webrtc source code, think it doesn't work for symmetric NAT, because it's TURN is released followed the RFC.

They are using ICE too, so it should work.
The ICE candidate with server reflexive address will be generated and paired with relayed candidate.

I basically figured out the ICE logic, let's see this diagram:

Screen Shot 2019-05-16 at 9 42 57 AM

Does it mean that in ICE the caller and callee send data through the other's related address and get data fromturn public address ?

I find another problem for gortcd, with rfc5766 discription, the Permission only include the IP address and lifetime rather than port, but in gortcd included, related code is allocator/allocation.go#L26 , addr.go#L9.

Thank you @songjiayang, we should ignore port while processing permissions.
That problem will be resolved in #34

Regarding your question about ICE: if they both are using TURN, they will interact only with TURN server.

Related:
https://tools.ietf.org/html/rfc5766#section-10.3