Kamailio Security

Security is Critical for a VoIP platform as it is susceptible to hacks , misuse , eavesdropping or just sheer misuse of the system by making robotic flood calls . Kamailio SIP Server provides some key features to meet these challenges which will be discussed in this blog .

Sanity checks for incoming SIP requests

Being a gateway on the VOIP system permiter is a challenging task due to the security threast it posses. It is must to configure per request initial checks for all incoming SIP request. This ideally should be the first step in routing clock before any other processing.

Exmaple programs https://github.com/altanai/kamailioexamples/blob/2039639275a33a2ba2435ae0b781e6f9dd51220e/Barebone_SIPServer/kamailio.cfg

request_route {
    route(REQINIT);
    ... 
    // proceed with routing 
}

Pointers for functionality

For replies coming from local users , usually behind NAT , do not open a new TCP connection on each reply

set_reply_no_connect();

For indialog requests also close connection after forwarding the request.

if(has_totag()) {
    set_forward_no_connect();
}

Check if any IP is flooding the server with messages and block for some time ( ANTI-FLOOD and pike decsribed later in the article ).
Ofcourse exclude self IP . sample to do blocking using hastable’s psedi variable ipban

if(src_ip!=myself) {
    if (!pike_check_req()) {
        $sht(ipban=>$si) = 1;
        exit;
    }
}

Friendly-scanners are type of botnets probing and scanning known IP ranges(5060,5061..) for SIP server, softswitches, cloud PBX. Once they detect a suitably open server they use brute force tactic to send all commonly/default username/passwords accounts. The prime purpose is to extract all vulenrable accounts for creating fradulent calls such as crating DOS attacks using high tarffic and consuming all bandwidth from good calls, free internation calls or imposter/scam calls.

Among some obvious ways to block the flood of packets by these scanner are

  • imply strict firewalls rules for allowing only known client IP’s
  • changing default SIP port from 5060 to some other non standard port in network
  • checking User agent for known attackes such as (sipcli , sipvicious , sip-scan , sipsak , sundayddr , friendly-scanner , iWar , CSipSimple , SIVuS , Gulp , sipv , smap , friendly-request , VaxIPUserAgent , VaxSIPUserAgent , siparmyknife , Test Agent)
if($ua =~ "friendly-scanner|sipcli|sipvicious|VaxSIPUserAgent") {
    exit;
}
  • track unsuccesfull quick/consecutive attempts from an IP and block its access temporatliy or permamntly. Such as failing to REGISTER / autehticate for 3 consecutive time should block it .

Track if the message is hopping too many times within the server server , intra or inter networks not reaching the destination . mf_process_maxfwd_header(maxvalue). Note maxvalue is added is no Max-Forward header is found in the message.

mf_process_maxfwd_header(10)

Sanity is a complete module by itself to perform various checks and validation such as

  • ruri sip version – (1) – checks if the SIP version in the request URI is supported, currently only 2.0
  • ruri scheme – (2) – checks if the URI scheme of the request URI is supported (sip[s]|tel[s])
  • required headers – (4) -checks if the minimum set of required headers to, from, cseq, callid and via is present in the request
  • via sip version – (8) – disabled
  • via protocol – (16) – disabled
  • Cseq method – (32) – checks if the method from the Cseq header is equal to the request method
  • Cseq value – (64) – checks if the number in the Cseq header is a valid unsigned integer
  • content length – (128) – checks if the size of the body matches with the value from the content length header
  • expires value – (256) – checks if the value of the expires header is a valid unsigned integer
  • proxy require – (512) – checks if all items of the proxy require header are present in the list of the extensions from the module parameter proxy_require.
  • parse uri’s – (1024) – checks if the specified URIs are present and parseable by the Kamailio parsers
  • digest credentials (2048) – Check all instances of digest credentials in a message
  • duplicated To/From tags (4096) – checks for the presence of duplicated tags in To/From headers.
  • authorization header (8192) – checks if the Authorization is valid if the scheme in “digest” always returns success for other schemes.
    sample for URI checks for list of parsed URIs: Request URI (1), From URI (2) and To URI (4).

Full route[REQINIT] block

route[REQINIT] {

set_reply_no_connect();
if(has_totag()) {
    set_forward_no_connect();
}

if(src_ip!=myself) {
    if (!pike_check_req()) {
        $sht(ipban=>$si) = 1;
        exit;
    }
}

if($ua =~ "friendly-scanner|sipcli|sipvicious|VaxSIPUserAgent") {
    exit;
}

if (!mf_process_maxfwd_header("10")) {
    sl_send_reply("483","Too Many Hops");
    exit;
}

if(is_method("OPTIONS") && uri==myself && $rU==$null) {
    sl_send_reply("200","Keepalive");
    exit;
}

if(!sanity_check("17895", "7")) {
    xlog("Malformed SIP request from $si:$sp\n");
    exit;
}
}

Access Control Lists and Permissions

permission module handles ACL by storing permission rules in plaintext configuration files , hosts.allow and hosts.deby by tcpd.

#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
...
# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif
..
#!ifdef WITH_IPAUTH
    if((!is_method("REGISTER")) && allow_source_address()) {
        # source IP allowed
        return;
    }
#!endif

sample programs to check for allowed access in LUA programing o Kamailio along when acting as registrar – https://github.com/altanai/kamailioexamples/blob/master/Lua%20-%20kamailio%20Registrar%20permission%20auth/kamailio.cfg

Functions

Call Routing

if (allow_routing("rules.allow", "rules.deny")) {
    t_relay();
};

Registration permissions

if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        exit;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};

URI permissions

if (allow_uri("basename", "$rt")) {  // Check Refer-To URI
    t_relay();
};

Address permissions

// check if sourec ip/port is in group 1
if (!allow_address("1", "$si", "$sp")) {
    sl_send_reply("403", "Forbidden");
};

Trusted Requests

if (allow_trusted("$si", "$proto")) {
    t_relay();
};

checks protocols which could be one of the “any”, “udp, “tcp”, “tls”, “ws”, “wss” and “sctp”.

Hiding Topology Details

Stripping the SIP routing headers that show topology details involves steps such as hiding the local IP address of user agent , hiding path taken to reach the server , obscuring the core SIP server’s ip and details etc . Some headers which giave away information are

  • top most Via header
  • contact address
  • Record-Route headers
  • sometimes the Call-ID header

This goes a long way in helping to keep the inner network topology secure from malacious exploiters, expecially to protect IP of the PSTN gateways which could let to an costly mess or gensrally from attackers and reverse engineering.

Topoh module hides the network topology by removing the internal IP addresa and instead add ing them in encrypted form the same sip packet. Diff server using the same shared secret key can encode decode the encrypted addresses.

This way it doesnt not even have to store the state of the call and is transpoarent to all call routing logic

sample program for kamailio sip server to provide topology hiding – https://github.com/altanai/kamailioexamples/tree/abcc7b06c00fee12252133614187b0451757fcf2/Topology_hiding

loadmodule topoh.so

modparam("topoh", "mask_key", "somekey")
modparam("topoh", "mask_ip", "1.1.1.1")
modparam("topoh", "mask_callid", 1)

topoh module

Primarily it does these things
hide the addresses of PSTN gateways
protect your internal network topology
interconnection provider – to keep the details of connected parties secret to the other, to prevent a bypass of its service in the future

loadmodule topoh.so
modparam("topoh", "mask_key", "YouDoHaveToChangeThisKey")
modparam("topoh", "mask_ip", "10.0.0.1")
modparam("topoh", "mask_callid", 1)

Params

mask_key (str)
mask_ip (str)
mask_callid (integer)
uparam_name (str)
uparam_prefix (str)
vparam_name (str)
vparam_prefix (str)
callid_prefix (str)
sanity_checks (integer)
uri_prefix_checks (integer)
event_callback (str)

Primarily tis module uses mask key to code the trimmed via header information and insert them into pre specified param names with prefixes. Hence it can work with stageful or stateless proxy and can also work if server is restarted in between

topos module

Offers topology hiding by stripping the SIP routing headers that show topology details.

It requires 2 modules rr module since server must perform record routing to ensure in-dialog requests are encoded/decoded and database module to store the data for topology stripping and restoring.

Params :
storage (str) – could be redis or database backend

modparam("topos", "storage", "redis")

db_url (str)

modparam("topos", "db_url", "dbdriver://username:password@dbhost/dbname") 
modparam("topos", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio”

mask_callid (int) – Whether to replace or not the Call-ID with another unique id generated by Kamailio. ( present with topoh)
sanity_checks (int) – with sanity module to perform checks before encoding /decoding
branch_expire (int)
dialog_expire (int)
clean_interval (int)
event_callback (str) – callback event

modparam("topos", "event_callback", "ksr_topos_event")
..
function ksr_topos_event(evname)
 KSR.info("===== topos module triggered event: " .. evname .. "\n");
 return 1;
end

event route :
event_route[topos:msg-outgoing]

loadmodule "topos.so"
loadmodule "topos_redis.so"

//topos params 
modparam("topos", "storage", "redis")
//branch_expire is 10 min
modparam("topos", "branch_expire", 10800)
// dialog_expire is 1 day
modparam("topos", "dialog_expire", 10800)
modparam("topos", "sanity_checks", 1)

FireWall

To save from the automatic port scans that attackers carry out to hack into the system use the script below

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:CHECK_TCP - [0:0]
:ICMP - [0:0]
:PRIVATE - [0:0]
:PSD - [0:0]
:SERVICES - [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -i eth0 -p ipv6 -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -j SERVICES 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
-A CHECK_TCP -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,ACK FIN -m state --state INVALID,NEW,RELATED -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags PSH,ACK PSH -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 64 -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 128 -j DROP 
-A ICMP -p icmp -m icmp --icmp-type 11/1 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 11/0 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 3 -m limit --limit 10/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 8 -m limit --limit 10/sec --limit-burst 10 -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -j DROP 
-A PRIVATE -d 192.168.0.0/16 -j DROP 
-A PRIVATE -d 172.16.0.0/12 -j DROP 
-A PRIVATE -d 10.0.0.0/8 -j DROP 
-A PRIVATE -j RETURN 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j TARPIT  --reset 
-A PSD -p tcp -m statistic --mode random --probability 0.500000 -j TARPIT  --tarpit 
-A PSD -p udp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-host-unreachable  
-A SERVICES -p icmp -m state --state INVALID -j DROP 
-A SERVICES -p icmp -j ICMP 
-A SERVICES -p tcp -j CHECK_TCP 
-A SERVICES -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT 
-A SERVICES -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m tcp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5060 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5061 -m state --state NEW -j ACCEPT 
-A SERVICES -i eth0 -j PSD 
COMMIT

Update/Remove Server and User Agent Headers

Rewrite server header to save the exact version of server from hackers

server_header="Server: Simple Server"

or completely rmemove it from traces

server_signature=no

and

user_agent_header="User-Agent: My SIP Server"

Remove Server warnings from traces and log file

Warnings expose the vulnerabilities of system and it is best to remove them in production enviornment

user_agent_header="User-Agent: My SIP Server"

Anti Flood

During Auth or logging there is a fair chance of leaking credentials or the fact that users opt for weak password themselves compromising the system via bruteforcing username/password . Or attacker may be bruteforcing prefixes to understand config and routing logic
Random unnecessary flood of SIP requests can consume CPU and make it slow or unavailable for others as Denial of Service . These situations can be made less daunting via pike module

pike modules

tracks the number of SIP messages per source IP address, per period.

loadmodule "pike.so"

// pike params 
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 20)
modparam("pike", "remove_latency", 4)

//routing logic inclusion
route {
  if (!pike_check_req()) {
    xlog("L_ALERT","ALERT: pike block $rm from $fu (IP:$si:$sp)\n");
    exit;
  }
  ...
}

Pike module implementation in LUa on kamailio https://github.com/altanai/kamailioexamples/tree/ead84a684108600ad930027a3dcc6ab7442f139c/Lua%20-%20kamailio%20Registrar%20permission%20auth

Fail2Ban

can syslog files for specific messages based on regular expressions and act upon matching by banning IP addresses.

Traffic Monitoring and Detection

Secfilter module

offer an additional layer of security over our communications. It can perform

  • Blacklisting user agents, IP addresses, countries, domains and users.
  • Whitelisting user agents, IP addresses, countries, domains and users.
  • Blacklist of destinations where the called number is not allowed.
  • SQL injection attacks prevention.

Digest Authetication

Digest is a cryptographic function based on symmetrical encryption.

Sample kamailio exmaple with Auth https://github.com/altanai/kamailioexamples/blob/5fb6c6d0bb7416b3698e657612f016e70145a638/simple%20relay%20with%20flags/kamailio_relay_with_auth.cfg

Read more

tbd

SIPp UAC / UAS on TLS to generate traffic to check secruity of Kamailio SIP server

sipp is a powerful traffic generate for SIP applications and is widely used to test call flow routing applications in white box envrionmenet as well as stress or load testing. Read more about sipp https://telecom.altanai.com/2018/02/01/sipp/

General syntax is

sipp -sn uas -p 5060 -t l1 -tls_key key.pem  -tls_cert cert.pem  -i 127.0.0.1

More on compiling sipp from source to include ssl behavious and self generate certificates for tls can be read from https://github.com/altanai/kamailioexamples/tree/master/sipp

Ref :

NAT traversal using STUN and TURN


WebRTC : Web-based real-time communications is a gamechanger for real-time communication systems. WebRTC is one such open-source, royalty-free, unencumbered browser-based platform using the browser’s embedded media application programming interface (API). It allows developers to add custom JavaScript & HTML5 to control the media setup and flow. WebRTC has enabled developers to build apps, sites, widgets, plugins and extensions capable of delivering simultaneous audio, video, data, and screen-sharing capability in a peer to peer fashion.

Issues accross Networks : But something which escapes our attention is how media is traversing across the network. Of course, the webrtc sessions run smoothly when both the peers are on the open public internet without any restrictions or firewall blocks. But the real problem begins when one of the peers is behind a Corporate/Enterprise network or using a different Internet service provider with some security restrictions. In such a case the normal ICE capability of WebRTC is not sufficient to set up a bidirectional media streaming setup. For network restriction what is required is a NAT ( Network Address Traversal) mechanism that performs address discovery.

NAT and ICE Solution : STUN and TURN server protocols handle session initiations with handshakes between peers in different network environments. In the case of a firewall blocking a STUN peer-to-peer connection, the system fallback to a TURN server which provides the necessary traversing mechanism through the NAT.

Lets study from the start ie ICE.

NAT

Network Address Translation provides a mapping of internal to external IP addresses. This helps in network address modification for packets which in transit accross a tarfic routinig node such as inter networks.

A private address on the inside of the NAT is mapped to an external public address. Port address translation (PAT) resolves conflicts that arise when multiple hosts happen to use the same source port number to establish different external connections at the same time.

Some ways to acheive this

  • Application Layer Gateway (ALG) 
  • Interactive Connectivity Establishment ( ICE )
  •  UPnP Internet Gateway Device Protocol
  • propertiary SIP based Session Border Controller, so on

Lets us just look at ICE in detail which is the default implementation for WebRTC

What is ICE and why is it used ?

ICE (Interactive Connectivity Establishment )  framework ( mandatory by WebRTC standards  ) find network interfaces and ports in Offer / Answer Model to exchange network based information with participating communication clients. ICE makes use of the Session Traversal Utilities for NAT (STUN) protocol and its extension, Traversal Using Relay NAT (TURN)

ICE is defined by RFC 5245 – Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols.

Sample WebRTC offer holding ICE candidates :

type: offer, sdp: v=0
o=- 3475901263113717000 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video data
a=msid-semantic: WMS dZdZMFQRNtY3unof7lTZBInzcRRylLakxtvc
m=audio 9 RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:/v5dQj/qdvKXthQ2
a=ice-pwd:CvSEjVc1z6cMnhjrLlcbIxWK
a=ice-options:google-ice
a=fingerprint:sha-256 F1:A8:2E:71:4B:4E:FF:08:0F:18:13:1C:86:7B:FE:BA:BD:67:CF:B1:7F:19:87:33:6E:10:5C:17:42:0A:6C:15
a=setup:actpass
a=mid:audio
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
m=video 9 RTP/SAVPF 100 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:/v5dQj/qdvKXthQ2
a=ice-pwd:CvSEjVc1z6cMnhjrLlcbIxWK
a=ice-options:google-ice
a=fingerprint:sha-256 F1:A8:2E:71:4B:4E:FF:08:0F:18:13:1C:86:7B:FE:BA:BD:67:CF:B1:7F:19:87:33:6E:10:5C:17:42:0A:6C:15
a=setup:actpass
a=mid:video
a=sendrecv
a=rtcp-mux
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=ice-ufrag:/v5dQj/qdvKXthQ2
a=ice-pwd:CvSEjVc1z6cMnhjrLlcbIxWK
a=ice-options:google-ice
a=fingerprint:sha-256 F1:A8:2E:71:4B:4E:FF:08:0F:18:13:1C:86:7B:FE:BA:BD:67:CF:B1:7F:19:87:33:6E:10:5C:17:42:0A:6C:15
a=setup:actpass
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024

Notice the ICE candidates under video and audio. Now take a look at the SDP answer

type: answer, sdp: v=0
o=- 6931590438150302967 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video data
a=msid-semantic: WMS R98sfBPNQwC20y9HsDBt4to1hTFeP6S0UnsX
m=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:WM/FjMA1ClvNb8xm
a=ice-pwd:8yy1+7x0PoHZCSX2aOVZs2Oq
a=fingerprint:sha-256 7B:9A:A7:43:EC:17:BD:9B:49:E4:23:92:8E:48:E4:8C:9A:BE:85:D4:1D:D7:8B:0E:60:C2:AE:67:77:1D:62:70
a=setup:active
a=mid:audio
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
m=video 1 RTP/SAVPF 100 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:WM/FjMA1ClvNb8xm
a=ice-pwd:8yy1+7x0PoHZCSX2aOVZs2Oq
a=fingerprint:sha-256 7B:9A:A7:43:EC:17:BD:9B:49:E4:23:92:8E:48:E4:8C:9A:BE:85:D4:1D:D7:8B:0E:60:C2:AE:67:77:1D:62:70
a=setup:active
a=mid:video
a=sendrecv
a=rtcp-mux
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
m=application 1 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
b=AS:30
a=ice-ufrag:WM/FjMA1ClvNb8xm
a=ice-pwd:8yy1+7x0PoHZCSX2aOVZs2Oq
a=fingerprint:sha-256 7B:9A:A7:43:EC:17:BD:9B:49:E4:23:92:8E:48:E4:8C:9A:BE:85:D4:1D:D7:8B:0E:60:C2:AE:67:77:1D:62:70
a=setup:active
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024
STUNTURN
address discovery for global IP:portallocates its own address as interface to the client
binary protocolextension of STUN
doesnt stay in path after connectionstays in path after connection.
tunnels and relays media
higher priority lower priority
server and peer reflexive ICE candidates relay ICE candidates
Failed WebRTC ICE Conection
succesfull STUN Connection
ICE candidate grid

Call Flow for STUN protocol exchange

Client -> Server : binding request with attributes – CHANGE-REQUEST

Server -> Cient : binding response with attributes – MAPPED-ADDRESS, RESPONSE-ORIGIN, OTHER-ADDRESS, XOR-MAPPED-ADDRESS

STUN call flow for WebRTC Offer Answer
STUN call flow for WebRTC Offer Answer
WebRTC STUN binding request
WebRTC STUN Binding success response

WebRTC needs SDP Offer to be sent to B from A.
Client B uses this SDP offer to generate an SDP Answer for A.
The SDP ( as seen on chrome://webrtc-internals/ ) includes ICE candidates which map open ports in the firewalls.

However, in case both sides are symmetric NATs, the media flow gets blocked. For such a case TURN is used which tries to give a public IP and port mapped to internal IP and port. This relay path provides an alternative routing mechanism like a packet mirror. It can open a DTLS connection and use it to key the SRTP-DTLS media streams.

NAT types

Some types of NAT are described below

Full Cone ( Normal)

All requests from the same internal IP address and port are mapped to the same external IP address and port. It also allows external hosts to send packet to internal host by using the mapped external address.

Full cone ( credits wikipedia)

Restricted Cone

All requests from the same internal IP address and port are mapped to the same external IP address and port, but external hosts can send packet to internal host only if  internal host had previously sent a packet to that IP address.

Address Restricted cone ( credits wikipedia)

Port Restricted Cone

All requests from the same internal IP address and port are mapped to the same external IP address and port, but external hosts can send packet to internal host only if  internal host had previously sent a packet to that IP address and that port.

Port Restricted cone ( credits wikipedia)

Symmetric

All requests from the same internal IP address and port, to a specific destination IP address and port, are mapped to the same external IP address and port. Any traffic from same internal IP+port to a different destination uses a new mapping. Also external hosts which receives a packet can send a UDP packet back to internal host.

Symmetric NAT ( credits wikipedia).
Address and Port-Dependent Mapping (“APDM”) and APDF (Address and Port-Dependent Filtering).
Web Archieve 2018
credit https://web.archive.org/web/20180829131023/http://nattest.net.in.tum.de/results.php

Network Scenarios for NAT

In order to Understand this better consider various scenarios that determine the NAT Mapping Behavior one could run tests using cli or network analyzer tools and checking checking the XOR-MAPPED-ADDRESS value of the Binding Response message that the client receives

Mapping behaviour

  •  Endpoint-Independent Mapping NAT (EIM-NAT)
  • Address-Dependent Mapping NAT (ADM-NAT)
  • Address and Port-Dependent Mapping NAT (APDM-NAT)

Filtering behaviour

  • Endpoint-Independent Filtering NAT (EIF-NAT)
  • Address-Dependent Filtering NAT (ADF-NAT)
  • Address and Port-Dependent Filtering NAT (APDF-NAT)

Hole Punching

As long as one end of the connection is able to determine the dynamic association of thee other [arty by NAT and send data , hole punching can work.

Permissive NAT mapping techniques which map the same internal address/port consistently to an external address/port are suitable for hole punching such as full cone , address or port restricted NAT. However pure symmetric NAT have inconsistent destination specific port mapping and thus cannot do hole punching.

1 . No Firewall present on either peer. Both connected to open public internet

Diagrammatic representation of  this shown as follows :

WebRTC signalling and media flow on Open public network
WebRTC signalling and media flow on Open public network

In this case there is no restriction to signal or media flow and the call takes places smoothly in p2p fashion.

2.  Either one or both the peer ( could be many in case of multi conf call ) are present behind a firewall  or  restrictive connection or router configured for intranet

In such a case the signal may pass with the use of default ICE candidates or simple ppensource google Stun server such as

iceServers:[
 { 'url': "stun:stun.l.google.com:19302"}]

Diagram :

WebRTC signalling when peers are behind  firewalls
WebRTC signalling when peers are behind firewalls

However the media is restricted resulting in a black / empty / no video situation for both peers  . To combat such situation a relay mechanism such as TURN is required which essentially maps public ip to private ips thus creating a alternative route for media and data to flow through .

WebRTC media flow when peers are behind NAT . Uses TURN relay mechanism
WebRTC media flow when peers are behind NAT . Uses TURN relay mechanism

Peer config should look like :

var configuration =  {
  iceServers: [
 { "url':"stun::"},
 { "url":"turn::"}
  ]};

var pc = new RTCPeerConnection(configuration);

3. When the TURN server is also behind a firewall

The config file of the turn server need to be altered to map the public and private IP. The diagrammatic description of this is as follows :

WebRTC media flow when peers are behind NAT and TURN server is behind NAT as well . TURN config files bind a public interface to private interface address.
WebRTC media flow when peers are behind NAT and TURN server is behind NAT as well . TURN config files bind a public interface to private interface address .

References :