1.SSH概念

ssh(secure shell),安全外壳协议,由IETF的网络小组所制定。ssh为建立在应用层基础上的安全协议。SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来迅速扩展到其他操作平台。SSH在正确使用时可以弥补网络中的漏洞。

1.1 ssh功能

传统的网络服务程序,如ftp、pop和telnet在本质上都是不安全的,因为它们在网络上使用明文传送口令和数据。而且,这些服务程序的安全验证方式也是有其弱点的,极易受到中间人攻击。通过使用SSH,可以把所有传输的数据进行加密,这样中间人攻击方式就不可能实现了,而且也能防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替TELNET,又可以为ftp、pop甚至为ppp提供一个安全的通道。

1.2 ssh验证

从客户端来看,ssh提供两种级别的安全验证。

第一种级别(基于口令的安全验证)

只要你知道自己账号和口令,就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受到“中间人攻击”。

第二种级别(基于密钥的安全验证)

需要依靠密钥,也就是你必须为自己创建一对密钥,并把公用密钥放在需要访问的服务器上。如果你想要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密钥进行安全验证。服务器收到请求之后,先到该服务器上你的主目录下寻找你的公用密钥,然后把它和你发送过来的公用密钥进行比较。如果两个密钥一致,服务器就用公钥密钥加密“质询(challenge)”并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密钥解密再把它发送给服务器。

用这种方式,你必须知道自己密钥口令,但是,与第一种级别相比,第二种级别不需要再网络上传送口令。

第二种级别不仅加密所有传输的数据,而且中间人攻击不能实现,因为他没有你的私人密钥。但是整个登陆过程可能需要10秒。

1.3 ssh结构

ssh由客户端和服务端软件组成,有两个不兼容的版本分别是:1.x和2.x。用ssh2.x的客户程序不能连接到ssh1.x的服务程序上去。openssh2.x同时支持ssh1.x和2.x。

服务端是一个守护进程,它在后台运行并响应来自客户端的连接请求。服务端一般是sshd进程,提供了对远程连接的处理,一般包括公共密钥认证、密钥交换、对称密钥加密和非安全连接。

客户端包含ssh程序以及像scp(远程拷贝)、slogin(远程登录)、sftp(安全文件传输)等其他的应用程序。

他们的工作机制大致是本地的客户端发送一个连接请求到远程的服务端,服务端检查申请的包和IP地址再发送密钥给SSH的客户端,本地再将密钥发回给服务端,自此连接建立。SSH1.x和SSH2.x在连接协议上有一些差异。

一旦建立一个安全传输层连接,客户机就发送一个服务请求。当用户认证完成之后,会发送第二个服务请求。这样就允许新定义的协议可以与上述协议共存。

启动SSH服务器后,sshd运行起来并在默认的22端口进行监听,当请求到来的时候SSH守护进程会产生一个子进程,该子进程进行这次的连接处理。

1.4 扩展

SSH协议框架中设计了大量可扩展的溶于能力,比如用户自定义算法、客户自定义密钥规则、高层扩展功能性应用协议。这些扩展大多遵循IANA的有关规定,特别是在重要的部分,像命名规则和消息编码方面。

SSH采用面向连接的TCP协议传输,应用22端口,安全系数较高。

2. libssh2

libssh2是一个用C库实现了SSH2协议的客户端。

2.1 libssh2特性

libssh2提供用于开发基于SSH的应用的API。一些特性如下:

  • 密钥交换方式:diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group-exchange-sha256;
  • 主机密钥类型:ssh-rsa,ssh-dss;
  • 加密器:aes256-ctr, aes192-ctr, aes128-ctr, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, arcfour, arcfour128, none;
  • 压缩方式:zlib, zlib@openssh.com, none;
  • MAC 哈希:hmac-sha2-256, hmac-sha2-512, hmac-sha1, hmac-sha1-96, hmac-md5, hmac-md5-96, hmac-ripemd160 (hmac-ripemd160@openssh.com), none;
  • 认证方式:none, password, public-key, hostbased, keyboard-interactive;
  • 通道:shell, exec (incl. SCP wrapper), direct-tcpip, subsystem;
  • 全局请求:tcpid-forward;
  • 通道请求:x11, pty, exit-signal, keepalive@openssh.com;
  • 子系统:sftp(version 3), publickey(version 2);
  • SFTP:statvfs@openssh.com, fstatvfs@openssh.com;
  • 线程安全:只是不要同时共享句柄;
  • 非阻塞:可以使用阻塞和非阻塞两种;
  • sockets:app在socket上调用,调用select()等;
  • 加密后端:OpenSSL、libgcrypt,mbedTLS

2.2 libssh2版本

libssh2 1.8.0

改变:

  • 添加了一个基础的dockerised测试套件;
  • crypto:添加了mbedTLS的后端支持。

bug修复:

  • libgcrypt:修复了OOM上的一个NULL指针解除引用;
  • VMS:不能将%zd用于off_t格式;
  • VMS:更新了 vms/libssh2_config.h;
  • windows:与crypt32.lib链接;
  • libssh2_channel_open:在通道错误消息中修复了speeling错误;
  • msvc:修复了14个编译警告;
  • tests:HAVE_NETINET_IN_H未正确定义;
  • openssl:添加OpenSSL 1.1.0兼容性;
  • cmake:添加CLEAR_MEMORY选项,类似于autoconf的选项;
  • configure:使用 --with-*选项覆盖OpenSSL的默认值;
  • libssh2_wait_socket:设置err_msg错误;
  • libssh2_wait_socket:修复用毫秒与api_timeout的比较。

2.3 libssh2应用例子

工作思路是为session以一种工作模式(加密、压缩和MAC层)启动一个libssh2例程,然后在经过身份认证后接着进行文件传输或其他服务,在完成服务后,关闭session和socket,最后退出libssh2。

2.3.1 在sftp的应用

unsigned long hostaddr;
int sock, i, auth_pw = ;
struct sockaddr_in sin;
const char *fingerprint;
char *userauthlist;
LIBSSH2_SESSION * session;
int rc;
LIBSSH2_SFTP *sftp_session;
LIBSSH2_HANDLE *sftp_handle;

步骤:

(1)创建socket并建立连接;

(2)创建一个会话实例;

/* Create a session instance */
session = libssh2_session_init();
if(!session)
return -;

(3)如果设置非阻塞模式,通知libssh2我们正在阻塞

libssh2_session_set_blocking(session, );

(4)启动它。操作包括:交易欢迎横幅、交换密钥并设置加密、压缩和MAC层。

rc = libssh2_session_handshake(session, sock);

if(rc)
{
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -;
}

(5)此时尚未通过身份验证。要做的第一件事是检查主机密钥对我们已知的主机的指纹(您的应用程序可能已经硬编码,可能会转到文件,可能会将其呈现给用户,这是你的通话)。

fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);

(6)检查可用的认证方法。

userauthlist = libssh2_userauth_list(session, username, strlen(username));
if(strstr(userauthlist, "password") != NULL)
{
auth_pw |= ;
}
if(strstr(userauthlist, "keyboard-interactive") != NULL)
{
auth_pw |= ;
}
if(strstr(userauthlist, "publickey") != NULL)
{
auth_pw |= ;
}

(7)根据用户参数-i、-p、-k选择认证方式

 if (auth_pw & ) {

        /* We could authenticate via password */

        if (libssh2_userauth_password(session, username, password)) {

            fprintf(stderr, "Authentication by password failed.\n");

            goto shutdown;

        }

    } else if (auth_pw & ) {

        /* Or via keyboard-interactive */

        if (libssh2_userauth_keyboard_interactive(session, username, &kbd_callback) ) {

            fprintf(stderr,

                "\tAuthentication by keyboard-interactive failed!\n");

            goto shutdown;

        } else {

            fprintf(stderr,

                "\tAuthentication by keyboard-interactive succeeded.\n");

        }

    } else if (auth_pw & ) {

        /* Or by public key */

        if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, keyfile2, password)) {

            fprintf(stderr, "\tAuthentication by public key failed!\n");

            goto shutdown;

        } else {

            fprintf(stderr, "\tAuthentication by public key succeeded.\n");

        }

    } else {

        fprintf(stderr, "No supported authentication methods found!\n");

        goto shutdown;

    }

(8)通过认证后 ,重启一个会话

  sftp_session = libssh2_sftp_init(session);
if (!sftp_session) { fprintf(stderr, "Unable to init SFTP session\n"); goto shutdown; }

(9)通过SFTP请求一个文件

sftp_handle = libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, );
...
do
{
char mem[1024]; rc = libssh2_sftp_read(sftp_handle, mem, sizeof(mem)); if(rc >0)
{
write(1, mem, rc);
}
else
{
break;
}
}while(1);

(10)关闭sftp句柄和sftp会话

libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);

(11)shutdown:断开会话连接并释放会话

libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session);

(12)关闭sock并退出libssh2

close(sock);
libssh2_exit();

libssh的更多相关文章

  1. 对libssh的golang 封装 ssh2go

    ssh2go 是对libssh的go语言绑定.libssh作为ssh的实现库,支持SSHv2和SSHv1的客户.服务端实现,通过libssh你可以远程执行程序.拷贝文件等等. ssh2go不像其他go ...

  2. Redhat 6.3上安装libssh

    遇到了很多坑,决定记录下来,有些经验还是很有帮助的. 最重要的一条就是:安装rpm包,总是比编译源码安装(make&make install)更快.记住两个rpm网站:https://pkgs ...

  3. Ubuntu 14.04 安装libssh

    参考: libssh [CMake] include command Ubuntu 14.04 安装libssh $ git clone https://github.com/substack/lib ...

  4. Libssh认证绕过CVE-2018-10933漏洞复现

    0x00 漏洞描述 libssh 0.6 及以上的版本,在服务端的代码实现中存在身份认证绕过漏洞.在向服务端认证的流程中,攻击者通过将 SSH2_MSG_USERAUTH_REQUEST 消息替换为  ...

  5. CVE-2018-10933 LibSSH auth bypass

    漏洞原理 认证实现错误, 认证分为多个步骤,可以直接跳到成功的步骤       A vulnerability was found in libssh's server-side state mach ...

  6. [异常解决] windows用SSH和linux同步文件&linux开启SSH&ssh client 报 algorithm negotiation failed的解决方法之一

    1.安装.配置与启动 SSH分客户端openssh-client和openssh-server 如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果没有 ...

  7. 树莓派 Linux备忘

    //更新树莓派 sudo apt-mark hold raspberrypi-bootloader sudo apt-get update sudo apt-get upgrade //配置 rasp ...

  8. links and softwares

    links 普通 http://www.ncpa-classic.com//special/2014gejujie/index.shtml ; 中国大剧院 http://tieba.baidu.com ...

  9. ubuntu14.04 安装 搜狗输入法

    1.安装或者更新fcitx libssh2-1:sudo  apt-get install fcitx libssh2-1; 2.搜索是否安装成功: dpkg -l | grep fcitx ; dp ...

随机推荐

  1. js 加法

    使用Number()函数可以解决这个问题,如下 var c = Number(a) + Number(b) 这样c得出来的解果是3,

  2. Django文档

    https://docs.djangoproject.com/zh-hans/2.1/

  3. jQuery禁用input历史选择

    $("#id").attr("autocomplete", "off");

  4. storm是如何保证at least once语义的?

    storm中的一些原语: 要说明上面的问题,得先了解storm中的一些原语,比如: tuple和messagetuple:在storm中,消息是通过tuple来抽象表示的,每个tuple知道它从哪里来 ...

  5. printf特殊用法

    printf("%*.*lf\n", a, b, c); //表示a宽距,保留b位小数 用这种方法可以通过输入控制a和b

  6. CSS内联--与块级元素区别

    内联元素:1.内联元素(inline)不会独占一行,相邻的内联元素会排在同一行.其宽度随内容的变化而变化. 2.内联元素不可以设置宽高 3.内联元素可以设置margin,padding,但只在水平方向 ...

  7. 【学习笔记】RMQ-Range Minimum/Maximum Query (区间最小/最大值)

    RMQ是一类询问区间最小/最大值的问题. 这类问题一般分成两类:静态区间(无修改),动态区间(带修改). 对于动态区间查询最大/最小,我们显然可以用线段树来解决…… 那么对于静态区间查询最大/最小的问 ...

  8. python学习-34 内置函数的补充

    其他内置函数 1.ord()    与chr()相反 2.pow() print(pow(3,3)) # 相当于3**3 print(pow(3,3,2)) # 相当于3*3%2 运行结果: 27 1 ...

  9. 十大经典算法 Python实现

    十大经典排序算法(python实现)(原创) 使用场景: 1,空间复杂度 越低越好.n值较大: 堆排序 O(nlog2n) O(1) 2,无空间复杂度要求.n值较大: 桶排序 O(n+k) O(n+k ...

  10. MySQL使用中遇到的error

    eclipse连接不上数据库 //加载驱动 //oracal.jdbc.drive.Oracle.Driver //com.mysql.jdbc.Driver try { Class.forName( ...