diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 80888c32ab8251f6c01275021018e881ac4431ad..2d57208e656ef6998a29d6ce0829ade15a4330ce 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -737,6 +737,9 @@
                         ; (default: "0")
 ;t38_udptl_nat=no       ; Whether NAT support is enabled on UDPTL sessions
                         ; (default: "no")
+;t38_bind_rtp_to_media_address=     ; Bind the UDPTL session to the media_address.
+                                    ; This causes all UDPTL packets to be sent from
+                                    ; the specified address. (default: "no")
 ;tone_zone=     ; Set which country s indications to use for channels created
                 ; for this endpoint (default: "")
 ;language=      ; Set the default language to use for channels created for this
diff --git a/contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py b/contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py
new file mode 100644
index 0000000000000000000000000000000000000000..2d9a58cad8f6597eaf8df2204eef2075e00684dc
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py
@@ -0,0 +1,29 @@
+"""add t38_bind_udptl_to_media_address
+
+Revision ID: a06d8f8462d9
+Revises: f56d79a9f337
+Create Date: 2021-09-24 10:03:01.320480
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a06d8f8462d9'
+down_revision = 'f56d79a9f337'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+AST_BOOL_NAME = 'ast_bool_values'
+AST_BOOL_VALUES = [ '0', '1',
+                    'off', 'on',
+                    'false', 'true',
+                    'no', 'yes' ]
+
+def upgrade():
+    ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False)
+    op.add_column('ps_endpoints', sa.Column('t38_bind_udptl_to_media_address', ast_bool_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 't38_bind_udptl_to_media_address')
diff --git a/doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt b/doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d7bc8a1e9fb836864bc767211d6e075a76f599c3
--- /dev/null
+++ b/doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt
@@ -0,0 +1,9 @@
+Subject: res_pjsip_t38
+
+In res_pjsip_sdp_rtp, the bind_rtp_to_media_address option and the
+fallback use of the transport's bind address solve problems sending
+media on systems that cannot send ipv4 packets on ipv6 sockets, and
+certain other situations. This change extends both of these behaviors
+to UDPTL sessions as well in res_pjsip_t38, to fix fax-specific
+problems on these systems, introducing a new option
+endpoint/t38_bind_udptl_to_media_address.
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 8c5b775bf5db7f2f15523bad6c14095b15951b9e..7b9dcbd51d0f742af344ec5509fe726ffd19f1f5 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -760,6 +760,8 @@ struct ast_sip_t38_configuration {
 	unsigned int nat;
 	/*! Whether to use IPv6 for UDPTL or not */
 	unsigned int ipv6;
+	/*! Bind the UDPTL instance to the media_address */
+	unsigned int bind_udptl_to_media_address;
 };
 
 /*!
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index a375fe083b34112707a5e883f6545c444d9223af..2b30317738545bcf9c3e26f417e844c6193e73a0 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -940,6 +940,13 @@
 						When enabled the UDPTL stack will use IPv6.
 					</para></description>
 				</configOption>
+				<configOption name="t38_bind_udptl_to_media_address" default="no">
+					<synopsis>Bind the UDPTL instance to the media_adress</synopsis>
+					<description><para>
+						If media_address is specified, this option causes the UDPTL instance to be bound to
+						the specified ip address which causes the packets to be sent from that address.
+					</para></description>
+				</configOption>
 				<configOption name="tone_zone">
 					<synopsis>Set which country's indications to use for channels created for this endpoint.</synopsis>
 				</configOption>
@@ -2783,6 +2790,9 @@
 				<parameter name="T38UdptlIpv6">
 					<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='t38_udptl_ipv6']/synopsis/node())"/></para>
 				</parameter>
+				<parameter name="T38BindUdptlToMediaAddress">
+					<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='t38_bind_udptl_to_media_address']/synopsis/node())"/></para>
+				</parameter>
 				<parameter name="ToneZone">
 					<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='tone_zone']/synopsis/node())"/></para>
 				</parameter>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 6defa7cb96a542d75ae9a13dad7b90afe52bd71c..c27b587076d79b3809b526331fbe77f3f3772596 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -2077,6 +2077,7 @@ int ast_res_pjsip_initialize_configuration(void)
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_bind_udptl_to_media_address", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.bind_udptl_to_media_address));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature));
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 5d7f68d09559ed8bbbd42a88b9e2b7ac7f86e94f..7df35d9b2ae0aa409ae2a934c25f4211d7b158b4 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -255,11 +255,52 @@ static struct t38_state *t38_state_get_or_alloc(struct ast_sip_session *session)
 /*! \brief Initializes UDPTL support on a session, only done when actually needed */
 static int t38_initialize_session(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 {
+	struct ast_sockaddr temp_media_address;
+	struct ast_sockaddr *media_address = &address;
+
 	if (session_media->udptl) {
 		return 0;
 	}
 
-	if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) {
+	if (session->endpoint->media.t38.bind_udptl_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
+		if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) {
+			ast_debug(5, "Endpoint %s: Binding UDPTL media to %s\n",
+				ast_sorcery_object_get_id(session->endpoint),
+				session->endpoint->media.address);
+			media_address = &temp_media_address;
+		} else {
+			ast_debug(5, "Endpoint %s: UDPTL media address invalid: %s\n",
+				ast_sorcery_object_get_id(session->endpoint),
+				session->endpoint->media.address);
+		}
+	} else {
+		struct ast_sip_transport *transport;
+
+		transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
+				session->endpoint->transport);
+		if (transport) {
+			struct ast_sip_transport_state *trans_state;
+
+			trans_state = ast_sip_get_transport_state(ast_sorcery_object_get_id(transport));
+			if (trans_state) {
+				char hoststr[PJ_INET6_ADDRSTRLEN];
+
+				pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0);
+				if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) {
+					ast_debug(5, "Transport %s bound to %s: Using it for UDPTL media.\n",
+						session->endpoint->transport, hoststr);
+					media_address = &temp_media_address;
+				} else {
+					ast_debug(5, "Transport %s bound to %s: Invalid for UDPTL media.\n",
+						session->endpoint->transport, hoststr);
+				}
+				ao2_ref(trans_state, -1);
+			}
+			ao2_ref(transport, -1);
+		}
+	}
+
+	if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address))) {
 		return -1;
 	}