VC++ 使用ssh协议连接Linux服务器执行指令并返回

提供一个libssh2.dll的工程和调用libssh2.dll实现登录Linux服务器并执行指令返回数据的工程

链接:https://pan.baidu.com/s/1ShXnldDHVv3YjDUJp4aMrg
提取码:rz6m

libssh2官网,这个里面好像并没有什么用,下载的东西只有代码,然后编译一堆错误

libssh2

libssh2 函数说明

libssh2 docs

 密钥文件登录Linux服务器

Windows 配置 ssh 免密登录_windows ssh_清潇和梨花的博客-CSDN博客

 

这里的难点是libssh2.dll编译,这个需要openssl  zlib  2个环境,

配置的过程很麻烦总缺少东西,原以为是需要安装zlib 和 openssl,现在看来大神已经配置好到工程里了

我也没走通配置过程,这个工程是从GitHub里下载的,当时下载太多资源导致链接找不到了

现提供一个资源下载,方便自己方便他人

 

 现在又有一个客户要求使用密钥文件执行ssh指令,使用上面那个libssh2编译出来的libssh2.dll老在验证密钥那里报错

密钥文件是没有后缀名的文件,再提供客户发过来的libssh2程序,编译环境与上面找的那个libssh2一致,openssl 和 zlib

遇到同样文件可以用这个工程试一下

链接:https://pan.baidu.com/s/1ANAST8UWjo9mEUhGBz7AKQ
提取码:s3k5

########################################################################################################################

这个dll是偶然得到的,可以用

https://files.cnblogs.com/files/ckrgd/libssh2.rar?t=1733474531&download=true

把代码写出来以后供参考

  1 //SSH会话对象
  2 LIBSSH2_SESSION *m_SSHsession;
  3 //socket对象
  4 SOCKET m_socket;
  5 //会话通道
  6 LIBSSH2_CHANNEL *m_SSHchannel;
  7 
  8 
  9 //连接ssh
 10 BOOL ConnectSSH(CString strIP, CString strUserName, CString strKeyFile)
 11 {
 12     //指定socket版本
 13     WSADATA wsadata;
 14     int err = WSAStartup(MAKEWORD(2, 0), &wsadata);
 15     if (err != 0)
 16     {
 17         CString strMsg;
 18         strMsg.Format("WSAStartup failed with error:%d", err);
 19         AfxMessageBox(strMsg);
 20         return FALSE;
 21     }
 22     //初始化libssh2函数
 23     int rc = libssh2_init(0);
 24     if (rc != 0)
 25     {
 26         CString strMsg;
 27         strMsg.Format("libssh2_init failed:%d", rc);
 28         AfxMessageBox(strMsg);
 29         return FALSE;
 30     }
 31     //socket连接
 32     m_socket = socket(AF_INET, SOCK_STREAM, 0);
 33     struct sockaddr_in sin;
 34     sin.sin_family = AF_INET;
 35     sin.sin_port = htons(22);
 36     sin.sin_addr.s_addr = inet_addr(strIP);
 37     if (connect(m_socket, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0)
 38     {
 39         CString strMsg;
 40         strMsg.Format("socket failed to connect");
 41         AfxMessageBox(strMsg);
 42         return FALSE;
 43     }
 44     //初始化SSH会话对象
 45     m_SSHsession = libssh2_session_init();
 46     if (!m_SSHsession)
 47     {
 48         CString strMsg;
 49         strMsg.Format("libssh2_session_init error");
 50         AfxMessageBox(strMsg);
 51         return FALSE;
 52     }
 53     //设置或者清除会话的阻塞模式
 54     libssh2_session_set_blocking(m_SSHsession, 0);
 55     //执行SSH握手
 56     while ((rc = libssh2_session_handshake(m_SSHsession, m_socket)) == LIBSSH2_ERROR_EAGAIN);
 57     if (rc)
 58     {
 59         CString strMsg;
 60         strMsg.Format("libssh2_session_handshake error:%d", rc);
 61         AfxMessageBox(strMsg);
 62         return FALSE;
 63     }
 64     //为此会话初始化已知主机的集合  返回的句柄用作libssh2提供的所有其他已知主机相关函数的输入
 65     LIBSSH2_KNOWNHOSTS *nh;
 66     nh = libssh2_knownhost_init(m_SSHsession);
 67     if (!nh)
 68     {
 69         CString strMsg;
 70         strMsg.Format("libssh2_knownhost_init error");
 71         AfxMessageBox(strMsg);
 72         return FALSE;
 73     }
 74     //从指定文件中读取已知主机的集合
 75     libssh2_knownhost_readfile(nh, "known_hosts", LIBSSH2_KNOWNHOST_FILE_OPENSSH);
 76     //将已知主机的集合写入文件
 77     libssh2_knownhost_writefile(nh, "dumpfile", LIBSSH2_KNOWNHOST_FILE_OPENSSH);
 78 
 79     size_t len;
 80     int type;
 81     //获取远程密钥
 82     const char *fingerprint;
 83     fingerprint = libssh2_session_hostkey(m_SSHsession, &len, &type);
 84     if (fingerprint)
 85     {
 86         //对照已知主机列表检查主机+密钥
 87         struct libssh2_knownhost *host;
 88         int check = libssh2_knownhost_checkp(nh, strIP, 22, fingerprint, len, LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW, &host);
 89     }
 90     else
 91     {
 92         CString strMsg;
 93         strMsg.Format("libssh2_session_hostkey error");
 94         AfxMessageBox(strMsg);
 95         return FALSE;
 96     }
 97     //释放已知主机的集合
 98     libssh2_knownhost_free(nh);
 99     //使用密钥文件的方式登录
100     CString strPassWord;
101     strPassWord.Empty();
102     if (strlen(strPassWord) != 0)
103     {
104         //用户身份验证密码
105         while ((rc = libssh2_userauth_password(m_SSHsession, strUserName, strPassWord)) == LIBSSH2_ERROR_EAGAIN);
106         if (rc)
107         {
108             CString strMsg;
109             strMsg.Format("libssh2_userauth_password error");
110             AfxMessageBox(strMsg);
111             return FALSE;
112         }
113     }
114     else
115     {
116         //私钥文件登录
117         while ((rc = libssh2_userauth_publickey_fromfile(m_SSHsession, strUserName, NULL, strKeyFile, NULL)) == LIBSSH2_ERROR_EAGAIN);
118         if (rc)
119         {
120             char *error = NULL;
121             libssh2_session_last_error(m_SSHsession, &error, NULL, 0);
122             CString strMsg;
123             strMsg.Format("libssh2_userauth_publickey_fromfile failed:%d,%s", rc, error);
124             AfxMessageBox(strMsg);
125             return FALSE;
126         }
127     }
128 
129     return TRUE;
130 }
131 
132 //关闭ssh
133 BOOL CloseSSH()
134 {
135     //int exitcode = 127;
136     //int rc;
137     ////关闭通道
138     //while ((rc = libssh2_channel_close(m_SSHchannel)) == LIBSSH2_ERROR_EAGAIN)
139     //{
140     //    waitsocket(m_socket, m_SSHsession);
141     //}
142     //char *exitsignal = (char *)"none";
143     //if (rc == 0)
144     //{
145     //    //获取远程退出代码
146     //    exitcode = libssh2_channel_get_exit_status(m_SSHchannel);
147     //    //获取远程退出信号
148     //    libssh2_channel_get_exit_signal(m_SSHchannel, &exitsignal, NULL, NULL, NULL, NULL, NULL);
149     //}
150     //if (exitsignal)
151     //{
152     //    CString strMsg;
153     //    strMsg.Format("Got signal:%s", exitsignal);
154     //    AfxMessageBox(strMsg);
155     //    return FALSE;
156     //}
157 
158     //释放与通道关联的所有资源
159     libssh2_channel_free(m_SSHchannel);
160     m_SSHchannel = NULL;
161     //终止传输层
162     libssh2_session_disconnect(m_SSHsession, "Normal Shutdown, Thank you for playing");
163     //释放与会话实例关联的资源
164     libssh2_session_free(m_SSHsession);
165     //关闭套接字
166     closesocket(m_socket);
167     //全局库取消初始化
168     libssh2_exit();
169 
170     return TRUE;
171 }
172 
173 static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
174 {
175     struct timeval timeout;
176     int rc;
177     fd_set fd;
178     fd_set *writefd = NULL;
179     fd_set *readfd = NULL;
180     int dir;
181 
182     timeout.tv_sec = 10;
183     timeout.tv_usec = 0;
184 
185     FD_ZERO(&fd);
186     FD_SET(socket_fd, &fd);
187 
188     //应用程序应等待套接字具有可用于读取或写入的数据
189     dir = libssh2_session_block_directions(session);
190     if (dir & LIBSSH2_SESSION_BLOCK_INBOUND)
191     {
192         readfd = &fd;
193     }
194     if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
195     {
196         writefd = &fd;
197     }
198     //确定一个或多个套接字的状态
199     rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
200 
201     return rc;
202 }
203 
204 //执行指令并返回
205 BOOL ExecSSHCmd(CString strCmdFlag, CString &strRead)
206 {
207     CLog mLog;
208     CString strCmd;
209 
210   //得到指令
211     mLog.WriteSSHLog("执行指令:%s,%s", strCmdFlag, strCmd);
212 
213     //建立通用会话通道
214     while ((m_SSHchannel = libssh2_channel_open_session(m_SSHsession)) == NULL && libssh2_session_last_error(m_SSHsession, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN)
215     {
216         waitsocket(m_socket, m_SSHsession);
217     }
218     if (m_SSHchannel == NULL)
219     {
220         CString strMsg;
221         strMsg.Format("libssh2_channel_open_session Error");
222         AfxMessageBox(strMsg);
223         return FALSE;
224     }
225     //执行shell指令
226     int rc;
227     while ((rc = libssh2_channel_exec(m_SSHchannel, strCmd)) == LIBSSH2_ERROR_EAGAIN)
228     {
229         waitsocket(m_socket, m_SSHsession);
230     }
231     if (rc != 0)
232     {
233         CString strMsg;
234         strMsg.Format("libssh2_channel_exec Error");
235         AfxMessageBox(strMsg);
236         return FALSE;
237     }
238 
239     //这是重启指令
240     if (strCmdFlag == "A15-3" || strCmdFlag == "F2")
241     {
242         CloseSSH();
243         return TRUE;
244     }
245     char buffer[0x4000];
246     int bytecount = 0;
247     for (;;)
248     {
249         int rc;
250         do
251         {
252             //从通道流读取数据
253             rc = libssh2_channel_read(m_SSHchannel, buffer, sizeof(buffer));
254             if (rc > 0)
255             {
256                 int i;
257                 bytecount += rc;
258                 for (i = 0; i < rc; ++i)
259                 {
260                     fputc(buffer[i], stderr);
261                 }
262             }
263         } while (rc > 0);
264         if (rc == LIBSSH2_ERROR_EAGAIN)
265         {
266             waitsocket(m_socket, m_SSHsession);
267         }
268         else
269         {
270             break;
271         }
272     }
273     //不加结束符会有些烫烫烫
274     buffer[bytecount] = '\0';
275     //关闭会话通道
276     libssh2_channel_close(m_SSHchannel);
277     strRead.Format("%s", buffer);
278     strRead.Remove('\n');//这个'\n'就是'\0'  影响解析所以干掉他
279     mLog.WriteSSHLog("返回结果:%s", strRead);
280     //解析返回数据
281     InterpretingData(strCmdFlag, strRead);
282 
283     return TRUE;
284 }

 #############################################################################################################

这c++整一星期还没搞定,c#10分钟就完事了

C#使用SSH.NET编写一个Linux操作客户端_ssh net-CSDN博客

1.前言

因为公司的网关与流媒体是基于Linux,如何查询网关与流媒体程序的运行日志如果直接操作服务器,存在着很大的风险。所以准备做一个基于winform的日志查询工具或者Linux运维工具,显得相对比较重要。

2.实现

2.1.开发工具

我这边使用的是VS2015,框架使用的是.NET Framework 4.6.1

2.2.引入dll

右键引用,选择“管理NuGet程序包”。

 

在浏览界面搜索框输入SSH.NET

 

选择SSH.NET后点击安装

 

到此开发包引入完成

2.3.操作封装

using Renci.SshNet;
using System;
 
namespace NetSSHOperation.Utils
{
    public class SSHClass
    {
        public delegate void GetSSHLog(string log);
        public static event GetSSHLog getSSHLog;
        /// <summary>
        /// SSH登录远程Linux服务器,并运行指令
        /// </summary>
        /// <param name="host">远程Linux服务器IP或域名</param>
        /// <param name="username">账号名</param>
        /// <param name="password">账号密码</param>
        /// <param name="command">命令</param>
        /// <returns></returns>
        public static void RunSSHCommands(string host, string username, string password, string command)
        {
            if (command == null || command.Length == 0)
            {
                getSSHLog("指令为空!");
            }
            try
            {
                using (var client = new SshClient(host, username, password))
                {
                    try
                    {
                        client.Connect();
                        string result = client.RunCommand(command).Execute();
                        getSSHLog(result);
                        client.Disconnect();
                    }
                    catch (Exception e)
                    {
                        getSSHLog(e.Message);
                    }
                }
            }
            catch (Exception e)
            {
                getSSHLog(e.Message);
            }
        }
    }
}

 

posted @ 2023-03-16 15:36  ckrgd  阅读(262)  评论(0)    收藏  举报