[Asterisk-code-review] res rtp asterisk: Add blackice option (asterisk[14])

Joshua Colp asteriskteam at digium.com
Fri Oct 14 09:56:30 CDT 2016


Joshua Colp has uploaded a new change for review.

  https://gerrit.asterisk.org/4110

Change subject: res_rtp_asterisk: Add blackice option
......................................................................

res_rtp_asterisk: Add blackice option

Introduces blackice configuration in rtp.conf. Subnets listed in the
form blackice = <subnet spec>, e.g. blackice =
192.168.1.0/255.255.255.0, are excluded from ICE host, srflx and relay
discovery. This is useful for optimizing the ICE process where a system
has multiple host address ranges and/or physical interfaces and certain
of them are not expected to be used for RTP. Multiple blackice
configuration lines may be used. If left unconfigured, all discovered
host addresses are used, as per previous behavior.

Documention in rtp.conf.sample.

ASTERISK-26418 #close

Change-Id: Ibee88f80d7693874fda1cceaef94a03bd86012c9
---
M CHANGES
M configs/samples/rtp.conf.sample
M res/res_rtp_asterisk.c
3 files changed, 98 insertions(+), 6 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/10/4110/1

diff --git a/CHANGES b/CHANGES
index 1fa9786..6c93f43 100644
--- a/CHANGES
+++ b/CHANGES
@@ -71,6 +71,11 @@
    Note: The caller-id and redirecting number strings obtained from incoming
    SIP URI user fields are now always truncated at the first semicolon.
 
+res_rtp_asterisk
+------------------
+  * An option, blackice, has been added which allows certain subnets to be
+    excluded from local ICE candidates.
+
 app_confbridge
 ------------------
   * Some sounds played into the bridge are played asynchronously. This, for
diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample
index 2ef5dd2..f500dcc 100644
--- a/configs/samples/rtp.conf.sample
+++ b/configs/samples/rtp.conf.sample
@@ -59,6 +59,18 @@
 ; Password used to authenticate with TURN relay server.
 ; turnpassword=
 ;
+; Subnets to exclude from ICE host, srflx and relay discovery. This is useful
+; to optimize the ICE process where a system has multiple host address ranges
+; and/or physical interfaces and certain of them are not expected to be used
+; for RTP. For example, VPNs and local interconnections may not be suitable or
+; necessary for ICE. Multiple subnets may be listed. If left unconfigured,
+; all discovered host addresses are used.
+;
+; e.g. blackice = 192.168.1.0/255.255.255.0
+;      blackice = 10.32.77.0/255.255.255.0
+;
+; blackice =
+;
 [ice_host_candidates]
 ;
 ; When Asterisk is behind a static one-to-one NAT and ICE is in use, ICE will
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 520fd76..eef37a5 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -51,6 +51,7 @@
 #include <pjlib.h>
 #include <pjlib-util.h>
 #include <pjnath.h>
+#include <ifaddrs.h>
 #endif
 
 #include "asterisk/stun.h"
@@ -145,6 +146,9 @@
 static int turnport = DEFAULT_TURN_PORT;
 static pj_str_t turnusername;
 static pj_str_t turnpassword;
+static struct ast_ha *blackice = NULL;    /*!< Blacklisted ICE networks */
+static ast_rwlock_t blackice_lock = AST_RWLOCK_INIT_VALUE;
+
 
 /*! \brief Pool factory used by pjlib to allocate memory. */
 static pj_caching_pool cachingpool;
@@ -2446,11 +2450,38 @@
 }
 
 #ifdef HAVE_PJPROJECT
+/*!
+ * \internal
+ * \brief Checks an address against the blackice list (aka ICE blacklist)
+ * \note If there is no blackice list, always returns 0
+ *
+ * \param address The address to consider
+ * \retval 0 if address is not blackice listed
+ * \retval 1 if address is blackice listed
+ */
+static int rtp_address_is_blackice(const pj_sockaddr_t *address)
+{
+	char buf[PJ_INET6_ADDRSTRLEN];
+	struct ast_sockaddr saddr;
+	int result = 1;
+
+	ast_sockaddr_parse(&saddr, pj_sockaddr_print(address, buf, sizeof(buf), 0), 0);
+
+	ast_rwlock_rdlock(&blackice_lock);
+	if (!blackice || (ast_apply_ha(blackice, &saddr) == AST_SENSE_ALLOW)) {
+		result = 0;
+	}
+	ast_rwlock_unlock(&blackice_lock);
+
+	return result;
+}
+
 static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *addr, int port, int component,
 				      int transport)
 {
 	pj_sockaddr address[16];
 	unsigned int count = PJ_ARRAY_SIZE(address), pos = 0;
+	int basepos = -1;
 
 	/* Add all the local interface IP addresses */
 	if (ast_sockaddr_is_ipv4(addr)) {
@@ -2464,9 +2495,18 @@
 	host_candidate_overrides_apply(count, address);
 
 	for (pos = 0; pos < count; pos++) {
-		pj_sockaddr_set_port(&address[pos], port);
-		ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_HOST, 65535, &address[pos], &address[pos], NULL,
+		if (!rtp_address_is_blackice(&address[pos])) {
+			if (basepos == -1) {
+				basepos = pos;
+			}
+			pj_sockaddr_set_port(&address[pos], port);
+			ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_HOST, 65535, &address[pos], &address[pos], NULL,
 				     pj_sockaddr_get_len(&address[pos]));
+		}
+	}
+	if (basepos == -1) {
+		/* start with first address unless excluded above */
+		basepos = 0;
 	}
 
 	/* If configured to use a STUN server to get our external mapped address do so */
@@ -2475,15 +2515,27 @@
 
 		if (!ast_stun_request(component == AST_RTP_ICE_COMPONENT_RTCP ? rtp->rtcp->s : rtp->s, &stunaddr, NULL, &answer)) {
 			pj_sockaddr base;
+			pj_sockaddr ext;
 			pj_str_t mapped = pj_str(ast_strdupa(ast_inet_ntoa(answer.sin_addr)));
+			int srflx = 1;
 
 			/* Use the first local host candidate as the base */
-			pj_sockaddr_cp(&base, &address[0]);
+			pj_sockaddr_cp(&base, &address[basepos]);
 
-			pj_sockaddr_init(pj_AF_INET(), &address[0], &mapped, ntohs(answer.sin_port));
+			pj_sockaddr_init(pj_AF_INET(), &ext, &mapped, ntohs(answer.sin_port));
 
-			ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_SRFLX, 65535, &address[0], &base,
-					     &base, pj_sockaddr_get_len(&address[0]));
+			/* If the returned address is the same as one of our host candidates, don't send the srflx */
+			for (pos = 0; pos < count; pos++) {
+				if ((pj_sockaddr_cmp(&address[pos], &ext) == 0) && !rtp_address_is_blackice(&address[pos])) {
+					srflx = 0;
+					break;
+				}
+			}
+
+			if (srflx) {
+				ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_SRFLX, 65535, &ext, &base,
+							 &base, pj_sockaddr_get_len(&ext));
+			}
 		}
 	}
 
@@ -5393,6 +5445,10 @@
 	turnusername = pj_str(NULL);
 	turnpassword = pj_str(NULL);
 	host_candidate_overrides_clear();
+	ast_rwlock_wrlock(&blackice_lock);
+	ast_free_ha(blackice);
+	blackice = NULL;
+	ast_rwlock_unlock(&blackice_lock);
 #endif
 
 	if (cfg) {
@@ -5502,6 +5558,25 @@
 			AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
 		}
 		AST_RWLIST_UNLOCK(&host_candidates);
+
+		/* Read blackice configuration lines */
+		ast_rwlock_wrlock(&blackice_lock);
+		for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
+			if (!strcasecmp(var->name, "blackice")) {
+				struct ast_ha *na;
+				int ha_error = 0;
+				if (!(na = ast_append_ha("d", var->value, blackice, &ha_error))) {
+					ast_log(LOG_WARNING, "Invalid blackice value: %s\n", var->value);
+				} else {
+					blackice = na;
+				}
+				if (ha_error) {
+					ast_log(LOG_ERROR, "Bad blackice configuration value line %d : %s\n", var->lineno, var->value);
+				}
+			}
+		}
+		ast_rwlock_unlock(&blackice_lock);
+
 #endif
 		ast_config_destroy(cfg);
 	}

-- 
To view, visit https://gerrit.asterisk.org/4110
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibee88f80d7693874fda1cceaef94a03bd86012c9
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-Owner: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Michael Walton <mike at farsouthnet.com>



More information about the asterisk-code-review mailing list