使用 pgAdmin4 通过 ssh 隧道连接远程 Postgres 服务器
Connection remote Postgres server with ssh tunneling using pgAdmin4
我在 macOS 上使用 pgAdmin4 3.1 版。今天我尝试使用 ssh 隧道连接我的远程 Postgres 服务器。当我的远程服务器 ssh 端口是默认值 (22) 时,就没有任何问题。 pgAdmin 可以通过创建 ssh 隧道连接到服务器。但是,如果您像我一样分配不同的端口,pgAdmin 将无法创建 ssh 隧道。我不知道 Windows 上是否存在这个问题。但是在 macOS 上,如果远程服务器端口不是 22,pgAdmin4 无法创建 ssh 隧道。
如果您的远程服务器 ssh 端口为 22,则您可以在 pgAdmin4 v3.1 中使用 SSH 隧道选项。如果您的远程服务器 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类型
的更多信息
尝试下载 pgAdmin4 v3.2,我看到了一些关于 SSH 隧道的修复。
参考:https://www.pgadmin.org/docs/pgadmin4/dev/release_notes_3_2.html
我在 macOS 上使用 pgAdmin4 3.1 版。今天我尝试使用 ssh 隧道连接我的远程 Postgres 服务器。当我的远程服务器 ssh 端口是默认值 (22) 时,就没有任何问题。 pgAdmin 可以通过创建 ssh 隧道连接到服务器。但是,如果您像我一样分配不同的端口,pgAdmin 将无法创建 ssh 隧道。我不知道 Windows 上是否存在这个问题。但是在 macOS 上,如果远程服务器端口不是 22,pgAdmin4 无法创建 ssh 隧道。
如果您的远程服务器 ssh 端口为 22,则您可以在 pgAdmin4 v3.1 中使用 SSH 隧道选项。如果您的远程服务器 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类型
的更多信息尝试下载 pgAdmin4 v3.2,我看到了一些关于 SSH 隧道的修复。
参考:https://www.pgadmin.org/docs/pgadmin4/dev/release_notes_3_2.html