How to proxy access mongoDB through ssh tunnel in code?

69 Views Asked by At

I'm trying to use atlas mongoDB using ssh tunnel with AWS EC2. The language is Go.

I can guarantee that there will be no problems with EC2. It works when accessing with mongoDB compass.

However, implementing tunneling-connection directly in Go does not work well.

The tunneling code is:

import (
        ...
    "github.com/rgzr/sshtun"
    ...
)
...
    sshTun := sshtun.New(27017, "EC2 IP", 27017)
    sshTun.SetUser("mongoproxy")
    sshTun.SetPassword("...")
    sshTun.SetLocalEndpoint(sshtun.NewTCPEndpoint("127.0.0.1", 27017))
    sshTun.SetRemoteEndpoint(sshtun.NewTCPEndpoint("...mongodb.net", 27017))

    sshTun.SetTunneledConnState(func(tun *sshtun.SSHTun, state *sshtun.TunneledConnState) {
        log.Printf("# TunneledConnState: %+v", state)
    })

    var connected atomic.Bool

    // We set a callback to know when the tunnel is ready
    sshTun.SetConnState(func(tun *sshtun.SSHTun, state sshtun.ConnState) {
        switch state {
        case sshtun.StateStarting:
            log.Printf("STATE is Starting")
        case sshtun.StateStarted:
            connected.Store(true)
            log.Printf("STATE is Started")
        case sshtun.StateStopped:
            connected.Store(false)
            log.Printf("STATE is Stopped")
        }
    })

    go func() {
        for {
            if err := sshTun.Start(context.Background()); err != nil {
                log.Printf("SSH tunnel error: %v", err)
                time.Sleep(time.Second * 10) 
            }
        }
    }()

    for !connected.Load() {
        time.Sleep(time.Second)
    }

       ...

The connection code is as follows:

func NewMongoClientWithTunneling(cfg *config.Config) MongoClient {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    dataSource := fmt.Sprintf(
        "mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority",
        cfg.Mongo.User,
        cfg.Mongo.Password,
        "127.0.0.1",
        cfg.Mongo.DBName,
    )

    c, err := mongo.Connect(ctx,
        options.
            Client().
            ApplyURI(dataSource).
            SetMinPoolSize(uint64(cfg.Mongo.Options.MinConnections)).
            SetMaxPoolSize(uint64(cfg.Mongo.Options.MaxConnections)).
            SetMaxConnIdleTime(10*time.Minute).
            SetMonitor(apmmongo.CommandMonitor()),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Check the connection
    if err := c.Ping(ctx, nil); err != nil {
        panic(fmt.Sprintf("Failed to connect to MongoDB: %v", err))
    }
...

When executing the above code, the following error occurs. This is probably because the work done with srv cannot be done on the local host.

2023/08/31 18:37:01 error parsing uri: lookup _mongodb._tcp.127.0.0.1 on 168.126.63.1:53: no such host

I'm wondering what I did wrong and how compass handles this.

I need your help...

The test environment is M2 Pro ventura.

0

There are 0 best solutions below