diff --git a/CHANGES b/CHANGES
index ad16a4008ffdf9012033b0e2afc86c04cbb10b74..d843848cfb3494f928b1cbc6cd47852a56dd8051 100644
--- a/CHANGES
+++ b/CHANGES
@@ -110,6 +110,12 @@ res_pjsip
    ID, AuthenticateQualify, OutboundProxy, Path, QualifyFrequency and
    QualifyTimeout.  Existing fields have not been disturbed.
 
+res_pjsip_endpoint_identifier_ip
+------------------
+ * SRV lookups can now be done on provided hostnames to determine additional
+   source IP addresses for requests. This is configurable using the
+   "srv_lookups" option on the identify and defaults to "yes".
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ------------
 ------------------------------------------------------------------------------
diff --git a/contrib/ast-db-manage/config/versions/28ab27a7826d_add_srv_lookups_to_identify.py b/contrib/ast-db-manage/config/versions/28ab27a7826d_add_srv_lookups_to_identify.py
new file mode 100644
index 0000000000000000000000000000000000000000..8831e20023e5f5d2aa476c6f67ff3c563c3cdff1
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/28ab27a7826d_add_srv_lookups_to_identify.py
@@ -0,0 +1,31 @@
+"""add srv_lookups to identify
+
+Revision ID: 28ab27a7826d
+Revises: 4468b4a91372
+Create Date: 2017-01-06 14:53:38.829655
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '28ab27a7826d'
+down_revision = '4468b4a91372'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_endpoint_id_ips', sa.Column('srv_lookups', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoint_id_ips', 'srv_lookups')
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 7a7af0b4e021b320747cc2d3ae44f9e32b5c36a0..e095a96309a3dbf9e5b1a30946f780917b9ca90c 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -51,6 +51,13 @@
 						mask with a slash ('/')
 					</para></description>
 				</configOption>
+				<configOption name="srv_lookups" default="yes">
+					<synopsis>Perform SRV lookups for provided hostnames.</synopsis>
+					<description><para>When enabled, <replaceable>srv_lookups</replaceable> will
+					perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of the given
+					hostnames to determine additional addresses that traffic may originate from.
+					</para></description>
+                                </configOption>
 				<configOption name="type">
 					<synopsis>Must be of type 'identify'.</synopsis>
 				</configOption>
@@ -70,6 +77,8 @@ struct ip_identify_match {
 	);
 	/*! \brief Networks or addresses that should match this */
 	struct ast_ha *matches;
+	/*! \brief Perform SRV resolution of hostnames */
+	unsigned int srv_lookups;
 };
 
 /*! \brief Destructor function for a matching object */
@@ -153,6 +162,72 @@ static struct ast_sip_endpoint_identifier ip_identifier = {
 	.identify_endpoint = ip_identify,
 };
 
+/*! \brief Helper function which performs a host lookup and adds result to identify match */
+static int ip_identify_match_host_lookup(struct ip_identify_match *identify, const char *host)
+{
+	struct ast_sockaddr *addrs;
+	int num_addrs = 0, error = 0, i;
+	int results = 0;
+
+	num_addrs = ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC);
+	if (!num_addrs) {
+		return -1;
+	}
+
+	for (i = 0; i < num_addrs; ++i) {
+		/* Check if the address is already in the list, if so don't bother adding it again */
+		if (identify->matches && (ast_apply_ha(identify->matches, &addrs[i]) != AST_SENSE_ALLOW)) {
+			continue;
+		}
+
+		/* We deny what we actually want to match because there is an implicit permit all rule for ACLs */
+		identify->matches = ast_append_ha("d", ast_sockaddr_stringify_addr(&addrs[i]), identify->matches, &error);
+
+		if (!identify->matches || error) {
+			results = -1;
+			break;
+		}
+
+		results += 1;
+	}
+
+	ast_free(addrs);
+
+	return results;
+}
+
+/*! \brief Helper function which performs an SRV lookup and then resolves the hostname */
+static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host)
+{
+	char service[NI_MAXHOST];
+	struct srv_context *context = NULL;
+	int srv_ret;
+	const char *srvhost;
+	unsigned short srvport;
+	int results = 0;
+
+	snprintf(service, sizeof(service), "%s.%s", prefix, host);
+
+	while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
+		int hosts;
+
+		/* In the case of the SRV lookup we don't care if it fails, we will output a log message
+		 * when we fallback to a normal lookup.
+		 */
+		hosts = ip_identify_match_host_lookup(identify, srvhost);
+		if (hosts == -1) {
+			results = -1;
+			break;
+		} else {
+			results += hosts;
+		}
+	}
+
+	ast_srv_cleanup(&context);
+
+	return results;
+}
+
 /*! \brief Custom handler for match field */
 static int ip_identify_match_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
 {
@@ -165,9 +240,9 @@ static int ip_identify_match_handler(const struct aco_option *opt, struct ast_va
 	}
 
 	while ((current_string = ast_strip(strsep(&input_string, ",")))) {
-		struct ast_sockaddr *addrs;
-		int num_addrs = 0, error = 0, i;
 		char *mask = strrchr(current_string, '/');
+		struct ast_sockaddr address;
+		int error, results = 0;
 
 		if (ast_strlen_zero(current_string)) {
 			continue;
@@ -185,28 +260,28 @@ static int ip_identify_match_handler(const struct aco_option *opt, struct ast_va
 			continue;
 		}
 
-		num_addrs = ast_sockaddr_resolve(&addrs, current_string, PARSE_PORT_FORBID, AST_AF_UNSPEC);
-		if (!num_addrs) {
-			ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n",
-				var->value, ast_sorcery_object_get_id(obj));
-			return -1;
-		}
-
-		for (i = 0; i < num_addrs; ++i) {
-			/* We deny what we actually want to match because there is an implicit permit all rule for ACLs */
-			identify->matches = ast_append_ha("d", ast_sockaddr_stringify_addr(&addrs[i]), identify->matches, &error);
-
-			if (!identify->matches || error) {
-				ast_log(LOG_ERROR, "Failed to add address '%s' to ip endpoint identifier '%s'\n",
-					ast_sockaddr_stringify_addr(&addrs[i]), ast_sorcery_object_get_id(obj));
-				error = -1;
-				break;
+		/* If the provided string is not an IP address perform SRV resolution on it */
+		if (identify->srv_lookups && !ast_sockaddr_parse(&address, current_string, 0)) {
+			results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string);
+			if (results != -1) {
+				results += ip_identify_match_srv_lookup(identify, "_sip._tcp", current_string);
+			}
+			if (results != -1) {
+				results += ip_identify_match_srv_lookup(identify, "_sips._tcp", current_string);
 			}
 		}
 
-		ast_free(addrs);
+		/* If SRV falls fall back to a normal lookup on the host itself */
+		if (!results) {
+			results = ip_identify_match_host_lookup(identify, current_string);
+		}
 
-		if (error) {
+		if (results == 0) {
+			ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n",
+				current_string, ast_sorcery_object_get_id(obj));
+		} else if (results == -1) {
+			ast_log(LOG_ERROR, "An error occurred when adding resolution results of '%s' on '%s'\n",
+				current_string, ast_sorcery_object_get_id(obj));
 			return -1;
 		}
 	}
@@ -469,6 +544,7 @@ static int load_module(void)
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "type", "", OPT_NOOP_T, 0, 0);
 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name));
 	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
+	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "srv_lookups", "yes", OPT_BOOL_T, 1, FLDSET(struct ip_identify_match, srv_lookups));
 	ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
 
 	ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip");