Extending functionality of SIPc with STUN/TURN/ICE

Wookyun Kho
Columbia Univercity
New York, NY 10026
USA
wk2153@columbia.edu

 

Contents


¡¤  Abstract
¡¤  Overview
¡¤  Related work
¡¤  Background
¡¤  Implementation details
¡¤  Tests
¡¤  References
¡¤  SIPc's bug list
¡¤  Future work
¡¤  Miscellaneous

Abstract


The current version of SIPc cannot traverse a NAT whose mapping is address and port-dependent (symmetric). To make SIPc work with address and port-dependent NAT, it needs to use a relay server. My work was to implement a STUN/TURN/ICE based on the recent IETF BEHAVE working group's drafts [2, 3, 4] and integrating it with SIPc. With STUN/TURN/ICE, SIPc can use a relay server (TURN server) to relay media stream to communicate with other clients. So, now SIPc can potentially traverse any kind of NAT.

 

Overview


My project was to implement STUN/TURN/ICE and integrating it with SIPc. STUN is used for obtaining external IP address. ICE uses STUN and TURN to find an appropriate external IP address for media data transmission.

    

As Figure 1 shows, when both clients are behind address and port-dependent NAT, media goes through a relay server(TURN server). If there is no STUN/TURN/ICE, media packets will be dropped by the NAT.

 

Related Work


 - IETF BEHAVE working group's STUN/TURN/ICE
 - STUN/TURN/ICE implemented voip telephony program: xten (http:://www.xten.com)
 - Original STUN module of SIPc was built by Kundan. In the recent STUN related drafts, the terminologies for NAT mapping have been changed and more functionality has been added. Therefore, I updated the original STUN module and added TURN functionalities. Also, I made ICE module in SIPc, and implemented STUN/TURN server.
 (STUN server is originally embedded in a STUN module, but I split stun server from SIPc.)

Background


¡¤  NAT mapping

 1. Endpoint-Independent Mapping:

The NAT reuses the port mapping for subsequent packets sent from the same internal IP address and port (X:x) to any external IP address and port. Specifically, X1':x1' equals X2':x2' for all values of Y2:y2.

 2. Address-Dependent Mapping:

The NAT reuses the port mapping for subsequent packets sent from the same internal IP address and port (X:x) to the same external IP address, regardless of the external port. Specifically, X1':x1' equals X2':x2' if and only if, Y2 equals Y1.

 3. Address and Port-Dependent Mapping:

The NAT reuses the port mapping for subsequent packets sent from the same internal IP address and port (X:x) to the same external IP address and port while the mapping is still active. Specifically, X1':x1' equals X2':x2' if and only if, Y2:y2 equals Y1:y1.

 4. Simple Traversal Underneath Network Address Translators (STUN)

STUN is a lightweight protocol that serves as a tool for application protocols in dealing with NAT traversal. It allows a client to determine the IP address and port allocated to them by a NAT and to keep NAT bindings open.

¡¤  Traversal Using Relay NAT (TURN)

TURN is a usage of the Simple Traversal of UDP Underneath NAT (STUN) Protocol for asking the STUN server to relay packets towards a client. This is useful for clients behind NATs whose mapping behavior is address and port dependent.

¡¤  Interactive Connectivity Establishment (ICE)

ICE is a protocol for Network Address Translator (NAT) traversal for multimedia session signaling protocols based on the offer/answer model, such as the Session Initiation Protocol (SIP). ICE makes use of the Simple Traversal of UDP Underneath NAT (STUN) protocol, applying its binding discovery and relay usages, in addition to define a new usage for checking connectivity between peers.

 

Implementation Details


 - I implemented the functional portions on STUN/TURN/ICE drafts as much as I could. Following features were not implemented. : 1) Security 2) Server Resource Related Attributes
- A list of attributes implemented and left is given in here. A detailed description of them is given in STUN[2]/TURN[3]/ICE[4] drafts.

¡¤  Integration with SIPc

  Modified Files

   1. sipc/controller.tcl
   2. sipc/controller_invite.tcl
   3. sipc/sdp.tcl
   4. sipc/sipstack/stun.tcl
   5.
addressbook_callarrive.tcl : main is modified
   6. sipc/stun/stun.tcl

  Added Files

   1. sipc/stun/ice.tcl
   2.
stun_server.tcl

  Update Details

   1. sipc/controller.tcl
   - In Controller::call, in case of the first call, SIPc needs to put
¡°candidates¡± information into INVITE message. To do that, I added code to get address candidates information by calling a function in ice.tcl.
   - In Controller::call, right before SIPc sends INVITE message to proxy server, I appended
¡°a¡± attributes which have ¡°candidates¡± information to the end of SDP message.

   2. sipc/controller_invite.tcl
   - In Controller::inviteAccept, append
¡°candidates¡± information to 200 OK message. Since SIPc doesn¡¯t support 183 message (in ICE tutorial, Rosenberg recommended to use 183 message to send ¡°candidates¡± information, but SIPc doesn¡¯t support 183 message, so I just appended it to 200 OK message)
   - In Controller::inviteAccept, right after SIPc sends 200 OK message, both end clients start connectivity check. At this point, callee is waiting for a STUN
¡°Binding Request¡± message. This is handled by calling ICE::listen.
   - In Controller::inviteResponseHandle, as soon as a caller receives 200 OK message from a callee, the caller parses the SDP, gets
¡°candidates¡± information of the callee, and starts connectivity check process. This is handled by calling ICE::chkConns.
   - In Controller::startMedia, if connectivity check succeeds, in ICE::chkConns, array ICE::selIP and ICE::selPort will be set like ICE::selIP(<media type name>). Thus, in startMedia, if these are set correctly, rhost and rport will be set by ICE::selIP and ICE::selPort.
   - During the project, I used sip.antisip.com sip proxy server. However, this proxy server was not a usual sip proxy server. It changes a part of the SIP message such as contact header and (m) attributes, so it tried to act like a relay server. Because of that, right before sipc starts ratmedia, I forced sipc to use default voice media port. If we can find or implement sip proxy server which implements rport option correctly, we don't have to force SIPc to use the default voice media port number. (The code for forcing SIPc to use the default port number is "set lport $Media::a_mediainit($type,port)" in Controller::startMedia. You can remove this line after you find a correctly working server.)

   3. sipc/sdp.tcl
   - In SP::parse, I added some codes to parse
¡°candidate¡± attributes. This candidate information will be stored in ICE::peerlist.
   - I made another function named SDP::encodeICECANDS to encode candidates information.

   4. sipc/sipstack/stun.tcl
   - According to new characteristics of stun, most of codes are little bit changed. (e.g. there is no more NAT mapping type checking)

   5. addressbook_callarrive.tcl
   - Since the original SDP message didn't have (a) attributes for candidates information, these (a) attributes cause some problem in this process. So, I added some codes to remove these (a) attribues from sdp message.
   - Since sipc already parsed candidates information from sdp message, it's fine to remove them.

   6. sipc/stun/stun.tcl (TURN implementation)
   - Following things are added based on the latest STUN/TURN drafts.
   - New Messaqe Handle
    1) Allocate Request (Section 9.1 [3])
    2) Set Active Destination (Section 9.2 [3])
    3) Send Indication (Section 9.5 [3])
    4) Data Indication (Section 9.6 [3])

   7. sipc/stun/ice.tcl
   - All ICE functionalities are implemented in this file.
   1) getCandidates
   Return candidates list and save this information in ICE::mylist.
   2) chkConns
   This module is for connectivity check and is used by Caller(or active client). After sipc receives a 200 OK message, it starts ICE::chkConns module to do connectivity check. This module makes connectivity check list with candidate list of the node and other call peer and sends a Binding Request message to the address specified in the check list. If there is a Binding Response, it stops and starts media.
   3) listen
   This module is also for connectivity check and is used by Callee(or passive client). After sipc receives ACK message, it starts listen module until it receives Binding Request message from caller(or active client). If sipc receives Binding Request message, it sends back Binding Response message, and starts to run media.

   8. STUN and TURN server
   - This is served as STUN/TURN server.
   - When both clients are behind address and port dependent NAT, this server will be served as relay server.
   - Because ratmedia is using random port number for sending media, STUN server is temporarily set as checking incoming messages only by ip address.
   - If ratmedia works correctly, it should check with both IP address and Port number since it would be possible there are more than 1 clients behind a NAT. (usually more than 1)

 

¡¤  List of Fully/Partially Implemented Requests and Attributes of STUN/TURN/ICE

1) STUN - Binding Request, MAPPED-ADDRESS, XOR-MAPPED-ADDRESS, ERROR-CODE

2) TURN - LIFETIME, REMOTE-ADDRESS, DATA, RELAY-ADDRESS

3) ICE - Gathering Candidates, Prioritization, Encoding in SDP, Connectivity Check

¡¤  List of Unimplemented Requestes and Attributes of STUN/TURN/ICE

1) STUN -
USERNAME, PASSWORD, MESSAGE-INTEGRITY, FINGERPRINT, REALM, NONCE, SERVER, ALTERNATE-SERVER, REFRESH-INTERVAL

2) TURN -
Connect Request, BANDWIDTH, REQUESTED-PORT-PROPS, REQUESTED-TRANSPORT, REQUESTED-IP, TIMER-VAL

3) ICE -
Frozen Algorithm

 

Tests


¡¤  Test Case

1. Both clients are behind Port dependent NAT

   
2. Both Clients are behind End point independent NAT

   
3. One client is behind Port dependent NAT, and another one is on public side

   

      - For each of them, test call establishment

 

References



[1] Network Address Translation (NAT) Behavioral Requirements for Unicast UDP (RFC 4787)

[2] Simple Traversal Underneath Network Address Translators (NAT) (STUN)

[3] Obtaining Relay Addresses from Simple Traversal Underneath NAT (STUN)

[4] Interactive Connectivity Establishment (ICE): A Methodology for Network Address Translator (NAT) Traversal for Offer/Answer Protocols


Future Work



- Debug ratmedia, then we can use my stun server with more than 1 clients behind a same NAT at the same time. Since the current version of ratmedia is using random port number for sending media stream, it's not possible for STUN/TURN server to know from where the incoming media comes. After debugging ratmedia, remove line 382 (set index [lsearch $STUN::conns UDP:$mappedip*]) and uncomment line 385 in stun_server.tcl.

- Implement rport option of conductor sip proxy server, then we can get rid of the code that I put in Controller::invite to force SIPc to use a default media port.

 

SIPc's Bug List



- Sip proxy server, conductor.cs.columbia.edu, doesn't implement rport option. : I thought that conductor should implement rport option. Because of that, it took quite much time figure out what the problem is. After I figured out what the problem was, I reported this to Jongyul, and tried to find another sip proxy server which implements rport option. I've tried several proxy servers, but most of them didn't implement rport option. Finally, I found sip.antisip.com, and it implements rport option correctly.

- When both clients are behind Address and Port dependent NAT, SIPc needs relay server to transmit media data each other. For that, before SIPc starts to send media packets through relay server, SIPc's external ip and port number for media should be registered in relay server. However, ratmedia, SIPc's media application, is using random port for sending data. Because of that, relay server couldn't recognize incoming message from SIPc as a data to be relayed, so I temporarily set stun server to use only ip address to recognize incoming message. I reported this problem to Xiaotao, and Salman.

- The sip proxy server(sip.antisip.com) is not an usual sip proxy server. Usually, sip proxy server must not change contact header or (m) attributes of sdp message, but sip.antisip.com proxy server does. Actually, sip.antisip.com is trying to act like relay server, so it allocates port number to client, and it puts its ip address and this allocated port number in sdp. Because of that, I added a line in Controller::invite to force SIPc use its default media port instead of the port which is specified in INVITE message. If we fix sipd to support rport option, we can remove this line.

- When SIPc tried to send INVITE message through sip.antisip.com, sip.antisip.com sent back 401 error message, but SIPc didn't have 401 handling process. So, I reported this to Xiatao Wu, the main author of SIPc, and he fixed that problem.

- When p2p-sipc is behind any NAT, it cannot register itself in open DHT. : My module cannot work with p2p-sipc. I reported this to Kundan.

 

Miscellaneous


¡¤  How to Configure NAT?
- You can configure some kinds of NAT by using iptables, but it's not enough for address and port dependent NAT. To configure address and port dependent NAT, you might need to make a small program.

1. Port dependent NAT
- iptables -t nat -A POSTROUTING -p udp -j SNAT -s <localip> --to <NAT box IP>
(ex) iptables -t nat -A POSTROUTING -p udp -j SNAT -s 10.0.1.0/24 --to 128.59.23.62
2. End point independent NAT
- Add one more command to port dependent NAT
- iptables -t nat -A PREROUTING -p udp -j DNAT -s <NAT bod IP> --to <localip>
(ex) iptables -t nat -A PREROUTING -p udp -j DNAT -s 128.59.23.62 --to 10.0.1.10

¡¤  Installing STUN/TURN server
- Install Tcl and Tcl udp extension.
=> Get Tcl installation file : http://www.activestate.com/Products/ActiveTcl/
=> Get Tcl udp extention installation file : http://tcludp.sourceforge.net/


- With "show" command, you can see current connection list. (2 line information per every connection)
 <internal tuple> <external tuple>
 <allocated ip-addr> <allocated port> <socket> <remaining life time - msec>

- Internal/External tuple is like below:
 <protocol>:<ipaddr1>:<port1>:<ipaddr2>:<port2>

Ex) UDP:128.59.23.59:5060:128.59.19.182:3478 UDP:128.59.19.182:43286:128.59.23.62:5060
    128.59.19.182 43286 sock1245 10840