使用pgAdmin4通过SSH隧道连接远程Postgres服务器

时间:2018-08-23 12:32:50

标签: ssh-tunnel postgresql-9.6 pgadmin-4

我正在macOS上使用pgAdmin4 3.1版。今天,我尝试使用ssh隧道连接远程Postgres服务器。当我的远程服务器的ssh端口是默认端口(22)时,则没有任何问题。 pgAdmin可以通过创建ssh隧道连接到服务器。但是,如果像我这样分配其他端口,pgAdmin将无法创建ssh隧道。我不知道Windows是否存在此问题。但是在macOS上,如果远程服务器端口不是22,则pgAdmin4无法创建ssh隧道。

2 个答案:

答案 0 :(得分:0)

如果远程服务器ssh端口为22,则可以将SSH隧道选项与pgAdmin4 v3.1一起使用。如果远程服务器ssh端口不是22,则无法使用pgAdmin执行此操作。


一种选择是使用终端创建ssh隧道,然后使用创建ssh隧道时使用的本地端口通过pgAdmin4连接到数据库。

但是,如果要使用pgAdmin4进行此操作,则应更改默认的 server_manager.py 脚本。


如果检查默认的server_manager.py代码,则会看到以下代码段,用于创建ssh隧道

def create_ssh_tunnel(self, tunnel_password):
    """
    This method is used to create ssh tunnel and update the IP Address and
    IP Address and port to localhost and the local bind port return by the
    SSHTunnelForwarder class.
    :return: True if tunnel is successfully created else error message.
    """
    # Fetch Logged in User Details.
    user = User.query.filter_by(id=current_user.id).first()
    if user is None:
        return False, gettext("Unauthorized request.")

    try:
        tunnel_password = decrypt(tunnel_password, user.password)
        # Handling of non ascii password (Python2)
        if hasattr(str, 'decode'):
            tunnel_password = \
                tunnel_password.decode('utf-8').encode('utf-8')
        # password is in bytes, for python3 we need it in string
        elif isinstance(tunnel_password, bytes):
            tunnel_password = tunnel_password.decode()

    except Exception as e:
        current_app.logger.exception(e)
        return False, "Failed to decrypt the SSH tunnel " \
                      "password.\nError: {0}".format(str(e))

    try:
        # If authentication method is 1 then it uses identity file
        # and password
        if self.tunnel_authentication == 1:
            self.tunnel_object = SSHTunnelForwarder(
                self.tunnel_host,
                ssh_username=self.tunnel_username,
             ssh_pkey=get_complete_file_path(self.tunnel_identity_file),
                ssh_private_key_password=tunnel_password,
                remote_bind_address=(self.host, self.port)
            )
        else:
            self.tunnel_object = SSHTunnelForwarder(
                self.tunnel_host,
                ssh_username=self.tunnel_username,
                ssh_password=tunnel_password,
                remote_bind_address=(self.host, self.port)
            )

        self.tunnel_object.start()
    except BaseSSHTunnelForwarderError as e:
        current_app.logger.exception(e)
        return False, "Failed to create the SSH tunnel." \
                      "\nError: {0}".format(str(e))

    # Update the port to communicate locally
    self.local_bind_port = self.tunnel_object.local_bind_port

    return True, None


如您所见,此方法仅使用服务器配置中的隧道主机地址,因此无论您从pgAdmin4设置tunnel_port属性如何都无关紧要,此方法始终使用默认的ssh端口22来创建ssh隧道。因此,要解决此问题,只需更改方法,然后将tunnel_port属性作为参数传递给SSHTunnelForwarder对象。 所以最终的代码就像下面的代码片段

if self.tunnel_authentication == 1:
   self.tunnel_object = SSHTunnelForwarder(
     (self.tunnel_host, int(self.tunnel_port)),
      ssh_username=self.tunnel_username,
      ssh_pkey=get_complete_file_path(self.tunnel_identity_file),
      ssh_private_key_password=tunnel_password,
      remote_bind_address=(self.host, self.port)
     )
else:
   self.tunnel_object = SSHTunnelForwarder(
     (self.tunnel_host, int(self.tunnel_port)),
      ssh_username=self.tunnel_username,
      ssh_password=tunnel_password,
      remote_bind_address=(self.host, self.port)
     )

tunnel_port属性是一个字符串,因此我们需要将此属性转换为int类型。

有关SSHTunnelForwarder

的更多信息

答案 1 :(得分:0)

尝试下载pgAdmin4 v3.2,我已经看到有关SSH隧道的一些修复程序。

参考:https://www.pgadmin.org/docs/pgadmin4/dev/release_notes_3_2.html