Merge "res_rtp_asterisk.c: Add stun_blacklist option"
This commit is contained in:
commit
1d15e95440
10
CHANGES
10
CHANGES
|
@ -21,6 +21,16 @@ app_queue
|
||||||
--- Functionality changes from Asterisk 14.4.0 to Asterisk 14.5.0 ------------
|
--- Functionality changes from Asterisk 14.4.0 to Asterisk 14.5.0 ------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
res_rtp_asterisk
|
||||||
|
------------------
|
||||||
|
* Added the stun_blacklist option to rtp.conf. Some multihomed servers have
|
||||||
|
IP interfaces that cannot reach the STUN server specified by stunaddr.
|
||||||
|
Blacklist those interface subnets from trying to send a STUN packet to find
|
||||||
|
the external IP address. Attempting to send the STUN packet needlessly
|
||||||
|
delays processing incoming and outgoing SIP INVITEs because we will wait
|
||||||
|
for a response that can never come until we give up on the response.
|
||||||
|
Multiple subnets may be listed.
|
||||||
|
|
||||||
res_pjsip_config_wizard
|
res_pjsip_config_wizard
|
||||||
------------------
|
------------------
|
||||||
* Two new parameters have been added to the pjsip config wizard.
|
* Two new parameters have been added to the pjsip config wizard.
|
||||||
|
|
|
@ -45,6 +45,25 @@ rtpend=20000
|
||||||
;
|
;
|
||||||
; stunaddr=
|
; stunaddr=
|
||||||
;
|
;
|
||||||
|
; Some multihomed servers have IP interfaces that cannot reach the STUN
|
||||||
|
; server specified by stunaddr. Blacklist those interface subnets from
|
||||||
|
; trying to send a STUN packet to find the external IP address.
|
||||||
|
; Attempting to send the STUN packet needlessly delays processing incoming
|
||||||
|
; and outgoing SIP INVITEs because we will wait for a response that can
|
||||||
|
; never come until we give up on the response.
|
||||||
|
; * Multiple subnets may be listed.
|
||||||
|
; * Blacklisting applies to IPv4 only. STUN isn't needed for IPv6.
|
||||||
|
; * Blacklisting applies when binding RTP to specific IP addresses and not
|
||||||
|
; the wildcard 0.0.0.0 address. e.g., A PJSIP endpoint binding RTP to a
|
||||||
|
; specific address using the bind_rtp_to_media_address and media_address
|
||||||
|
; options. Or the PJSIP endpoint specifies an explicit transport that binds
|
||||||
|
; to a specific IP address.
|
||||||
|
;
|
||||||
|
; e.g. stun_blacklist = 192.168.1.0/255.255.255.0
|
||||||
|
; stun_blacklist = 10.32.77.0/255.255.255.0
|
||||||
|
;
|
||||||
|
; stun_blacklist =
|
||||||
|
;
|
||||||
; Hostname or address for the TURN server to be used as a relay. The port
|
; Hostname or address for the TURN server to be used as a relay. The port
|
||||||
; number is optional. If omitted the default value of 3478 will be used.
|
; number is optional. If omitted the default value of 3478 will be used.
|
||||||
; This option is disabled by default.
|
; This option is disabled by default.
|
||||||
|
|
|
@ -131,13 +131,13 @@ static int rtcpstats; /*!< Are we debugging RTCP? */
|
||||||
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
|
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
|
||||||
static struct ast_sockaddr rtpdebugaddr; /*!< Debug packets to/from this host */
|
static struct ast_sockaddr rtpdebugaddr; /*!< Debug packets to/from this host */
|
||||||
static struct ast_sockaddr rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
|
static struct ast_sockaddr rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
|
||||||
static int rtpdebugport; /*< Debug only RTP packets from IP or IP+Port if port is > 0 */
|
static int rtpdebugport; /*!< Debug only RTP packets from IP or IP+Port if port is > 0 */
|
||||||
static int rtcpdebugport; /*< Debug only RTCP packets from IP or IP+Port if port is > 0 */
|
static int rtcpdebugport; /*!< Debug only RTCP packets from IP or IP+Port if port is > 0 */
|
||||||
#ifdef SO_NO_CHECK
|
#ifdef SO_NO_CHECK
|
||||||
static int nochecksums;
|
static int nochecksums;
|
||||||
#endif
|
#endif
|
||||||
static int strictrtp = DEFAULT_STRICT_RTP; /*< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */
|
static int strictrtp = DEFAULT_STRICT_RTP; /*!< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */
|
||||||
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; /*< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */
|
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; /*!< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */
|
||||||
#ifdef HAVE_PJPROJECT
|
#ifdef HAVE_PJPROJECT
|
||||||
static int icesupport = DEFAULT_ICESUPPORT;
|
static int icesupport = DEFAULT_ICESUPPORT;
|
||||||
static struct sockaddr_in stunaddr;
|
static struct sockaddr_in stunaddr;
|
||||||
|
@ -145,9 +145,14 @@ static pj_str_t turnaddr;
|
||||||
static int turnport = DEFAULT_TURN_PORT;
|
static int turnport = DEFAULT_TURN_PORT;
|
||||||
static pj_str_t turnusername;
|
static pj_str_t turnusername;
|
||||||
static pj_str_t turnpassword;
|
static pj_str_t turnpassword;
|
||||||
|
|
||||||
static struct ast_ha *ice_blacklist = NULL; /*!< Blacklisted ICE networks */
|
static struct ast_ha *ice_blacklist = NULL; /*!< Blacklisted ICE networks */
|
||||||
static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
|
static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
|
||||||
|
|
||||||
|
/*! Blacklisted networks for STUN requests */
|
||||||
|
static struct ast_ha *stun_blacklist = NULL;
|
||||||
|
static ast_rwlock_t stun_blacklist_lock = AST_RWLOCK_INIT_VALUE;
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Pool factory used by pjlib to allocate memory. */
|
/*! \brief Pool factory used by pjlib to allocate memory. */
|
||||||
static pj_caching_pool cachingpool;
|
static pj_caching_pool cachingpool;
|
||||||
|
@ -2523,6 +2528,32 @@ static int rtp_address_is_ice_blacklisted(const pj_sockaddr_t *address)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Checks an address against the STUN blacklist
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \note If there is no stun_blacklist list, always returns 0
|
||||||
|
*
|
||||||
|
* \param addr The address to consider
|
||||||
|
*
|
||||||
|
* \retval 0 if address is not STUN blacklisted
|
||||||
|
* \retval 1 if address is STUN blacklisted
|
||||||
|
*/
|
||||||
|
static int stun_address_is_blacklisted(const struct ast_sockaddr *addr)
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
|
ast_rwlock_rdlock(&stun_blacklist_lock);
|
||||||
|
if (!stun_blacklist
|
||||||
|
|| ast_apply_ha(stun_blacklist, addr) == AST_SENSE_ALLOW) {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
ast_rwlock_unlock(&stun_blacklist_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,
|
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)
|
int transport)
|
||||||
{
|
{
|
||||||
|
@ -2557,7 +2588,8 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If configured to use a STUN server to get our external mapped address do so */
|
/* If configured to use a STUN server to get our external mapped address do so */
|
||||||
if (stunaddr.sin_addr.s_addr && ast_sockaddr_is_ipv4(addr) && count) {
|
if (stunaddr.sin_addr.s_addr && count && ast_sockaddr_is_ipv4(addr)
|
||||||
|
&& !stun_address_is_blacklisted(addr)) {
|
||||||
struct sockaddr_in answer;
|
struct sockaddr_in answer;
|
||||||
|
|
||||||
if (!ast_stun_request(component == AST_RTP_ICE_COMPONENT_RTCP ? rtp->rtcp->s : rtp->s, &stunaddr, NULL, &answer)) {
|
if (!ast_stun_request(component == AST_RTP_ICE_COMPONENT_RTCP ? rtp->rtcp->s : rtp->s, &stunaddr, NULL, &answer)) {
|
||||||
|
@ -5626,6 +5658,66 @@ static struct ast_cli_entry cli_rtp[] = {
|
||||||
AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
|
AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PJPROJECT
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Clear the configured blacklist.
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param lock R/W lock protecting the blacklist
|
||||||
|
* \param blacklist List to clear
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
static void blacklist_clear(ast_rwlock_t *lock, struct ast_ha **blacklist)
|
||||||
|
{
|
||||||
|
ast_rwlock_wrlock(lock);
|
||||||
|
ast_free_ha(*blacklist);
|
||||||
|
*blacklist = NULL;
|
||||||
|
ast_rwlock_unlock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Load the blacklist configuration.
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param cfg Raw config file options.
|
||||||
|
* \param option_name Blacklist option name
|
||||||
|
* \param lock R/W lock protecting the blacklist
|
||||||
|
* \param blacklist List to load
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
static void blacklist_config_load(struct ast_config *cfg, const char *option_name,
|
||||||
|
ast_rwlock_t *lock, struct ast_ha **blacklist)
|
||||||
|
{
|
||||||
|
struct ast_variable *var;
|
||||||
|
|
||||||
|
ast_rwlock_wrlock(lock);
|
||||||
|
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
|
||||||
|
if (!strcasecmp(var->name, option_name)) {
|
||||||
|
struct ast_ha *na;
|
||||||
|
int ha_error = 0;
|
||||||
|
|
||||||
|
na = ast_append_ha("d", var->value, *blacklist, &ha_error);
|
||||||
|
if (!na) {
|
||||||
|
ast_log(LOG_WARNING, "Invalid %s value: %s\n",
|
||||||
|
option_name, var->value);
|
||||||
|
} else {
|
||||||
|
*blacklist = na;
|
||||||
|
}
|
||||||
|
if (ha_error) {
|
||||||
|
ast_log(LOG_ERROR,
|
||||||
|
"Bad %s configuration value line %d: %s\n",
|
||||||
|
option_name, var->lineno, var->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast_rwlock_unlock(lock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int rtp_reload(int reload)
|
static int rtp_reload(int reload)
|
||||||
{
|
{
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
|
@ -5638,7 +5730,7 @@ static int rtp_reload(int reload)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
|
cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
|
||||||
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
|
if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5664,13 +5756,10 @@ static int rtp_reload(int reload)
|
||||||
turnusername = pj_str(NULL);
|
turnusername = pj_str(NULL);
|
||||||
turnpassword = pj_str(NULL);
|
turnpassword = pj_str(NULL);
|
||||||
host_candidate_overrides_clear();
|
host_candidate_overrides_clear();
|
||||||
ast_rwlock_wrlock(&ice_blacklist_lock);
|
blacklist_clear(&ice_blacklist_lock, &ice_blacklist);
|
||||||
ast_free_ha(ice_blacklist);
|
blacklist_clear(&stun_blacklist_lock, &stun_blacklist);
|
||||||
ice_blacklist = NULL;
|
|
||||||
ast_rwlock_unlock(&ice_blacklist_lock);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cfg) {
|
|
||||||
if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
|
if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
|
||||||
rtpstart = atoi(s);
|
rtpstart = atoi(s);
|
||||||
if (rtpstart < MINIMUM_RTP_PORT)
|
if (rtpstart < MINIMUM_RTP_PORT)
|
||||||
|
@ -5779,26 +5868,14 @@ static int rtp_reload(int reload)
|
||||||
AST_RWLIST_UNLOCK(&host_candidates);
|
AST_RWLIST_UNLOCK(&host_candidates);
|
||||||
|
|
||||||
/* Read ICE blacklist configuration lines */
|
/* Read ICE blacklist configuration lines */
|
||||||
ast_rwlock_wrlock(&ice_blacklist_lock);
|
blacklist_config_load(cfg, "ice_blacklist", &ice_blacklist_lock, &ice_blacklist);
|
||||||
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
|
|
||||||
if (!strcasecmp(var->name, "ice_blacklist")) {
|
|
||||||
struct ast_ha *na;
|
|
||||||
int ha_error = 0;
|
|
||||||
if (!(na = ast_append_ha("d", var->value, ice_blacklist, &ha_error))) {
|
|
||||||
ast_log(LOG_WARNING, "Invalid ice_blacklist value: %s\n", var->value);
|
|
||||||
} else {
|
|
||||||
ice_blacklist = na;
|
|
||||||
}
|
|
||||||
if (ha_error) {
|
|
||||||
ast_log(LOG_ERROR, "Bad ice_blacklist configuration value line %d : %s\n", var->lineno, var->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast_rwlock_unlock(&ice_blacklist_lock);
|
|
||||||
|
|
||||||
|
/* Read STUN blacklist configuration lines */
|
||||||
|
blacklist_config_load(cfg, "stun_blacklist", &stun_blacklist_lock, &stun_blacklist);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ast_config_destroy(cfg);
|
ast_config_destroy(cfg);
|
||||||
}
|
|
||||||
if (rtpstart >= rtpend) {
|
if (rtpstart >= rtpend) {
|
||||||
ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
|
ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
|
||||||
rtpstart = DEFAULT_RTP_START;
|
rtpstart = DEFAULT_RTP_START;
|
||||||
|
|
Loading…
Reference in New Issue