How to Properly Connect to MongoDB Replica Set Through Proxy Servers


2 views

When working with MongoDB replica sets behind proxy servers, a common pain point emerges: while standalone connections work fine, replica set mode fails because the driver receives internal addresses from the isMaster response. Here's why this happens:

// What the driver sees from isMaster response:
{
  "hosts": [
    "member1-private-ip:27017",
    "member2-private-ip:27017",
    "member3-private-ip:27017"
  ],
  "setName": "replcaSetName",
  "ismaster": false,
  "secondary": true
}

The most reliable approach is to configure DNS records that map to your proxy servers:

  1. Create DNS entries for each member (member1.yourdomain.com → proxy-public-ip:27017)
  2. Configure MongoDB to use these DNS names in replica set configuration
// Replica set configuration example:
rs.initiate({
  _id: "replcaSetName",
  members: [
    { _id: 0, host: "member1.yourdomain.com:27017" },
    { _id: 1, host: "member2.yourdomain.com:27018" },
    { _id: 2, host: "member3.yourdomain.com:27019" }
  ]
})

For quick testing or temporary solutions, you can use these MongoDB URI options:

mongodb://usr:pwd@proxy-server-public-ip:27017,proxy-server-public-ip:27018,proxy-server-public-ip:27019/db?
replicaSet=replcaSetName&
connectTimeoutMS=30000&
socketTimeoutMS=30000&
serverSelectionTimeoutMS=50000&
retryWrites=true&
readPreference=secondaryPreferred

For enhanced security, consider creating SSH tunnels instead of direct proxy:

# Create multiple SSH tunnels
ssh -N -L 27017:member1-private-ip:27017 user@proxy-server-public-ip
ssh -N -L 27018:member2-private-ip:27017 user@proxy-server-public-ip
ssh -N -L 27019:member3-private-ip:27017 user@proxy-server-public-ip

Then connect using localhost:

mongodb://usr:pwd@localhost:27017,localhost:27018,localhost:27019/db?replicaSet=replcaSetName
  • Monitor proxy connection limits (MongoDB drivers maintain multiple connections)
  • Implement connection pooling properly
  • Set appropriate timeouts based on your network latency
  • Consider using a dedicated proxy like HAProxy with MongoDB-specific configuration
# Example HAProxy configuration
frontend mongodb_front
  bind *:27017
  mode tcp
  timeout client 3600s
  default_backend mongodb_back

backend mongodb_back
  mode tcp
  balance leastconn
  timeout server 3600s
  timeout connect 10s
  server mongo1 member1-private-ip:27017 check
  server mongo2 member2-private-ip:27017 check
  server mongo3 member3-private-ip:27017 check

When working with MongoDB replica sets behind a proxy, you'll encounter a fundamental problem: the replica set members communicate their internal network addresses to clients through the isMaster response. Here's what happens:

// What the client receives when connecting
{
  "hosts": [
    "member1-private-ip:27017",
    "member2-private-ip:27017", 
    "member3-private-ip:27017"
  ],
  "setName": "replcaSetName",
  "ismaster": true
}

The MongoDB driver follows these steps when connecting:
1. Contacts the initial seed list (your proxy addresses)
2. Receives the replica set configuration with internal IPs
3. Attempts to connect directly to those internal IPs (which fails)

Solution 1: DNS Rewriting

Create DNS entries that map the internal hostnames to your proxy public IPs:

member1.yourdomain.com -> proxy-public-ip
member2.yourdomain.com -> proxy-public-ip
member3.yourdomain.com -> proxy-public-ip

Then connect using:

mongoUri = new MongoClientURI(
  "mongodb://usr:pwd@member1.yourdomain.com:27017," +
  "member2.yourdomain.com:27018," +
  "member3.yourdomain.com:27019/db?replicaSet=replcaSetName"
);

Solution 2: Connection String Modifications

Use the directConnection option in modern drivers (4.0+):

mongoUri = new MongoClientURI(
  "mongodb://usr:pwd@proxy-public-ip:27017," +
  "proxy-public-ip:27018," +
  "proxy-public-ip:27019/db?" +
  "replicaSet=replcaSetName&directConnection=false"
);

For HAProxy users:

frontend mongodb_front
  bind *:27017
  mode tcp
  option tcplog
  default_backend mongodb_back

backend mongodb_back
  mode tcp
  option tcp-check
  server mongo1 member1-private-ip:27017 check
  server mongo2 member2-private-ip:27017 check
  server mongo3 member3-private-ip:27017 check

For Node.js MongoDB driver:

const { MongoClient } = require('mongodb');
const client = new MongoClient(
  'mongodb://proxy-public-ip:27017,proxy-public-ip:27018/db?replicaSet=replcaSetName',
  {
    directConnection: false,
    retryWrites: true,
    serverSelectionTimeoutMS: 5000,
    socketTimeoutMS: 20000
  }
);

Always ensure:

  • Proxy connections use TLS/SSL
  • Implement IP whitelisting on the proxy
  • Use MongoDB SCRAM authentication
  • Rotate credentials regularly