diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 53832d0..e0ae721 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -495,6 +495,18 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
        </varlistentry>
 
        <varlistentry>
+        <term><literal>redirect</literal></term>
+        <listitem>
+         <para>
+          Redirects the connection to the alternative server specified if it
+          matches the requested database user name and IP address. This is
+          only available for Protocol Version 3.1 and beyond.
+          See <xref linkend="auth-redirect"/> for details.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
         <term><literal>ldap</literal></term>
         <listitem>
          <para>
@@ -624,7 +636,7 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
    non-null <structfield>error</structfield> fields indicate problems in the
    corresponding lines of the file.
   </para>
- 
+
   <tip>
    <para>
     To connect to a particular database, a user must not only pass the
@@ -1434,6 +1446,29 @@ omicron         bryanh                  guest1
 
   </sect2>
 
+  <sect2 id="auth-redirect">
+   <title>Redirect Authentication</title>
+
+   <indexterm>
+    <primary>redirect</primary>
+   </indexterm>
+
+   <para>
+    This authentication mechanism works by specifying an alternative server to redirect
+    client connections to. The alternative server endpoint is specified by a hostname and port, separated by a single comma.
+   </para>
+
+   <para>
+    An example entry with <productname>redirect</productname> would look like the following:
+    host    all             all             127.0.0.1/32            redirect  <hostname>,<port>
+   </para>
+
+   <para>
+   Support for redirection is only available from wire protocol v3.1 upwards.
+   </para>
+
+  </sect2>
+
   <sect2 id="auth-ldap">
    <title>LDAP Authentication</title>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 3cec9e0..5b58270 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -4747,6 +4747,79 @@ GSSResponse (F)
 
 <varlistentry>
 <term>
+RedirectClient (B)
+</term>
+<listitem>
+<para>
+
+<variablelist>
+<varlistentry>
+<term>
+        Byte1('M')
+</term>
+<listitem>
+<para>
+                Redirects client connection to alternative server.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+        Int32
+</term>
+<listitem>
+<para>
+                Length of message contents in bytes, including self.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+        String
+</term>
+<listitem>
+<para>
+                Parameter name "server" to identify the redirect target host.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+        String
+</term>
+<listitem>
+<para>
+                Specifies the target host name.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+        String
+</term>
+<listitem>
+<para>
+                Parameter name "port" to identify the redirect target port.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term>
+        String
+</term>
+<listitem>
+<para>
+                Specifies the target host's port.
+</para>
+</listitem>
+</varlistentry>
+</variablelist>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
 NegotiateProtocolVersion (B)
 </term>
 <listitem>
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 3014b17..a700a9b 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -206,6 +206,12 @@ static int pg_SSPI_make_upn(char *accountname,
 static int	CheckRADIUSAuth(Port *port);
 static int	PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd);
 
+/*----------------------------------------------------------------
+ * Connection Redirection
+ *----------------------------------------------------------------
+ */
+static int	SendAlternativeServerName(Port *port, char **logdetail);
+
 
 /*
  * Maximum accepted size of GSS and SSPI authentication tokens.
@@ -598,6 +604,9 @@ ClientAuthentication(Port *port)
 		case uaTrust:
 			status = STATUS_OK;
 			break;
+		case uaRedirect:
+			status = SendAlternativeServerName(port, &logdetail);
+			break;
 	}
 
 	if (ClientAuthentication_hook)
@@ -609,6 +618,28 @@ ClientAuthentication(Port *port)
 		auth_failed(port, status, logdetail);
 }
 
+/*
+ * Send alternative server information packet to the frontend.
+ */
+static int
+SendAlternativeServerName(Port *port, char **logdetail)
+{
+	StringInfoData buf;
+
+	CHECK_FOR_INTERRUPTS();
+
+	pq_beginmessage(&buf, 'M');
+	pq_sendstring(&buf, "server");
+	pq_sendstring(&buf, port->hba->alternativeservername);
+	pq_sendstring(&buf, "port");
+	pq_sendstring(&buf, port->hba->alternativeserverport);
+
+	pq_endmessage(&buf);
+	pq_flush();
+	proc_exit(0);
+
+	return STATUS_OK;
+}
 
 /*
  * Send an authentication request packet to the frontend.
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index acf625e..f3f7d6f 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -134,7 +134,8 @@ static const char *const UserAuthName[] =
 	"ldap",
 	"cert",
 	"radius",
-	"peer"
+	"peer",
+	"redirect"
 };
 
 
@@ -1358,6 +1359,8 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
 #endif
 	else if (strcmp(token->string, "radius") == 0)
 		parsedline->auth_method = uaRADIUS;
+	else if (strcmp(token->string, "redirect") == 0)
+		parsedline->auth_method = uaRedirect;
 	else
 	{
 		ereport(elevel,
@@ -1384,6 +1387,49 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
 		return NULL;
 	}
 
+	if (parsedline->auth_method == uaRedirect)
+	{
+		/* Get the alternative server name and port */
+		field = lnext(field);
+		if (!field)
+		{
+			ereport(elevel,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("end-of-line before alternative server name"),
+					 errcontext("line %d of configuration file \"%s\"",
+								line_num, HbaFileName)));
+			*err_msg = "end-of-line before alternative server name";
+			return NULL;
+		}
+		tokens = lfirst(field);
+		if (tokens->length > 2)
+		{
+			ereport(elevel,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("multiple values specified for alternative server"),
+					 errhint("Specify exactly one alternative server per line."),
+					 errcontext("line %d of configuration file \"%s\"",
+								line_num, HbaFileName)));
+			*err_msg = "multiple values specified for alternative server";
+			return NULL;
+		}
+
+		tokencell = list_head(tokens);
+		token = lfirst(tokencell);
+		parsedline->alternativeservername = pstrdup(token->string);
+
+		if (tokens->length == 2)
+		{
+			tokencell = lnext(tokencell);
+			token = lfirst(tokencell);
+			parsedline->alternativeserverport = pstrdup(token->string);
+		}
+		else
+		{
+			pg_itoa(DEF_PGPORT, parsedline->alternativeserverport);
+		}
+	}
+
 	/*
 	 * XXX: When using ident on local connections, change it to peer, for
 	 * backwards compatibility.
@@ -2100,6 +2146,21 @@ check_hba(hbaPort *port)
 		if (!check_role(port->user_name, roleid, hba->roles))
 			continue;
 
+		/*
+		 * Check the protocol version to see if the client supports
+		 * redirection
+		 */
+		if (hba->auth_method == uaRedirect &&
+			PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
+			(PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
+			 PG_PROTOCOL_MINOR(port->proto) < PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
+			ereport(FATAL,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("Redirection is only supported by protocol version 3.1 and above. \
+							Try connecting to %s:%s directly",
+							hba->alternativeservername,
+							hba->alternativeserverport)));
+
 		/* Found a record that matched! */
 		port->hba = hba;
 		return;
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index c853e36..3af0972 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -43,7 +43,7 @@
 # directly connected to.
 #
 # METHOD can be "trust", "reject", "md5", "password", "scram-sha-256",
-# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert".
+# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius", "cert" or "redirect".
 # Note that "password" sends passwords in clear text; "md5" or
 # "scram-sha-256" are preferred since they send encrypted passwords.
 #
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 5f68f4c..1e4f2bd 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -38,8 +38,9 @@ typedef enum UserAuth
 	uaLDAP,
 	uaCert,
 	uaRADIUS,
-	uaPeer
-#define USER_AUTH_LAST uaPeer	/* Must be last value of this enum */
+	uaPeer,
+	uaRedirect
+#define USER_AUTH_LAST uaRedirect	/* Must be last value of this enum */
 } UserAuth;
 
 typedef enum IPCompareMethod
@@ -99,6 +100,8 @@ typedef struct HbaLine
 	char	   *radiusidentifiers_s;
 	List	   *radiusports;
 	char	   *radiusports_s;
+	char	   *alternativeservername;
+	char	   *alternativeserverport;
 } HbaLine;
 
 typedef struct IdentLine
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 77eebb0..26fa934 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -129,6 +129,7 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
 #else
 #define DefaultSSLMode	"disable"
 #endif
+#define DefaultRedirectionLimit "2"
 
 /* ----------
  * Definition of the conninfo parameters and their fallback resources.
@@ -266,7 +267,7 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 
 	{"scram_channel_binding", NULL, DefaultSCRAMChannelBinding, NULL,
 		"SCRAM-Channel-Binding", "D",
-		21,	/* sizeof("tls-server-end-point") == 21 */
+		21,						/* sizeof("tls-server-end-point") == 21 */
 	offsetof(struct pg_conn, scram_channel_binding)},
 
 	/*
@@ -330,6 +331,11 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"Target-Session-Attrs", "", 11, /* sizeof("read-write") = 11 */
 	offsetof(struct pg_conn, target_session_attrs)},
 
+	{"redirect_limit", "PGREDIRECTLIMIT",
+		DefaultRedirectionLimit, NULL,
+		"Redirection-Count", "", 10,	/* strlen(INT32_MAX) == 10 */
+	offsetof(struct pg_conn, redirect_limit)},
+
 	/* Terminating entry --- MUST BE LAST */
 	{NULL, NULL, NULL, NULL,
 	NULL, NULL, 0}
@@ -1805,11 +1811,11 @@ connectDBStart(PGconn *conn)
 #endif
 
 	/*
-	 * Set up to try to connect, with protocol 3.0 as the first attempt.
+	 * Set up to try to connect, with protocol 3.1 as the first attempt.
 	 */
 	conn->whichhost = 0;
 	conn->addr_cur = conn->connhost[0].addrlist;
-	conn->pversion = PG_PROTOCOL(3, 0);
+	conn->pversion = PG_PROTOCOL(3, 1);
 	conn->send_appname = true;
 	conn->status = CONNECTION_NEEDED;
 
@@ -2007,6 +2013,14 @@ PQconnectPoll(PGconn *conn)
 	int			optval;
 	PQExpBufferData savedMessage;
 
+	/* Variable declarations for redirection. */
+	int			originalMsgLen; /* Length in bytes of message sans msg type */
+	int			runningMsgLen;	/* Length in bytes of message sans metadata */
+	int			availableMsgLen;
+	char	   *altServer = NULL;
+	char	   *altPort = NULL;
+	bool		redirectionError = false;	/* Flag used to mark exceptions */
+
 	if (conn == NULL)
 		return PGRES_POLLING_FAILED;
 
@@ -2024,6 +2038,7 @@ PQconnectPoll(PGconn *conn)
 
 			/* These are reading states */
 		case CONNECTION_AWAITING_RESPONSE:
+		case CONNECTION_REDIRECTION:
 		case CONNECTION_AUTH_OK:
 			{
 				/* Load waiting data */
@@ -2655,6 +2670,25 @@ keep_going:						/* We will come back to here until there is
 					return PGRES_POLLING_READING;
 				}
 
+				if (beresp == 'M')
+				{
+					conn->status = CONNECTION_REDIRECTION;
+					goto keep_going;
+				}
+
+				/*
+				 * If server sends protocol negotiation message, default to
+				 * 3.0 protocol.
+				 */
+				if (beresp == 'v')
+				{
+					conn->pversion = PG_PROTOCOL(3, 0);
+					/* Must drop the old connection */
+					pqDropConnection(conn, true);
+					conn->status = CONNECTION_NEEDED;
+					goto keep_going;
+				}
+
 				/*
 				 * Validate message type: we expect only an authentication
 				 * request or an error here.  Anything else probably means
@@ -2722,19 +2756,28 @@ keep_going:						/* We will come back to here until there is
 					appendPQExpBufferChar(&conn->errorMessage, '\n');
 
 					/*
-					 * If we tried to open the connection in 3.0 protocol,
-					 * fall back to 2.0 protocol.
+					 * If we tried to open the connection in 3.1 protocol,
+					 * fall back to 3.0 protocol. If that fails as well, fall
+					 * back to 2.0 protocol.
 					 */
-					if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+					if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3
+						&& PG_PROTOCOL_MINOR(conn->pversion) >= 1)
+					{
+						conn->pversion = PG_PROTOCOL(3, 0);
+					}
+					else if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
 					{
 						conn->pversion = PG_PROTOCOL(2, 0);
-						/* Must drop the old connection */
-						pqDropConnection(conn, true);
-						conn->status = CONNECTION_NEEDED;
-						goto keep_going;
+					}
+					else
+					{
+						goto error_return;
 					}
 
-					goto error_return;
+					/* Must drop the old connection */
+					pqDropConnection(conn, true);
+					conn->status = CONNECTION_NEEDED;
+					goto keep_going;
 				}
 
 				/*
@@ -3097,6 +3140,146 @@ keep_going:						/* We will come back to here until there is
 				conn->status = CONNECTION_OK;
 				return PGRES_POLLING_OK;
 			}
+
+		case CONNECTION_REDIRECTION:
+			{
+				/*
+				 * Check if the number of redirect attempts exceeds the limit.
+				 */
+				if (++conn->nRedirection > atoi(conn->redirect_limit))
+				{
+					appendPQExpBuffer(&conn->errorMessage,
+									  libpq_gettext("Exceeded the maximum number of redirection attempts."));
+					goto error_return;
+				}
+
+				/* Mark 'M' consumed: a single byte for message type. */
+				conn->inCursor = conn->inStart + 1;
+
+				/* Obtain message length from packet. */
+				if (pqGetInt(&originalMsgLen, sizeof(int32), conn))
+					return PGRES_POLLING_READING;
+
+				/* Obtain the number of bytes in payload. */
+				runningMsgLen = originalMsgLen - sizeof(int32);
+
+				/*
+				 * Enlarge buffer if payload's size is greater than what is
+				 * available.
+				 */
+				availableMsgLen = conn->inEnd - conn->inCursor;
+				if (availableMsgLen < runningMsgLen)
+				{
+					if (pqCheckInBufferSpace(conn->inCursor + (size_t) runningMsgLen, conn))
+						return PGRES_POLLING_READING;
+				}
+
+				PQExpBuffer buf = createPQExpBuffer();
+
+				while (pqGets(buf, conn) != EOF)
+				{
+					if (!strcmp(buf->data, "server"))
+					{
+						if (pqGets(buf, conn) == EOF)
+						{
+							appendPQExpBuffer(&conn->errorMessage,
+											  libpq_gettext("failed to obtain server value from redirection packet"));
+
+							redirectionError = true;
+							break;
+						}
+						altServer = strdup(buf->data);
+					}
+					else if (!strcmp(buf->data, "port"))
+					{
+						if (pqGets(buf, conn) == EOF)
+						{
+							appendPQExpBuffer(&conn->errorMessage,
+											  libpq_gettext("failed to obtain port value from redirection packet"));
+
+							redirectionError = true;
+							break;
+						}
+						altPort = strdup(buf->data);
+					}
+					else
+					{
+						appendPQExpBuffer(&conn->errorMessage,
+										  libpq_gettext("unknown key in redirection server packet"));
+						redirectionError = true;
+					}
+
+					if (redirectionError)
+					{
+						/* Free buffer to prevent memory leak on error. */
+						destroyPQExpBuffer(buf);
+
+						/* Free strdup'd variables. */
+						if (altServer)
+							free(altServer);
+
+						if (altPort)
+							free(altPort);
+
+						goto error_return;
+					}
+
+					/*
+					 * Buffer length does not account for null-terminated
+					 * strings.
+					 */
+					runningMsgLen -= buf->len + 1;
+				}
+
+				/* Free buffer used for reading string params in packet. */
+				destroyPQExpBuffer(buf);
+
+				/* Check for extraneous data in packet. */
+				if (conn->inCursor != conn->inStart + 1 + originalMsgLen)
+				{
+					appendPQExpBuffer(&conn->errorMessage,
+									  libpq_gettext("Extraneous data in redirection packet from server\n"));
+
+					/* Free strdup'd variables. */
+					if (altServer)
+						free(altServer);
+
+					if (altPort)
+						free(altPort);
+
+					goto error_return;
+				}
+
+				/* Mark incoming data consumed */
+				conn->inStart = conn->inCursor;
+
+				/* Drop existing connection. */
+				pqDropConnection(conn, true);
+
+				/* Set connection parameters. */
+				if (conn->pghost)
+				{
+					free(conn->pghost);
+					conn->pghost = altServer;
+				}
+
+				if (conn->pgport)
+				{
+					free(conn->pgport);
+					conn->pgport = altPort;
+				}
+
+				/* connectDBStart() sets appropriate connection status. */
+				if (!connectOptions2(conn) || !connectDBStart(conn))
+				{
+					conn->status = CONNECTION_BAD;
+					appendPQExpBuffer(&conn->errorMessage,
+									  libpq_gettext("Failed to establish connection to redirected database\n"));
+				}
+
+				goto keep_going;
+			}
+
 		case CONNECTION_CHECK_WRITABLE:
 			{
 				const char *displayed_host;
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index ed9c806..38616d2 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -65,8 +65,10 @@ typedef enum
 	CONNECTION_NEEDED,			/* Internal state: connect() needed */
 	CONNECTION_CHECK_WRITABLE,	/* Check if we could make a writable
 								 * connection. */
-	CONNECTION_CONSUME			/* Wait for any pending message and consume
+	CONNECTION_CONSUME,			/* Wait for any pending message and consume
 								 * them. */
+	CONNECTION_REDIRECTION		/* Redirecting the connection to the
+								 * alternative server specified in pg_hba.conf */
 } ConnStatusType;
 
 typedef enum
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index eba23dc..d4edd40 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -349,7 +349,7 @@ struct pg_conn
 										 * retransmits */
 	char	   *keepalives_count;	/* maximum number of TCP keepalive
 									 * retransmits */
-	char	   *scram_channel_binding; /* SCRAM channel binding type */
+	char	   *scram_channel_binding;	/* SCRAM channel binding type */
 	char	   *sslmode;		/* SSL mode (require,prefer,allow,disable) */
 	char	   *sslcompression; /* SSL compression (0 or 1) */
 	char	   *sslkey;			/* client key filename */
@@ -495,6 +495,10 @@ struct pg_conn
 
 	/* Buffer for receiving various parts of messages */
 	PQExpBufferData workBuffer; /* expansible string */
+
+	char	   *redirect_limit; /* Specifies the maximum number of times to
+								 * attempt redirection. */
+	int			nRedirection;	/* Number of redirects attempted so far */
 };
 
 /* PGcancel stores all data necessary to cancel a connection. A copy of this
@@ -742,8 +746,8 @@ extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
  *
  */
 extern int pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
-														   int *names_examined,
-														   char **first_name);
+												int *names_examined,
+												char **first_name);
 
 /* === miscellaneous macros === */
 
diff --git a/src/test/authentication/t/003_redirection.pl b/src/test/authentication/t/003_redirection.pl
new file mode 100644
index 0000000..db0b78c
--- /dev/null
+++ b/src/test/authentication/t/003_redirection.pl
@@ -0,0 +1,92 @@
+# Test redirection authentication method.
+#
+# This test cannot run on Windows as Postgres cannot be set up with Unix
+# sockets and needs to go through SSPI.
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More;
+if ($windows_os)
+{
+	plan skip_all => "authentication tests cannot run on Windows";
+}
+else
+{
+	plan tests => 3;
+}
+
+# Delete pg_hba.conf from the given node, add a new entry to it
+# and then execute a reload to refresh it.
+sub reset_pg_hba
+{
+	my $node       = shift;
+	my $hba_method = shift;
+	my $redirect_endpoint = shift;
+
+	unlink($node->data_dir . '/pg_hba.conf');
+	$node->append_conf('pg_hba.conf', "local all all $hba_method $redirect_endpoint");
+	$node->reload;
+}
+
+# Test access for a single role, useful to wrap all tests into one.
+sub test_login
+{
+	my $node          = shift;
+	my $role          = shift;
+	my $password      = shift;
+	my $expected_res  = shift;
+	my $status_string = 'failed';
+
+	$status_string = 'success' if ($expected_res eq 0);
+
+	$ENV{"PGPASSWORD"} = $password;
+	my $res = $node->psql('postgres', undef, extra_params => [ '-U', $role ]);
+	is($res, $expected_res,
+		"authentication $status_string for role $role with password $password"
+	);
+}
+
+# Initialize node1.
+my $node1 = get_new_node('master');
+$node1->init;
+$node1->start;
+$node1->safe_psql(
+	'postgres',
+	"CREATE ROLE pguser1 LOGIN PASSWORD 'postgres';
+");
+
+# Initialize node2, the redirect target.
+my $node2 = get_new_node('redirect');
+$node2->init;
+$node2->start;
+$node2->safe_psql(
+	'postgres',
+	"CREATE ROLE pguser2 LOGIN PASSWORD 'postgres';
+");
+
+# Host is identical as both nodes reside on the same machine
+my $host = $node1->host;
+
+my $node1_port = $node1->port;
+# 1. Test a redirected connection from node1 to itself.
+# Add the redirect authentication method to the node1's pg_hba.conf to set up redirection to itself.
+reset_pg_hba($node1, 'redirect', "$host,$node1_port");
+# A redirect from a node to itself should fail after PGREDIRECTLIMIT (default is 5) retries.
+test_login($node1, 'pguser1', "postgres",   2);
+
+
+my $node2_port = $node2->port;
+# 2. Test a redirected connection from node1 to node2 with correct creds.
+# Add the redirect authentication method to the node1's pg_hba.conf to set up redirection to node2.
+reset_pg_hba($node1, 'redirect', "$host,$node2_port");
+# A redirect from a node to another should succeed, given the correct creds are used.
+test_login($node1, 'pguser2', "postgres",   0);
+
+
+# 3. Test a redirected connection from node1 to node2 with wrong creds.
+# Add the redirect authentication method to the node1's pg_hba.conf to set up redirection to node2.
+reset_pg_hba($node1, 'redirect', "$host,$node2_port");
+# A redirect from a node to another should fail if the wrong creds are used.
+test_login($node1, 'pguser', "postgres",   2);
