SSH(Secure SHell)是为远程登录, 远程通信等设计的安全通信协议, 由芬兰研究员于1995年提出,其目的是用于替代非安全的Telnet、rsh、rexec等不安全的远程Shell协议.

SSH提供身份认证,加密通信,完整性校验以及身份认证等功能. 工程人员经常使用SSH协议登录云服务器等远程计算机, FTP, RPC等协议也可以使用SSH提供的安全信道.

因为版权, 加密算法等原因目前广为使用OpenSSH提供SSH服务.

使用SSH

OpenSSH分为客户端和服务端, Linux和Mac OS系统一般会自带openssh-client。

本地计算机上需要安装客户端, 远程计算机上需要运行服务端。 SSH协议默认使用TCP22端口, 远程计算机需要确保远程计算机打开了22端口.

远程计算机安装服务端后可以使用sudo service ssh start启动, 或者使用sudo /etc/init.d/ssh start.

启动成功后可以使用service ssh status或者ps -e中查看ssh服务的状态.

远程主机配置完毕后, 在本地主机使用ssh user@host命令可以用户user的身份登录远程主机host, 如ssh root@mycloud.com.

ssh服务可以使用口令验证(password)或者使用私钥验证(private-key)。ssh优先使用私钥验证, 若未配置私钥则要求用户输入口令进行验证, 该口令为远程计算机上账户的登录口令.

客户端在要求客户输入口令之前, 会先会检查自己的knows_hosts数据库中(一般为~/.ssh/know_hosts文件)是否已经包含当前服务端的密钥指纹(ECDSA key fingerprint).

若包含则会继续建立连接, 否则由用户判断是否相信当前客户端. 若用户不相信则中断连接, 否则继续建立连接, 并将当前服务端加入known_hosts中。

用户在判断是否相信当前服务端时需注意, 若该服务端为真正的目标服务端, 则此后与此服务端通信过程中基本不会再受到中间人的威胁. 若发现错误信任了假冒的服务端, 则应尽快在known_hosts中删除它的指纹, 避免计算机在通信时默认相信该假冒者.

配置密钥对

ssh-keygen是用于生成密钥对的工具, 使用ssh-keygen生成RSA密钥对:

$ssh-keygen -t rsa -C finley@gmail.com
Generating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ~/.ssh/id_rsa.
Your public key has been saved in ~/.ssh/id_rsa.pub.
The key fingerprint is:

上面的提示说明私钥保存在~/.ssh/id_rsa, 公钥保存在~/.ssh/id_rsa.pub. 如果必要的话也可以为私钥设置口令.

使用man ssh-keygen可以看到该命令的帮助, 最常用的选项有:

  • -q: 以静默方式生成
  • -b bits: 指定位数
  • -t: 指定加密方式, 包括: dsa | ecdsa | ed25519 | rsa | rsa1
  • -N new_passphrase: 指定新的私钥密码
  • -C comment: 添加注释, 通常是用户的签名
  • [-f output_keyfile]: 保存密钥的文件, 默认为~/.ssh/id_rsa

打开~/.ssh/id_rsa.pub可以看到自己的公钥, 将公钥的内容添加到远程计算机的~/.ssh/authorized_keys中,然后重启远程计算机的sshd使新的配置生效。

为了保证安全,其它用户不能拥有修改密钥的权限,若系统检测到其它用户有密钥的写(w)权限将会拒绝使用该密钥。因此,我们将.ssh目录权限设置为700, 目录下所有相关文件权限设置为600

在终端中再次使用ssh命令登录时就不需要输入远程计算机的登录口令了。

通常情况下我们只需要一对密钥, 就像我们可以使用同一个身份证在不同的地方证明我们的身份一样, 只不过防伪的不是难以伪造的证件而是难以猜测的私钥.

传输文件

基于ssh传输文件是一个非常方便的功能, scp可以通过ssh通道在本地计算机和远程计算机之间传递文件.

scp会先使用ssh的认证方式建立安全链接, 然后完成文件传输, 完成传输后立即断开连接.

在本地计算机的终端中执行scp命令从远程计算机下载文件:

# format : scp user@host:remote_path local_path
$ scp ubuntu@qcloud:~/1.txt 1.txt

注意在本地终端执行, 而非使用ssh命令登录的远程终端.

scp命令与cp命令相似,第一个参数为源地址,第二个参数为目标地址, 只不过支持远程路径.

在复制目录下的所有内容时同样需要-r参数:

# format: scp -r user@host:remote_path local_path
$ scp -r ubuntu@qcloud:~/workspace workspace

目的地址写为远程地址即可将本地文件上传到远程计算机:

# format: scp local_path user@host:remote_path
$ scp 1.txt ubuntu@qcloud:~/1.txt
# format scp -r local_path user@host:remote_path
$ scp -r workspace ubuntu@qcloud:~/workspace

使用跳板机

出于安全原因,通常集群中只有网关机可以从外网登录,内网中机器只能从网关机登录。若先登录网关机作为跳板,再从网关机上登录目标机则非常麻烦。

我们可以使用ssh的ProxyCommand功能自动使用跳板机登录内网:

$ ssh username@internal -o ProxyCommand='ssh username@gateway -W %h:%p'

其中,ProxyCommand是登录跳板机的ssh指令,internal是内网中目标机的地址。ssh username@internal将在跳板机上执行,internal通常为目标机的内网ip地址。

注意,这种方式要求目标机的authorized_keys中包含本地计算机的密钥。

配置主机别名

每次ssh登录都需要输入很长的指令是一件很麻烦的事情,我们可以在~/.ssh/config文件中配置主机别名极大的简化登录指令:

Host gateway # 主机别名,使用`ssh gateway`命令可以直接登录该主机
Protocol 2 # ssh协议版本
HostName example.com # 主机地址,支持IP或域名
Port 22 # ssh服务端口号
User ubuntu # 登录用户名
IdentityFile ~/.ssh/id_rsa # 使用的私钥文件 Host internal # 主机别名,这是一个自动跳转示例
Protocol 2
HostName 192.168.1.111 # 目标机的内网ip地址,通常不使用域名
Port 22 # 内网中目标机的ssh服务端口号
User ubuntu # 登录目标机的用户名
ProxyCommand ssh gateway -W %h:%p # 登录跳板机的ssh指令,这里使用上一条配置的别名
IdentityFile ~/.ssh/id_rsa # 登录跳板机的私钥文件,该密钥必须包含在跳板机的authorized_keys中 Host 10.10.0.* # 使用通配符的示例,登录HostName符合通配符的主机都可以用该配置,如:`ssh ubuntu@10.10.0.1`
Port 22
User ubuntu
ProxyCommand ssh gateway -W %h:%p

端口转发

SSH可以通过端口转发为其它协议提供安全通信. 端口转发中涉及四台主机:

  • 本地主机LocalHost: 运行SSH客户端的主机, 即用户操作的主机
  • 远程主机RemoteHost: 运行SSH服务端的主机
  • 源主机SrcHost: 发送请求的主机
  • 目的主机DestHost: 请求要前往的主机

本地端口转发是由ssh客户端监听本地端口, 并将发往该端口的通信由远程主机发往目标:

ssh -L LocalPort:DestHost:DestPort user@RemoteHost

配置本地转发后:

  1. 本地SSH客户端将监听LocalPort端口
  2. 所有发往该本地端口的请求将被通过SSH信道发往远程主机RemoteHost
  3. 远程主机上的SSH服务端会将请求转发到目标主机DestHost上的DestPort端口
  4. 目标主机的响应将被RemoteHost和LocalHost依次转发, 原路返回来源主机

远程转发的过程正好与本地转发相反:

ssh -R RemotePort:DestHost:DestPort user@RemoteHost

配置远程转发后:

  1. 远程主机RemoteHost上的SSH服务端将监听RemoteHost上的RemotePort端口
  2. 所有发送到RemoteHost得RemotePort端口上的请求将通过SSH信道发往本地
  3. 本地主机上的SSH客户端将请求转发到目标主机DestHost上的DestPort端口
  4. 目标主机的响应将被LocalHost和RemoteHost依次转发, 原路返回来源主机

本地转发只能请求发往固定的目的主机和目的端口, 而动态转发则会根据请求的目的和协议决定转发到的目的主机和目的端口.

ssh -D LocalPort user@RemoteHost

ssh客户端将会监听所有发往本地LocalPort的请求, 并通过远程主机中转, 转发到请求的目的地址.

该过程与本地转发类似, 不过目的主机与目的端口是根据请求动态决定的.

安全通信原理

在进一步介绍认证过程之前, 需要先介绍一下对称加密和非对称加密的概念.

  • 对称加密: 加密和解密的密钥相同. 如典型的移位密码: C代替A,D代替B...

    这里向后移两位就是密钥, 得知向后移两位后可以将明文加密也可以将密文解密.

  • 非对称加密: 加密密钥与解密密钥不同. 通常加密密钥公开(公钥), 解密密钥私有(私钥), 且很难通过公钥推断私钥.

非对称加密方式下, 所有人都可以使用公钥对明文进行加密, 但是只有持有私钥的人才可以解密密文.

一般来说, 对称加密方式的加解密速度比非对称方式更快.

现在, 我们可以开始介绍SSH认证和安全通信的原理了.

协议协商阶段

建立SSH安全链接的第一个阶段为协议协商阶段:

  1. 服务端监听端口等待客户端连接
  2. 客户端发起TCP连接请求, 服务端接收到该请求后,向客户端发送SSH协议版本信息.
  3. 客户端接根据该版本信息与自己的版本,决定将要使用的SSH版本,并向服务端发送选用的SSH版本信息
  4. 服务端检查是否支持客户端的决定使用的SSH版本

至此,双方完成协议协商。如果该过程中,客户端或服务端发送SSH版本无法兼容,任何一方都可以断开连接.

此时双方建立明文信道, 均无法确认对方身份.

服务端认证阶段

随后进入服务端认证阶段:

  1. 服务端向客户端发送下列信息:

    • 服务端身份公钥(Host Key), 用于认证服务端身份
    • 服务端通信公钥(Server Key), 用于生成通信加密密钥
  2. 客户端根据Host Key, 查询known_hosts或交由用户判断是否信任该服务端.

    若信任则继续,否则断开连接

  3. 客户端随机生成会话密钥(Session Key), 并使用服务端通信公钥(Server Key)加密后发给服务端

  4. 服务端用自己的私钥解密得到会话密钥(Session Key)

本阶段仍然使用明文信道, 当本阶段结束时双方都有了相同且安全的会话密钥. 此后的通信过程中, 双方将使用会话密钥对称加密进行安全通信.

客户端认证阶段

随后进入客户端认证阶段, 此阶段双方已建立对称加密安全信道.

  • 口令方式: 客户端提供用户和口令,服务端进行匹配完成认证.

  • 密钥方式:

    1. 客户端发起一个Public Key认证请求
    2. 服务端检查是否存在请求帐号的公钥(一般在~/.ssh/authorized_keys文件中),以及其拥有的访问权限, 如果没有则断开连接.
    3. 服务端使用客户端发送的公钥对一个随机的256位的字符串进行加密,并发送给客户端.
    4. 客户端使用私钥对字符串进行解密,并生成一个MD5值发送给服务端
    5. 服务端根据原始随机字符串生成MD5值进行匹配, 确认客户端身份

至此, 双方互相确认对方身份并建立加密信道, 可以正式进行安全通信。

SSH原理和应用的更多相关文章

  1. SSH原理与运用

    SSH是每一台Linux电脑的标准配置. 随着Linux设备从电脑逐渐扩展到手机.外设和家用电器,SSH的使用范围也越来越广.不仅程序员离不开它,很多普通用户也每天使用. SSH具备多种功能,可以用于 ...

  2. SSH原理与运用(二):远程操作与端口转发

    SSH原理与运用(二):远程操作与端口转发 作者:阮一峰 (Image credit: Tony Narlock) 七.远程操作 SSH不仅可以用于远程主机登录,还可以直接在远程主机上执行操作. 上一 ...

  3. SSH原理与运用(一)和(二):远程登录 RSA算法原理(一)和(二)

    SSH原理与运用(一)和(二):远程登录  RSA算法原理(一)和(二) http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html ht ...

  4. SSH原理与运用一:远程登录(转)

    原文:http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html 作者: 阮一峰 SSH是每一台Linux电脑的标准配置. 随着Linux ...

  5. ssh原理[转]

    SSH是每一台Linux电脑的标准配置. 随着Linux设备从电脑逐渐扩展到手机.外设和家用电器,SSH的使用范围也越来越广.不仅程序员离不开它,很多普通用户也每天使用. SSH具备多种功能,可以用于 ...

  6. Hadoop第一式:配置Linux环境之免密配置及SSH原理

    一.配置SSH免密登录 进入/.ssh目录,执行密钥生成指令 ssh-keygen -t rsa (rsa为默认加密格式) 然后会出现四个提示,让你选择密钥保存路径.指纹.拍照啥的,不用管它直接回车过 ...

  7. ssh原理图解

    SSH(Secure Shell)是一种能够以安全的方式提供远程登录的协议,也是目前远程管理Linux系统的首选方式.在此之前,远程登录一般常用FTP和Telnet,但是它们以明文的形式在网络中传输账 ...

  8. 图解SSH原理及两种登录方法

    SSH(Secure Shell)是一套协议标准,可以用来实现两台机器之间的安全登录以及安全的数据传送,其保证数据安全的原理是非对称加密. 传统的对称加密使用的是一套秘钥,数据的加密以及解密用的都是这 ...

  9. SSH原理与运用(一):远程登录(转)

      作者: 阮一峰 日期: 2011年12月21日 SSH是每一台Linux电脑的标准配置. 随着Linux设备从电脑逐渐扩展到手机.外设和家用电器,SSH的使用范围也越来越广.不仅程序员离不开它,很 ...

  10. 图解SSH原理

    1. 初见SSH SSH是一种协议标准,其目的是实现安全远程登录以及其它安全网络服务. SSH仅仅是一协议标准,其具体的实现有很多,既有开源实现的OpenSSH,也有商业实现方案.使用范围最广泛的当然 ...

随机推荐

  1. activeMq-2 高可用以及集群搭建

    Activemq 的集群方法可以有多种实现方式,我们这里使用zookeeper来实现 要搭建集群,请确保已经搭建好zookeeper环境.这里不再演示. 基本原理: 使用ZooKeeper(集群)注册 ...

  2. iframe和选项卡面板切换

    <div class="col-sm-6"> <div class="tabs-container"> <ul class=&qu ...

  3. MySQL 查看修改字符集

    查看MYSQL数据库服务器和数据库字符集 方法一:show variables like '%character%'; 方法二:show variables like 'collation%'; sh ...

  4. 20155326刘美岑 《网络对抗》Exp1 PC平台逆向破解

    20155326刘美岑 <网络对抗>逆向及Bof基础实践 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函 ...

  5. Android开发 - 设置DialogFragment全屏显示

    默认的DialogFragment并不是全屏,但有些需求需要我们将对话框设置为全屏(内容全屏),Android并没有提供直接的API,通过其它不同的方法设置全屏在不同的机型上总有一些诡异的问题,经过测 ...

  6. JavaScript学习之路-语法

    版权声明:未经博主允许不得转载 在JavaScript中如何写语法呢?这里你可以去看一些教学文档来得快一些,这里不介绍,有点基础的也可以复习一下. //定义变量并赋值 var a; //定义变量 va ...

  7. 用redux-thunk异步获取数据

    概述 最近学习redux,打算用redux-thunk给todo添加异步获取数据组件.记录下来,供以后开发时参考,相信对其他人也有用. 注意: 在todo下方,我异步获取我的react博客的标题,点击 ...

  8. Swift5 语言指南(十二) 属性

    属性将值与特定类,结构或枚举相关联.存储的属性将常量和变量值存储为实例的一部分,而计算属性则计算(而不是存储)值.计算属性由类,结构和枚举提供.存储的属性仅由类和结构提供. 存储和计算属性通常与特定类 ...

  9. Swift5 语言指南(十) 枚举

    一个枚举定义了一个通用型的一组相关的值,使你在你的代码中的一个类型安全的方式这些值来工作. 如果您熟悉C,您将知道C枚举将相关名称分配给一组整数值.Swift中的枚举更灵活,并且不必为枚举的每个案例提 ...

  10. 转载 用Python实现设计模式——工厂模式

    转载自 SegmentFault作者 夏秋, https://segmentfault.com/a/1190000013053013 非常感谢这位作者的深入浅出的讲解. 前言 工厂模式,顾名思义就是我 ...