使用 libssh 进行 SSH 本地端口转发
SSH local port forwarding using libssh
问题
我尝试使用 libssh with the libssh-C++-wrapper 进行本地端口转发。我的意图是通过 SSH 将服务器上的端口 localhost:3306
转发到我机器上的 localhost:3307
以通过 MySQL 连接到 localhost:3307
.
void ssh_session::forward(){
ssh::Channel channel(this->session);
//remotehost, remoteport, localhost, localport
channel.openForward("localhost",3306,"localhost",3307);
std::cout<< "Channel is " << (channel.isOpen()?"open!":"closed!") << std::endl;
}
ssh::Channel
的构造函数中的 session
是 ssh::Session
.
类型
上面的代码打印 Channel is open!
。如果我尝试使用 MySQL Connector/C++ 连接到 localhost:3307
,我会得到
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (61)
观察结果
- 如果我使用 shell 命令
$ ssh -L 3307:localhost:3306 me@myserver.com
一切正常,我可以连接。
- 如果我在构造函数中使用
ssh::Session session
或 ssh::Channel channel
来执行远程 shell 命令,一切正常,因此会话正常!
- libssh 的文档(对于 C++ 包装器
libsshpp.hpp
来说完全是废话,因为很多 public 成员函数都没有记录,您必须查看源代码)表明 ssh::Channel::openForward()
是 C 函数 ssh_channel_open_forward()
的包装器
ssh_channel_open_forward()
的 documentation 状态
Warning
This function does not bind the local port and does not automatically forward the content of a socket to the channel. You still have to use channel_read and channel_write for this.
我认为这可能会导致问题。我在 ssh:Channel
中读写没问题,但 MySQL Connector/C++ 不是这样工作的。
问题
我怎样才能实现与常用 shell 命令
相同的行为
$ ssh -L 3307:localhost:3306 me@myserver.com
使用 libssh?
Warning
This function does not bind the local port and does not automatically forward the content of a socket to the channel. You
still have to use channel_read and channel_write for this.
这是在告诉您,您需要编写自己的本地套接字代码。不幸的是,它不适合你。
最简单的实现是 bind
一个本地套接字,并使用 ssh_select
来侦听事件(例如到 accept
的新连接、套接字或通道事件)。您可以将套接字 fd
s a 和 ssh_channel
s 放在一个向量中以便于管理。
当你得到任何事件时,只需以非阻塞方式循环所有操作,即
- 尝试
accept
一个新的连接,并将 fd 和一个新的 ssh_channel(按照您的问题创建)附加到您的向量中。
- 尝试
read
所有套接字 fd
s,并使用 ssh_channel_write
将任何内容转发到相应的 ssh 通道(确保将 sockopt SO_RCVTIMEO 设置为 0)
- 尝试使用
ssh_channel_read_nonblocking
读取所有频道,并使用 write
转发到套接字 fd
。
还需要处处处理错误,关闭相应的fd和ssh_channel。
总的来说,Whosebug 答案的代码可能太多了,但如果我有时间,我可能会回来添加它。
所有这些的诱人替代方案是 运行 ssh -L ...
作为使用 fork
和 exec
的子进程,避免所有样板套接字代码,并从中受益来自高效、无错误的实施。
问题
我尝试使用 libssh with the libssh-C++-wrapper 进行本地端口转发。我的意图是通过 SSH 将服务器上的端口 localhost:3306
转发到我机器上的 localhost:3307
以通过 MySQL 连接到 localhost:3307
.
void ssh_session::forward(){
ssh::Channel channel(this->session);
//remotehost, remoteport, localhost, localport
channel.openForward("localhost",3306,"localhost",3307);
std::cout<< "Channel is " << (channel.isOpen()?"open!":"closed!") << std::endl;
}
ssh::Channel
的构造函数中的 session
是 ssh::Session
.
上面的代码打印 Channel is open!
。如果我尝试使用 MySQL Connector/C++ 连接到 localhost:3307
,我会得到
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (61)
观察结果
- 如果我使用 shell 命令
$ ssh -L 3307:localhost:3306 me@myserver.com
一切正常,我可以连接。 - 如果我在构造函数中使用
ssh::Session session
或ssh::Channel channel
来执行远程 shell 命令,一切正常,因此会话正常! - libssh 的文档(对于 C++ 包装器
libsshpp.hpp
来说完全是废话,因为很多 public 成员函数都没有记录,您必须查看源代码)表明ssh::Channel::openForward()
是 C 函数ssh_channel_open_forward()
的包装器
ssh_channel_open_forward()
的 documentation 状态Warning
This function does not bind the local port and does not automatically forward the content of a socket to the channel. You still have to use channel_read and channel_write for this.
我认为这可能会导致问题。我在 ssh:Channel
中读写没问题,但 MySQL Connector/C++ 不是这样工作的。
问题
我怎样才能实现与常用 shell 命令
相同的行为$ ssh -L 3307:localhost:3306 me@myserver.com
使用 libssh?
Warning
This function does not bind the local port and does not automatically forward the content of a socket to the channel. You still have to use channel_read and channel_write for this.
这是在告诉您,您需要编写自己的本地套接字代码。不幸的是,它不适合你。
最简单的实现是 bind
一个本地套接字,并使用 ssh_select
来侦听事件(例如到 accept
的新连接、套接字或通道事件)。您可以将套接字 fd
s a 和 ssh_channel
s 放在一个向量中以便于管理。
当你得到任何事件时,只需以非阻塞方式循环所有操作,即
- 尝试
accept
一个新的连接,并将 fd 和一个新的 ssh_channel(按照您的问题创建)附加到您的向量中。 - 尝试
read
所有套接字fd
s,并使用ssh_channel_write
将任何内容转发到相应的 ssh 通道(确保将 sockopt SO_RCVTIMEO 设置为 0) - 尝试使用
ssh_channel_read_nonblocking
读取所有频道,并使用write
转发到套接字fd
。
还需要处处处理错误,关闭相应的fd和ssh_channel。
总的来说,Whosebug 答案的代码可能太多了,但如果我有时间,我可能会回来添加它。
所有这些的诱人替代方案是 运行 ssh -L ...
作为使用 fork
和 exec
的子进程,避免所有样板套接字代码,并从中受益来自高效、无错误的实施。