diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h
index cd49dbe4825d577af6b44ee0f17dd0ea60523ecb..2180ef46bd6d5f65759a3a75c9155f37f8a5c679 100644
--- a/include/asterisk/http_websocket.h
+++ b/include/asterisk/http_websocket.h
@@ -344,6 +344,15 @@ AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno
  */
 AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {return NULL;});
 
+/*!
+ * \brief Get the local address for a WebSocket connection session.
+ *
+ * \retval ast_sockaddr Local address
+ *
+ * \since 13.19.0
+ */
+AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_local_address, (struct ast_websocket *session), {return NULL;});
+
 /*!
  * \brief Get whether the WebSocket session is using a secure transport or not.
  *
diff --git a/res/res_hep_pjsip.c b/res/res_hep_pjsip.c
index 13efbfa6afa1d4cdc9d8842e17437b28eefcdfc3..b5be4a1025d522a7964ebc972b4ee553a0000224 100644
--- a/res/res_hep_pjsip.c
+++ b/res/res_hep_pjsip.c
@@ -89,35 +89,44 @@ static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
 	pjsip_cid_hdr *cid_hdr;
 	pjsip_from_hdr *from_hdr;
 	pjsip_to_hdr *to_hdr;
-	pjsip_tpmgr_fla2_param prm;
 
 	capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));
 	if (!capture_info) {
 		return PJ_SUCCESS;
 	}
 
-	/* Attempt to determine what IP address will we send this packet out of */
-	pjsip_tpmgr_fla2_param_default(&prm);
-	prm.tp_type = tdata->tp_info.transport->key.type;
-	pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
-	prm.local_if = PJ_TRUE;
+	if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+		pjsip_tpmgr_fla2_param prm;
 
-	/* If we can't get the local address use what we have already */
-	if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
-		pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
-	} else {
-		if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
-			snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
-				(int)pj_strlen(&prm.ret_addr),
-				pj_strbuf(&prm.ret_addr),
-				prm.ret_port);
+		/* Attempt to determine what IP address will we send this packet out of */
+		pjsip_tpmgr_fla2_param_default(&prm);
+		prm.tp_type = tdata->tp_info.transport->key.type;
+		pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
+		prm.local_if = PJ_TRUE;
+
+		/* If we can't get the local address use what we have already */
+		if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
+			pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
 		} else {
-			snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
-				(int)pj_strlen(&prm.ret_addr),
-				pj_strbuf(&prm.ret_addr),
-				prm.ret_port);
+			if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+				snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+					(int)pj_strlen(&prm.ret_addr),
+					pj_strbuf(&prm.ret_addr),
+					prm.ret_port);
+			} else {
+				snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+					(int)pj_strlen(&prm.ret_addr),
+					pj_strbuf(&prm.ret_addr),
+					prm.ret_port);
+			}
 		}
+	} else {
+		/* For reliable transports they can only ever come from the transport
+		 * local address.
+		 */
+		pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
 	}
+
 	pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);
 
 	cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);
@@ -150,7 +159,6 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
 	char remote_buf[256];
 	char *uuid;
 	struct hepv3_capture_info *capture_info;
-	pjsip_tpmgr_fla2_param prm;
 
 	capture_info = hepv3_create_capture_info(&rdata->pkt_info.packet, rdata->pkt_info.len);
 	if (!capture_info) {
@@ -162,27 +170,33 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
 	}
 	pj_sockaddr_print(&rdata->pkt_info.src_addr, remote_buf, sizeof(remote_buf), 3);
 
-	/* Attempt to determine what IP address we probably received this packet on */
-	pjsip_tpmgr_fla2_param_default(&prm);
-	prm.tp_type = rdata->tp_info.transport->key.type;
-	pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
-	prm.local_if = PJ_TRUE;
+	if (!(rdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+		pjsip_tpmgr_fla2_param prm;
 
-	/* If we can't get the local address use what we have already */
-	if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
-		pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
-	} else {
-		if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
-			snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
-				(int)pj_strlen(&prm.ret_addr),
-				pj_strbuf(&prm.ret_addr),
-				prm.ret_port);
+		/* Attempt to determine what IP address we probably received this packet on */
+		pjsip_tpmgr_fla2_param_default(&prm);
+		prm.tp_type = rdata->tp_info.transport->key.type;
+		pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
+		prm.local_if = PJ_TRUE;
+
+		/* If we can't get the local address use what we have already */
+		if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
+			pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
 		} else {
-			snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
-				(int)pj_strlen(&prm.ret_addr),
-				pj_strbuf(&prm.ret_addr),
-				prm.ret_port);
+			if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+				snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+					(int)pj_strlen(&prm.ret_addr),
+					pj_strbuf(&prm.ret_addr),
+					prm.ret_port);
+			} else {
+				snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+					(int)pj_strlen(&prm.ret_addr),
+					pj_strbuf(&prm.ret_addr),
+					prm.ret_port);
+			}
 		}
+	} else {
+		pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
 	}
 
 	uuid = assign_uuid(&rdata->msg_info.cid->id, &rdata->msg_info.to->tag, &rdata->msg_info.from->tag);
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 8e9aae9dded13b7e66a9f8ff283b8178e15f2b9d..c1f9a29d6df0478c542a0da92f4f940350d0230d 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -86,18 +86,19 @@
 
 /*! \brief Structure definition for session */
 struct ast_websocket {
-	struct ast_iostream *stream;       /*!< iostream of the connection */
-	struct ast_sockaddr address;       /*!< Address of the remote client */
-	enum ast_websocket_opcode opcode;  /*!< Cached opcode for multi-frame messages */
-	size_t payload_len;                /*!< Length of the payload */
-	char *payload;                     /*!< Pointer to the payload */
-	size_t reconstruct;                /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
-	int timeout;                       /*!< The timeout for operations on the socket */
-	unsigned int secure:1;             /*!< Bit to indicate that the transport is secure */
-	unsigned int closing:1;            /*!< Bit to indicate that the session is in the process of being closed */
-	unsigned int close_sent:1;         /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
-	struct websocket_client *client;   /*!< Client object when connected as a client websocket */
-	char session_id[AST_UUID_STR_LEN]; /*!< The identifier for the websocket session */
+	struct ast_iostream *stream;        /*!< iostream of the connection */
+	struct ast_sockaddr remote_address; /*!< Address of the remote client */
+	struct ast_sockaddr local_address;  /*!< Our local address */
+	enum ast_websocket_opcode opcode;   /*!< Cached opcode for multi-frame messages */
+	size_t payload_len;                 /*!< Length of the payload */
+	char *payload;                      /*!< Pointer to the payload */
+	size_t reconstruct;                 /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
+	int timeout;                        /*!< The timeout for operations on the socket */
+	unsigned int secure:1;              /*!< Bit to indicate that the transport is secure */
+	unsigned int closing:1;             /*!< Bit to indicate that the session is in the process of being closed */
+	unsigned int close_sent:1;          /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
+	struct websocket_client *client;    /*!< Client object when connected as a client websocket */
+	char session_id[AST_UUID_STR_LEN];  /*!< The identifier for the websocket session */
 };
 
 /*! \brief Hashing function for protocols */
@@ -183,7 +184,7 @@ static void session_destroy_fn(void *obj)
 			ast_iostream_close(session->stream);
 			session->stream = NULL;
 			ast_verb(2, "WebSocket connection %s '%s' closed\n", session->client ? "to" : "from",
-				ast_sockaddr_stringify(&session->address));
+				ast_sockaddr_stringify(&session->remote_address));
 		}
 	}
 
@@ -318,7 +319,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_close)(struct ast_websocket *session, ui
 		ast_iostream_close(session->stream);
 		session->stream = NULL;
 		ast_verb(2, "WebSocket connection %s '%s' forcefully closed due to fatal write error\n",
-			session->client ? "to" : "from", ast_sockaddr_stringify(&session->address));
+			session->client ? "to" : "from", ast_sockaddr_stringify(&session->remote_address));
 	}
 
 	ao2_unlock(session);
@@ -432,7 +433,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_fd)(struct ast_websocket *session)
 
 struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_remote_address)(struct ast_websocket *session)
 {
-	return &session->address;
+	return &session->remote_address;
+}
+
+struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_local_address)(struct ast_websocket *session)
+{
+	return &session->local_address;
 }
 
 int AST_OPTIONAL_API_NAME(ast_websocket_is_secure)(struct ast_websocket *session)
@@ -899,11 +905,21 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
 		return 0;
 	}
 
+	/* Get our local address for the connected socket */
+	if (ast_getsockname(ast_iostream_get_fd(ser->stream), &session->local_address)) {
+		ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to get local address\n",
+			ast_sockaddr_stringify(&ser->remote_address));
+		websocket_bad_request(ser);
+		ao2_ref(session, -1);
+		ao2_ref(protocol_handler, -1);
+		return 0;
+	}
+
 	ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol ? : "", version);
 
 	/* Populate the session with all the needed details */
 	session->stream = ser->stream;
-	ast_sockaddr_copy(&session->address, &ser->remote_address);
+	ast_sockaddr_copy(&session->remote_address, &ser->remote_address);
 	session->opcode = -1;
 	session->reconstruct = DEFAULT_RECONSTRUCTION_CEILING;
 	session->secure = ast_iostream_get_ssl(ser->stream) ? 1 : 0;
@@ -1357,7 +1373,7 @@ static enum ast_websocket_result websocket_client_connect(struct ast_websocket *
 	ws->stream = ws->client->ser->stream;
 	ws->secure = ast_iostream_get_ssl(ws->stream) ? 1 : 0;
 	ws->client->ser->stream = NULL;
-	ast_sockaddr_copy(&ws->address, &ws->client->ser->remote_address);
+	ast_sockaddr_copy(&ws->remote_address, &ws->client->ser->remote_address);
 	return WS_OK;
 }
 
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index 22ec19540dc52839f266aaf75495accb0ff72bbe..b5b6a3e0ade9b500f9f7e25c21be21bd1a19c503 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -206,20 +206,16 @@ static int transport_create(void *data)
 	pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
 	if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {
 		newtransport->transport.key.type = transport_type_wss_ipv6;
-		newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);
-		pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);
 	} else {
 		newtransport->transport.key.type = transport_type_wss;
-		newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);
-		pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);
 	}
 
 	newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
 
-	pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);
-
-	newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
-	newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
+	ws_addr_str = ast_sockaddr_stringify(ast_websocket_local_address(newtransport->ws_session));
+	pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.local_addr);
+	pj_strdup2(pool, &newtransport->transport.local_name.host, ast_sockaddr_stringify_host(ast_websocket_local_address(newtransport->ws_session)));
+	newtransport->transport.local_name.port = ast_sockaddr_port(ast_websocket_local_address(newtransport->ws_session));
 
 	newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
 	newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);