Golang SSH隧道连接到远程Postgres数据库

huangapple go评论106阅读模式
英文:

Golang SSH tunneling connection to a remote postgres DB

问题

我已经查看了各种资源。我不确定如何完成这个任务。我可以在本地连接没有问题,但是我不能轻松地连接到远程。我需要传递一个RSA .pem密钥,但我不太确定如何在不强制进行不安全连接的情况下完成这个任务。

package main

import (
	"database/sql"
	"fmt"
	"os"

	_ "github.com/lib/pq"
)

var (
	dbUser  = os.Getenv("DB_USER")
	dbPass  = os.Getenv("DB_PASS")
	dbName  = os.Getenv("DB_NAME")
	dbHost  = os.Getenv("DB_HOST")
	dbPort  = os.Getenv("DB_PORT")
	sslMode = os.Getenv("SSLMODE")
)

// ConnectDb是一个通过CLI接收参数并返回一个指向sql.DB连接的快捷函数。
// 它不接受任何参数。
func ConnectDb() (*sql.DB, error) {

	db, err := sql.Open("postgres", getDbInfo())
	CheckErr(err, "无法连接到数据库")

	if err := db.Ping(); err != nil {
		return nil, err
	}

	return db, nil
}

func getDbInfo() string {
	var dbInfo string

	if dbName != "" {
		dbInfo += fmt.Sprintf("dbname=%s ", dbName)
	} else {
		dbInfo += fmt.Sprintf("dbname=%s ", "development")
	}

	// 检查是否为nil值
	if dbUser != "" {
		dbInfo += fmt.Sprintf("dbuser=%s ", "user")
	}

	// 检查是否为nil值
	if dbPass != "" {
		dbInfo += fmt.Sprintf("dbpass=%s ", dbPass)
	}

	if sslMode != "" {
		dbInfo += fmt.Sprintf("sslmode=%s", sslMode)
	} else {
		dbInfo += fmt.Sprintf("sslmode=disable")
	}

	return dbInfo
}

以上是要翻译的内容。

英文:

I have looked at various resources. I'm not sure how to accomplish this task. I can connect locally no problem, but I cannot connect to the remote easily. I need to pass on an RSA .pem key, and I'm not quite sure how to do this w/o forcing a connection unsecured

package main
import (
"database/sql"
"fmt"
"os"
_ "github.com/lib/pq"
)
var (
dbUser  = os.Getenv("DB_USER")
dbPass  = os.Getenv("DB_PASS")
dbName  = os.Getenv("DB_NAME")
dbHost  = os.Getenv("DB_HOST")
dbPort  = os.Getenv("DB_PORT")
sslMode = os.Getenv("SSLMODE")
)
// ConnectDb is a short cut function that takes parameters through
// CLI that returns a pointer to a sql.DB connection.
// It takes no arguments.
func ConnectDb() (*sql.DB, error) {
db, err := sql.Open("postgres", getDbInfo())
CheckErr(err, "Unable to connecto tthe DB")
if err := db.Ping(); err != nil {
return nil, err
}
return db, nil
}
func getDbInfo() string {
var dbInfo string
if dbName != "" {
dbInfo += fmt.Sprintf("dbname=%s ", dbName)
} else {
dbInfo += fmt.Sprintf("dbname=%s ", "development")
}
// checks for nil value
if dbUser != "" {
dbInfo += fmt.Sprintf("dbuser=%s ", "user")
}
// checks for nil value
if dbPass != "" {
dbInfo += fmt.Sprintf("dbpass=%s ", dbPass)
}
if sslMode != "" {
dbInfo += fmt.Sprintf("sslmode=%s", sslMode)
} else {
dbInfo += fmt.Sprintf("sslmode=disable")
}
return dbInfo
}

答案1

得分: 2

据我了解,您需要打开与PostgreSQL数据库的连接。我不知道是否存在原生的PostgreSQL SSH隧道支持。因此,以下是关于SSH隧道连接到数据库服务器的答案。

我没有以这种方式测试过PostgreSQL,但我曾经在一些专有服务器连接中使用过这种模型。

该过程如下:

  1. 打开与数据库服务器的SSH连接。
  2. 在本地端口和远程数据库端口之间建立隧道。
  3. 在本地端口上打开数据库连接。

您可以使用OpenSSH或putty等SSH客户端来完成步骤1和步骤2。您应该首先尝试这样做。如果外部客户端可用,那么您可以尝试将所有内容都放入Go语言代码中,而无需使用外部SSH客户端。

在Go语言中,您可以使用以下包:

"golang.org/x/crypto/ssh"

有一些教程可以教您如何使用Go语言进行SSH隧道连接。以下是一个没有错误检查的示例:

var buffer []byte
var err error
buffer, err = ioutil.ReadFile(sshKeyFile)
var key ssh.Signer
key, err = ssh.ParsePrivateKey(buffer)
var authMethod ssh.AuthMethod
authMethod = ssh.PublicKeys(key)
sshConfig = &ssh.ClientConfig{
User: "user_id",
Auth: []ssh.AuthMethod{authMethod},
}
conn, err := ssh.Dial("tcp", endpoint, sshConfig)
// 在PostgreSQL上打开连接:
dbConn, err = conn.Dial("tcp", dbEndpoint)

上面的最后一行并不是真正的隧道,而是与数据库服务器建立的TCP连接。您可能可以将该连接传递给数据库库。如果不能,您将需要设置一个隧道。

英文:

It is my understanding that you need to open connection to postgre database. I don't know if a native postgre ssh tunneling support exists. So, this answer about SSH tunneling to DB machine.

I have not tested postgre this way, but I have had this model used in some proprietary server connections.

The process goes like that:

  1. open ssh connection to db machine
  2. establish tunnel from local port to remote db port
  3. open db connection on local port

You can accomplish #1 and #2 with ssh client like OpenSSH or putty. You should probably do that 1st. If external client works, then you can attempt to put it all into go language code without external SSH client.

In go you would use

"golang.org/x/crypto/ssh"

package.

There are tutorials out there how to use GO ssh tunneling. Below is not a tested sample without error checking:

var buffer []byte
var err error
buffer, err = ioutil.ReadFile(sshKeyFile)
var key ssh.Signer
key, err = ssh.ParsePrivateKey(buffer)
var authMethod ssh.AuthMethod
authMethod = ssh.PublicKeys(key)
sshConfig = &ssh.ClientConfig{
User: "user_id",
Auth: []ssh.AuthMethod{authMethod},
}
conn, err := ssh.Dial("tcp", endpoint, sshConfig)
// open connection on postgre:
dbConn, err = conn.Dial("tcp", dbEndpoint)

The last line above is not exactly tunneling, but an TCP connection open to DB server. You might be able to pass that connection into db library. If not, you would have to setup a tunnel.

huangapple
  • 本文由 发表于 2016年3月17日 01:14:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/36042528.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定