我想打开与远程 MySQL 数据库的连接。此数据库位于不同网络上的私有子网中,因此我无法直接打开与它的连接。MySQL 服务器上的远程 SSH 访问也已完全禁用。
我当前的流程是这样的:
我通过公共服务器 HOST_1 打开 SSH 隧道。从该隧道,我打开与 MySQL 服务器 (MYSQL_HOST) 位于同一子网的服务器 (HOST_2) 的 SSH 连接。使用我当时打开的 SSH 会话(在 HOST_2 上),我使用 MySQL 客户端打开与 MYSQL_HOST 的连接。
下面是当前所做工作的非常粗略的图表:
我想要做的就是使用我本地计算机的 MySQL 客户端连接到 127.0.0.1:3306,并让连接从 HOST_1 一直通过隧道传输到 HOST_2,然后到 MYSQL_HOST,就好像我首先从 127.0.0.1 运行 MySQL 服务器一样。
同样,我无法从 HOST_2 打开通往 MYSQL_HOST 的 SSH 隧道,因此无法从那里建立隧道。我需要弄清楚如何通过 SSH 隧道将 MySQL 客户端连接转发到 HOST_2,然后让 HOST_2 将 MySQL 客户端连接转发到 MYSQL_HOST。
我想我可以使用redir
或nc
来实现这一点。但我不确定如何做。
我读过几个问题,但对它们了解不够多,无法将这些信息整合在一起来得到我想要的答案:
- 通过多跳的 SSH 隧道
- 通过 SSH 隧道的 UDP 流量
- https://unix.stackexchange.com/questions/267090/reroute-mysql-connection-through-external-machine
我知道此页面上再次包含信息,这会对我有帮助,但我不知道如何使用它:http://sshmenu.sourceforge.net/articles/transparent-mulithop.html
谢谢!
答案1
该答案假设 sshd 配置为允许在 HOST_1 和 HOST_2 上进行端口转发。
您已经找到了您需要的大部分内容(第一个链接中 Mika Fischer 的回答中的第二个选项)。
从 localhost 到 host1 以及从 host1 到 host2 的隧道:
ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2
这将打开从 localhost 到 host1 的隧道和从 host1 到 host2 的另一条隧道。但是 host1 上的任何人都可以使用到 host2:1234 的端口 9999。这可能是问题,也可能不是问题。
这个想法是将端口转发串联在一起(即,将本地端口转发到远程端口,然后将其转发到更远程的端口)。
对于你的例子,命令将是
ssh -tt -L 3306:localhost:XXXX [user@]HOST_1 ssh -L XXXX:MYSQL_HOST:3306 [user@]HOST_2
其中 XXXX 是任何大于 1024 且尚未使用的端口(使用相同的数字来替换两个实例)
执行后,除非您使用 SSH 密钥进行无密码登录,否则系统会要求您输入两次密码(一次输入 HOST_1,一次输入 HOST_2)。只要您通过 HOST_1 保持与 HOST_2 的连接,隧道就会一直有效。
具体细节如下:
ssh
你正在执行的是本地 ssh 客户端吗
-tt
强制分配伪 tty(参见由于 stdin 不是终端,因此不会分配伪终端为什么可能需要这样做)
-L 3306:localhost:XXXX [user@]HOST_1
告诉您的本地 ssh 客户端将本地系统上的 3306 转发到 SSH 连接另一端的“localhost”上的端口 XXXX。您只需指定user@
本地计算机上的用户是否与您在 HOST_1 上连接的用户不同。更一般地,您可以指定 3306 以外的本地端口,但您需要将 mysql 客户端指向 127.0.0.1:[您选择的端口]。
ssh
(第二个)您可能知道,ssh 有一个选项可以运行单个命令,而不是启动 shell。您将使用该选项在 HOST_1 上执行另一个 SSH 会话,这将创建端口转发链中的下一个链接。
-L XXXX:MYSQL_HOST:3306 [user@]HOST_2
由于此 ssh 会话在 HOST_1 上执行,因此会将本地端 (HOST_1) 上的 XXXX(从客户端上的 3306 转发)转发到远程端 (HOST_2) 上的 MYSQL_HOST 上的端口 3306。您只需指定user@
HOST_1 上的用户是否与您在 HOST_2 上连接的用户不同。
如果需要额外的跳数,则ssh -L XXXX:localhost:XXXX hostX
在中间为每个跳数添加实例,只要 XXXX 是路径中每个服务器上的可用端口即可。
答案2
由于您通过 HOST_1 代理与 HOST_2 的 SSH 连接,因此您只需一个-L
端口转发即可完成此操作:
ssh -A -o'ProxyCommand=ssh -q 用户@HOST_1 nc %h %p' 用户@HOST_2 -L 3306:MYSQL_HOST:3306
这基本上就是您现在正在做的事情:通过与 HOST_1 的 ssh 连接打开与 HOST_2 的 ssh 连接,然后将来自本地主机 3306 的连接转发到 MYSQL_HOST:3306。请注意,MYSQL_HOST 将看到来自 HOST_2 的连接,因为这是它退出隧道并返回正常 TCP 连接的地方。
顺便说一句,如果你在本地计算机和 HOST_1 上都安装了 OpenSSH 7.3 或更高版本,则可以使用新-J
选项(或ProxyJump
ssh 配置文件中的指令):
ssh -A -J 用户@HOST_1 用户@HOST_2 -L 3306:MYSQL_HOST:3306
这也使得通过多个 SSH 代理变得更加容易:
ssh -A -J 用户@HOST_1,用户@HOST_3,用户@HOST_3 用户@HOST_4 -L 3306:MYSQL_HOST:3306