使用libssh进行SSH本地端口转发

时间:2017-04-13 18:05:02

标签: c++ ssh portforwarding libssh

问题

我尝试使用libssh 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;
}

session的构造函数中的ssh::Channel属于ssh::Session类型。

上面的代码打印Channel is open!。如果我尝试使用MySQL Connector/C++

连接到localhost:3307
  

ERROR 2003(HY000):无法在&#39; 127.0.0.1&#39;上连接到MySQL服务器(61)

观察

  • 如果我使用shell命令$ ssh -L 3307:localhost:3306 me@myserver.com,一切正常,我可以连接。
  • 如果我使用构造函数中使用的ssh::Session sessionssh::Channel channel执行远程shell命令,那么一切正常,会话就可以了!
  • libssh的文档(由于许多公共成员函数没有记录,你必须查看源代码,因此C ++包装器libsshpp.hpp的完全废话)显示ssh::Channel::openForward()是一个C函数ssh_channel_open_forward()
  • 的包装器
  • ssh_channel_open_forward()documentation个州
      

    警告
      此功能不绑定本地端口,也不会自动将套接字的内容转发到通道。您仍然必须使用channel_read和channel_write。

我认为这可能会导致问题。通过读写ssh:Channel我没有问题,但这不是MySQL Connector / C ++的工作方式。

问题

如何实现common shell命令

产生的相同行为
$ ssh -L 3307:localhost:3306 me@myserver.com

使用libssh?

1 个答案:

答案 0 :(得分:3)

  

警告

     

此功能不绑定本地端口,也不会自动将套接字的内容转发到该通道。您   仍然必须使用channel_read和channel_write。

这告诉您需要编写自己的本地套接字代码。不幸的是,它并没有为你做到这一点。

最简单的实现是bind本地套接字,并使用ssh_select监听事件(例如,与accept的新连接,套接字或通道事件)。您可以将套接字fdssh_channel保存在向量中,以便于管理。

当您收到任何事件时,只需以非阻塞方式循环所有操作,即

  • 尝试accept一个新连接,并将fd和一个新的ssh_channel(在您的问题中创建)附加到您的向量。
  • 尝试read所有套接字fd,并使用ssh_channel_write将任何内容转发到相应的ssh频道(确保将SOKC_VOMEO设置为0)
  • 尝试使用ssh_channel_read_nonblocking阅读所有频道,然后使用fd转发至套接字write

您还需要在任何地方处理错误,并关闭相应的fd和ssh_channel。

总的来说,StackOverflow的答案可能会有太多代码,但如果我有时间的话,我可以回来加入。

使用ssh -L ...&amp; amp;运行fork作为子流程的所有方法的诱人替代品exec,避免使用所有样板插槽代码,并从高效,无错误的实现中受益。