diff --git a/CHANGES b/CHANGES
index 109f4f60d024bad99b48ab32c10f9b1141f0c2f3..2ef538eab140b267ea6d93172c2c4969bcf1c0cc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -398,6 +398,9 @@ chan_sip
    detects that an incoming SIP request crossed a NAT after being sent by
    the remote endpoint.
 
+ * The default global nat setting in sip.conf has been changed from force_rport
+   to auto_force_rport.
+
  * NAT settings are now a combinable list of options. The equivalent of the
    deprecated nat=yes is nat=force_rport,comedia. nat=no behaves as before.
 
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index cdf020ad70a36395aea4210143c592070d35d74d..1adf7a00faeb921755a9d7964ea22bda216f7bb6 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1399,7 +1399,7 @@ static int get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoi
 static int get_also_info(struct sip_pvt *p, struct sip_request *oreq);
 static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
 static int set_address_from_contact(struct sip_pvt *pvt);
-static void check_via(struct sip_pvt *p, struct sip_request *req);
+static void check_via(struct sip_pvt *p, const struct sip_request *req);
 static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
 static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason, char **reason_str);
 static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
@@ -8747,9 +8747,8 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
 
 	if (useglobal_nat && addr) {
 		/* Setup NAT structure according to global settings if we have an address */
-		ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
 		ast_sockaddr_copy(&p->recv, addr);
-
+		check_via(p, req);
 		do_setnat(p);
 	}
 
@@ -12116,8 +12115,9 @@ static int transmit_response_using_temp(ast_string_field callid, struct ast_sock
 
 	if (useglobal_nat && addr) {
 		ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT_FORCE_RPORT);
+		ast_copy_flags(&p->flags[2], &global_flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
 		ast_sockaddr_copy(&p->recv, addr);
-		do_setnat(p);
+		check_via(p, req);
 	}
 
 	ast_string_field_set(p, fromdomain, default_fromdomain);
@@ -17958,7 +17958,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
 }
 
 /*! \brief check Via: header for hostname, port and rport request/answer */
-static void check_via(struct sip_pvt *p, struct sip_request *req)
+static void check_via(struct sip_pvt *p, const struct sip_request *req)
 {
 	char via[512];
 	char *c, *maddr;
@@ -18092,6 +18092,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
 		return AUTH_DONT_KNOW;
 	}
 
+	/*  build_peer, called through sip_find_peer, is not able to check the
+	 *  sip_pvt->natdetected flag in order to determine if the peer is behind
+	 *  NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
+	 *  are set on the peer.  So we check for that here and set the peer's
+	 *  address accordingly.
+	 */
+	if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+		ast_set_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT);
+		ast_sockaddr_copy(&peer->addr, &p->recv);
+	}
+
+	if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
+		ast_set_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP);
+	}
+
 	if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
 		ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
 		sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
@@ -28426,7 +28441,10 @@ static int handle_request_do(struct sip_request *req, struct ast_sockaddr *addr)
 	owner_chan_ref = sip_pvt_lock_full(p);
 
 	copy_socket_data(&p->socket, &req->socket);
-	ast_sockaddr_copy(&p->recv, addr);
+
+	if (ast_sockaddr_isnull(&p->recv)) { /* This may already be set before getting here */
+		ast_sockaddr_copy(&p->recv, addr);
+	}
 
 	/* if we have an owner, then this request has been authenticated */
 	if (p->owner) {
@@ -30637,7 +30655,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
 			} else if (!strcasecmp(v->name, "host")) {
 				if (!strcasecmp(v->value, "dynamic")) {
 					/* They'll register with us */
-					if ((!found && !realtime) || !peer->host_dynamic) {
+					if ((!found && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) || !peer->host_dynamic) {
 						/* Initialize stuff if this is a new peer, or if it used to
 						 * not be dynamic before the reload. */
 						ast_sockaddr_setnull(&peer->addr);
@@ -30990,6 +31008,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
 		set_socket_transport(&peer->socket, peer->default_outbound_transport);
 	}
 
+	ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
+	ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
+	ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags);
+
 	if (ast_str_strlen(fullcontact)) {
 		ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
 		peer->rt_fromcontact = TRUE;
@@ -31083,9 +31105,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
 		sip_poke_peer(peer, 0);
 	}
 
-	ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
-	ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
-	ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags);
 	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
 		sip_cfg.allowsubscribe = TRUE;	/* No global ban any more */
 	}
diff --git a/contrib/realtime/mysql/sippeers.sql b/contrib/realtime/mysql/sippeers.sql
index 5c58df7ea1e67487417b25cd57f85d4e8c55e145..e0dbe1a430492662e8d4fae8af77222a4859d7f3 100644
--- a/contrib/realtime/mysql/sippeers.sql
+++ b/contrib/realtime/mysql/sippeers.sql
@@ -24,7 +24,7 @@ CREATE TABLE IF NOT EXISTS `sippeers` (
       `transport` enum('udp','tcp','udp,tcp','tcp,udp') DEFAULT NULL,
       `dtmfmode` enum('rfc2833','info','shortinfo','inband','auto') DEFAULT NULL,
       `directmedia` enum('yes','no','nonat','update') DEFAULT NULL,
-      `nat` enum('yes','no','never','route') DEFAULT NULL,
+      `nat` varchar(29) DEFAULT NULL,
       `callgroup` varchar(40) DEFAULT NULL,
       `pickupgroup` varchar(40) DEFAULT NULL,
       `language` varchar(40) DEFAULT NULL,
diff --git a/contrib/realtime/postgresql/realtime.sql b/contrib/realtime/postgresql/realtime.sql
index abcadd2fd801676b0767dfdfb77e0e789b2ac4a9..cba8d3895db4a3af738ee7075a839c21be20d200 100644
--- a/contrib/realtime/postgresql/realtime.sql
+++ b/contrib/realtime/postgresql/realtime.sql
@@ -48,7 +48,7 @@ insecure character varying(4),
 "language" character varying(2),
 mailbox character varying(50),
 md5secret character varying(80),
-nat character varying(5) DEFAULT 'no' NOT NULL,
+nat character varying(29) DEFAULT '' NOT NULL,
 permit character varying(95),
 deny character varying(95),
 mask character varying(95),