Eu fiz esta pergunta em maio, mas agora estou aqui para responder minha própria pergunta.
Como discutido nos comentários, o servidor MongoDB retornará uma lista de seus membros, com seus endereços configurados. Como um conjunto de réplica Manged MongoDB é configurado com endereços privados, o servidor MongoDB fornecerá endereços particulares do membro.
Para resolver esse problema, precisamos de um proxy dedicado para conexões de cliente do Mongo. O proxy deve interceptar a resposta do servidor MongoDB ao comando isMaster e substituir o endereço privado pelo endereço público do servidor ou pelo endereço do seu servidor proxy. Depois que o cliente receber esses endereços interceptados, eles poderão conectar esses endereços no modo replicaSet.
Aqui está um código no Node.js:
clientConn.on("data", dataHandler(proxyConn, function(data) {
const msg = new WireMessage(data);
if (msg.isCommand("isMaster")) {
remoteClient.recordForInterception(msg);
}
mongoConn.write(data);
}));
mongoConn.on("data", dataHandler(proxyConn, function(data) {
const msg = new WireMessage(data, {skipBody: true});
var changed = false;
if (remoteClient.shouldInterceptReply(msg)) {
// To Intercept message, we need a full parse
msg.parseBody();
changed = remoteClient.interceptReply(clientConn, msg);
}
if (changed) {
// Serialize intercepted data
data = msg.serialize();
}
clientConn.write(data);
}));
interceptReply = function (conn, replyMessage) {
if ('isMaster'.toLowerCase() !== replyMessage.toLowerCase()) {
return false;
}
var doc;
if (replyMessage.body.metadata) {
doc = replyMessage.body.metadata;
} else if (replyMessage.body.documents instanceof Array &&
replyMessage.body.documents.length > 0) {
doc = replyMessage.body.documents[0];
} else {
this.logger.warn("No document to handle: %s.", replyMessage.toString());
return false;
}
return interceptHosts(doc, conn, hostMappings);
};
interceptHosts = function (doc, conn, mappings) {
if (doc.hosts) {
var hosts = doc.hosts;
for (var i = 0; i < hosts.length; ++i) {
var host = hosts[i];
hosts[i] = getReverseAddress(host, conn, mappings);
}
}
if (doc.primary) {
doc.primary = getReverseAddress(doc.primary, conn, mappings);
}
if (doc.me) {
doc.me = getReverseAddress(doc.me, conn, mappings);
}
return doc;
};
function getReverseAddress(endpoint, conn, reverseAddressMapping) {
var hostMap = reverseAddressMapping[endpoint];
if (hostMap && hostMap.host === "0.0.0.0") {
// If we are listening on ANY address, use
// the effective address the client connect us.
return conn.localAddress + ":" + hostMap.port;
} else if (hostMap) {
return hostMap.host + ":" + hostMap.port;
} else {
return endpoint;
}
}
A alteração da biblioteca do cliente para mapear endereços privados para o endereço público deve ser uma solução alternativa. Mas pode ser um trabalho árduo suportar todos os idiomas e enviar sua biblioteca personalizada para a máquina de desenvolvimento do seu parceiro.