Watch keynotes and sessions from MongoDB.live, our virtual developer conference.

Tunneling (Port forwarding) with MongoDB Go driver is not working

I am trying to connect aws documentdb from local environment following the docs https://docs.aws.amazon.com/documentdb/latest/developerguide/connect-from-outside-a-vpc.html
i am able to connect from mongo shell but not from GO application

Tunneling command
ssh -L 27017::27017 @ -N

Mongo Shell(this is working)
mongo --sslAllowInvalidHostnames --ssl --host localhost:27017 --sslCAFile rds-combined-ca-bundle.pem --username --password

Sample Go codes(This is not working)
connectionURI := mongodb://:@localhost:27017/?sslCAFile=rds-combined-ca-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&ssl=true&sslAllowInvalidHostnames=true&retryWrites=false&sslInsecure=true&sslVerifyCertificate=false

tlsConfig, err := getCustomTLSConfig(caFilePath)
if err != nil {
fmt.Printf(“Failed getting TLS configuration: %v”, err)
}

// Connect to MongoDB
client, err := mongo.NewClient(options.Client().ApplyURI(connectionURI).SetTLSConfig(tlsConfig))
//client, err := mongo.NewClient(options.Client().ApplyURI(connectionURI))
if err != nil {
fmt.Println("client error: ", err)
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

err = client.Connect(ctx)
if err != nil {
fmt.Println("connect error: ", err)
}

ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

err = client.Ping(ctx, nil)

if err != nil {
fmt.Println("ping error: ", err)
}

fmt.Println(“Connected to MongoDB!”)

collection := client.Database(“mytestdb”).Collection(“mytestcollection”)

res, err := collection.InsertOne(context.TODO(), bson.M{“name”: “pi”, “value”: 3.14159})
if err != nil {
fmt.Printf(“Failed to insert document: %v”, err)
}

getting following errors
i. ping error: context deadline exceeded
ii. Failed to insert document: server selection error: server selection timeout, current topology: { Type: ReplicaSetNoPrimary, Servers: [{ Addr: test-1.test.us-west-2.docdb.amazonawscom:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : connection(test-docdb-1.test.us-west-2.docdb.amazonawscom:27017[-3]) incomplete read of message header: EOF }, { Addr: test-docdb-3.test.us-west-2.docdb.amazonawscom:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : connection(test-docdb-3.test.us-west-2.docdb.amazonawscom:27017[-4]) incomplete read of message header: EOF }, { Addr: test-docdb-2.test.us-west-2.docdb.amazonawscom:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : connection(test-docdb-2.test.us-west-2.docdb.amazonawscom:27017[-5]) incomplete read of message header: EOF }, ]

I would greatly appreciate for any help/suggestion.

(I am new to Go language)
Thanks

Hi @Manoj_Maharjan, and welcome to the forum!

Please note that AWS DocumentDB API is an emulation of MongoDB which differs in features, compatibility, and implementation from an actual MongoDB deployment. Their suggestion of API version support (eg 3.6) is referring to the wire protocol used rather than the full MongoDB feature set for that version. Official MongoDB drivers (i.e. MongoDB Go driver) are only tested against actual MongoDB deployments.

For further questions on AWS DocumentDB connections I’d suggest to contact AWS.

Depending on your requirements, you may find it useful to know that MongoDB Atlas clusters can be deployed in AWS, GCP, and Azure. MongoDB Atlas also supports network peering connections for AWS, GCP and Azure-backed clusters. See also MongoDB Atlas: Set up a Network Peering Connection.
For more information, see Connect to an Atlas cluster

Regards,
Wan.

2 Likes

I am having the same issue in a similar situation (using AWS DocumentDB). The issue seems to be entirely within the driver before any commands are sent to the server.

I tried to trace it back but wasn’t able to follow the driver code very well. What seems to be happening is that the driver appears to recurse through the connection a couple of times to apply changes, and it ends up replacing the “localhost” address with the TLS server name (the DocDB instance) at some point. Since the address of the instance is not Internet-connected, the connection fails and the entire process aborts. The connection must be made through localhost via the SSH tunnel.

When I add c.addr = "localhost:27017" to the top of (*topology.connection).connect(...), which forces the update to the address to be undone, I am able to establish a connection. I am not certain whether the behavior described earlier is a bug or not, but for me, it is. And, official tools like MongoDB Compass and the mongo shell do not have this issue.

1 Like

Thank you @wan and @Marshall_Meng for your responses. It seems AWS doesn’t allow auto discoverr to all the endpoints. Basically, it allows only one cluster endpoint(primary) connection while tunneling from local environment and i had to set following 2 parameters to connect directly to the primary endpoint. i am able to connect successfully now.
“&connect=direct&sslInsecure=true”

Complete connection uri:
connectionURI := "mongodb://<user_name>:<password>@localhost:27017/?ssl=true&sslCAFile=<path to rds-combined-ca-bundle.pem>&connect=direct&sslInsecure=true&replicaSet=rs0&readPreference=secondaryPreferred

Thanks for the update Manoj. I can confirm this worked for me as well.