Nicolas Cognaux - Tech entrepreneur & engineer

I share about development, productivity, open source and entrepreneurship.

How to connect to Mongo Atlas in a VPC

2020-03-21 Nicolas Cognaux 4 min readDevelopment

At Seety, we recently switched from self-hosted Mongo cluster to Mongo Atlas, the hosted and managed MongoDB cluster. It’s a relief for me as they manage the cluster, the backups, the updates, the security, etc.

Mongo Atlas comes with great features but the one that convinced me to switch was the ability to peer the cluster directly with an existing VPC (Google, Azure or AWS). That enhances the security of the communication as everything is routed on a private network and no access is given on a public IP address. However, it also locks the developers out. Access to the DB is always interesting for maintenances or debugging.

Previously, I was simply using a port forwarding to our mongo servers in our Kubernetes cluster, but it’s not possible anymore as the Mongo Atlas cluster isn’t accessible directly. The solution I found is using SSH tunneling to a machine connected to the VPC, and I thought it can help some others!

Connect via the URL ?

To connect to the mongo atlas cluster, we use the mongodb URI (in this form):

mongodb://username:[email protected]:27017,your-cluster-00-01-abc.gcp.mongodb.net:27017,your-cluster-00-02-abc.gcp.mongodb.net:27017/database?ssl=true&replicaSet=your-cluster-0&authSource=admin&retryWrites=true&w=majority

This URI refers to 3 different servers (the members of the cluster):

  • your-cluster-00-00-abc.gcp.mongodb.net
  • your-cluster-00-01-abc.gcp.mongodb.net
  • your-cluster-00-02-abc.gcp.mongodb.net

Trying to get their IPs, will only show private IPs (only accessible from within the VPC). Here is an example of a dig output on one of the servers:

; <<>> DiG 9.11.5-P4-5.1ubuntu2.1-Ubuntu <<>> your-cluster-00-00-abc.gcp.mongodb.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49806
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;your-cluster-00-00-abc.gcp.mongodb.net.	IN A

;; ANSWER SECTION:
your-cluster-00-00-abc.gcp.mongodb.net.	60 IN A	192.168.144.12

;; Query time: 20 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sat Mar 21 14:42:21 CET 2020
;; MSG SIZE  rcvd: 91

The returned IP is 192.168.144.12 (obviously not accessible from my computer). Thus, you’ll need a connexion inside your VPC to access this IP.

The SSH Tunnel

The solution to be able to connect to those local IPs is an SSH tunnel to a machine connected to the VPC. To do so, we have a VM connected to our VPC, for back-office access, only accessible from the office’s IP or via our VPN, this instance is only running an SSH server.

We create an SSH tunnel with the following command (assuming 123.123.123.123 is the SSH server’s IP):

ssh 123.123.123.123 -N \
  -L 127.0.1.1:27017:your-cluster-00-00-abc.gcp.mongodb.net:27017 \
  -L 127.0.1.2:27017:your-cluster-00-01-abc.gcp.mongodb.net:27017 \
  -L 127.0.2.3:27017:your-cluster-00-02-abc.gcp.mongodb.net:27017

This command actually redirects requests you make from your local machine to 127.0.1.1 to your-cluster-00-00-abc.gcp.mongodb.net (on the SSH server), 127.0.1.2 to your-cluster-00-01-abc.gcp.mongodb.net and 127.0.1.3 to your-cluster-00-02-abc.gcp.mongodb.net.

We can now connect to the mongo cluster, through the SSH tunnel with the following URL (via the local IPs):

mongodb://username:[email protected]:27017,127.0.1.2:27017,127.0.1.3:27017/database?ssl=true&replicaSet=your-cluster-0&authSource=admin&retryWrites=true&w=majority

Invalid Hostnames

You’ll, however, receive a warning about the certificates not matching the domain names. For that, you have two possibilities, either you ignore it simply with the --tlsAllowInvalidHostnames parameter of the mongo CLI, or you edit your /etc/hosts file to resolve your-cluster-00-00-abc.gcp.mongodb.net to 127.0.1.1 etc. That’s the solution I followed and added those lines to my /etc/hosts:

127.0.1.1     your-cluster-00-00-abc.gcp.mongodb.net
127.0.1.2     your-cluster-00-01-abc.gcp.mongodb.net
127.0.1.3     your-cluster-00-02-abc.gcp.mongodb.net

A script that does it for you ?

Because I want the whole development team to be able to connect to the production and/or preproduction database cluster, I created a small script that automates the tunnel and asks for the /etc/hosts edit if not done already:

#!/bin/bash

# Infos about ssh server (tunnel)
SSH_SERVER=123.123.123.123 # <== IP of your SSH server here
PORT=22 # <== Port of your SSH server here (default is 22)

# Local subnet to use (Local subnet to avoid conflicts)
SUBNET=127.0.1

# Infos about Mongo Atlas Cluster (Prod cluster)
SERV0=your-cluster-00-00-abc.gcp.mongodb.net
SERV1=your-cluster-00-01-abc.gcp.mongodb.net
SERV2=your-cluster-00-02-abc.gcp.mongodb.net

# Check the /etc/hosts file and aask changes if needed
if grep -q $SERV0 "/etc/hosts"; then
  echo "/etc/hosts is already OK"
else
  echo "Be sure to have those lines in your /etc/hosts file"
  echo "$SUBNET.1       $SERV0"
  echo "$SUBNET.2       $SERV1"
  echo "$SUBNET.3       $SERV2"
  read -p "Press [Enter] when it's in /etc/hosts"
fi;

echo "Connected! Use Ctrl+C to exit."
ssh $SSH_SERVER -p $PORT -N \
    -L $SUBNET.1:27017:$SERV0:27017 \
    -L $SUBNET.2:27017:$SERV1:27017 \
    -L $SUBNET.3:27017:$SERV2:27017

echo "Disconnected!"

I hope this post will be useful for you! Don’t hesitate to give feedback and follow me on Twitter!

Don't miss an episode!

Nicolas Cognaux (Gp2mv3) - Tech entrepreneur & engineer

About Nicolas Cognaux

Entrepreneur and CTO. I’m an electrical engineer and passionate about software development. I post about technologies, entrepreneurship, projects, and geeky stuff. Follow me on social media to stay updated.

Don't miss an episode!