[asterisk-dev] IAX native bridge and NAT

Tim Davies tim at opensystems.net.au
Fri Jun 16 02:58:13 MST 2006


Hi all,

After posting a patch to Mantis for this, and then deciding it was a
poor solution, I thought getting some feedback might be a good idea. 
And yes, it's a long one!

What I am trying to do is make the IAX2 protocol better at native
bridging a call when there is address translation somewhere along the
path between the two endpoints.

At the moment (and correct me if I am wrong), the addresses of the
endpoints (call them A and B) are sent to the other endpoint by the
intermediate server (call it C) via the TXREQ packet.  A and B then try
to send a TXCNT to each other, and expect to see a TXACC reply.  If
received, they send a TXREADY back to C.  On seeing both TXREADYs, C
will then send a TXREL to A and B.

The situations where I have seen this fail are:

a) When C sees an internal address of A, and sends this to B in the
TXREQ.  B clearly cannot send the TXCNT to A.
b) When A is behind NAT and C sees the real address.  C sends the
correct address to B, but A's NAT will not pass the packets from B through.
c) A finds one path to B and back, and B finds a different path to A and
back.  I managed to do this in a contrived situation.  A and B had
multiple IP addresses.

The protocol requires a bidirectional connection is established FROM
BOTH ENDS, and relies on the fact that they will discover the same IP
address/port pair.  In fact, only a single bidirectional path needs to
be found.

So I played around with:

- always sending the TXACC to where the TXCNT came from, and then either
- resending TXCNTs back to the address that TXCNTs were received from
(if it different from the original address given in the TXREQ), or
- sending an additional TXACC back to where a TXACC came from, in case
the TXCNT never made it.  A kind of 3-way handshake.

These either break backwards compatibility, or cause a problem with
cancelling the TXREJ timeout, or one end still isn't guaranteed to know
where to transfer to.

The way I thought of making a robust transfer happen is:

- Send the TXREQs as per normal.
- Send the TXCNT to the address given in the TXREQ
- When a TXCNT is received, put the address/port it was received from
into the TXACC reply. Send the TXACC back to this address/port.
- When the TXACC is received, collect the address the other host
received the TXCNT from, add the address the TXACC was received from,
and send this in the TXREADY packet back to C.
- When a *single* TXREADY is received by C, the transfer can occur.
Collect the two addresses, and send them in the relevant TXREL packets. 
Ignore any subsequent TXREADYs.
- On receipt of the TXREL, use this address to transfer the call. And
cancel pending TXCNTs, so we don't get a TXREJ.

Now this will break backwards compatibility for sure, unless we can get
around it by examining the packet payloads, or maybe defining new packet
types?

Thoughts anyone?





More information about the asterisk-dev mailing list