ssh的理解和使用

ls ~/.ssh/            
config   id_rsa    id_rsa.pub   known_hosts   test.crt   test.key   testenc.key

SSH

SSH 为 Secure Shell 的缩写,由 IETF 的网络小组( Network Working Group)所制定;SSH 为创建在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登陆会话和其余网络服务提供安全性的协议。利用 SSH 协议能够有效防止远程管理过程当中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其余操做平台。 SSH在正确使用时可弥补网络中的漏洞。SSH客户端适用于多种平台。几乎全部 UNIX平台—包括 HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其余平台,均可运行SSH。

SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。本文针对的实现是OpenSSH,它是自由软件,应用很是普遍。SSH在Linux Shell中的用法。若是要在Windows系统中使用SSH,会用到另外一种软件PuTTYhtml

基本的用法

SSH主要用于远程登陆。假定你要以用户名user,登陆远程主机host,只要一条简单命令就能够了。linux

$ ssh user@host

若是本地用户名与远程用户名一致,登陆时能够省略用户名。git

$ ssh host

SSH的默认端口是22,也就是说,你的登陆请求会送进远程主机的22端口。使用p参数,能够修改这个端口。github

$ ssh -p 2222 user@host

上面这条命令表示,ssh直接链接远程主机的2222端口。算法

链接方式

SSH之因此可以保证安全,缘由在于它采用了公钥加密。shell

整个过程是这样的:ubuntu

  1. 远程主机收到用户的登陆请求,把本身的公钥发给用户。
  2. 用户使用这个公钥,将登陆密码加密后,发送回来。
  3. 远程主机用本身的私钥,解密登陆密码,若是密码正确,就赞成用户登陆。

安全隐患

上面所述的 SSH登入过程自己是安全的,可是实施的时候存在一个风险:若是有人截获了登陆请求,而后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。由于不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是本身签发的。安全

能够设想,若是攻击者插在用户与远程主机之间(好比在公共的wifi区域),用伪造的公钥,获取用户的登陆密码。再用这个密码登陆远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"Man-in-the-middle attack)。服务器

第一次登入

为了应对上述的中间人攻击,在用户第一次登陆对方主机,系统会出现下面的提示:网络

$ ssh user@host

  The authenticity of host 'host (12.18.429.21)' can't be established.

  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.

  Are you sure you want to continue connecting (yes/no)?

这段话的意思是,没法确认host主机的真实性,只知道它的公钥指纹,问你还想继续链接吗?

所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,因此对其进行MD5计算,将它变成一个128位的指纹。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再进行比较,就容易多了。

很天然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在本身的网站上贴出公钥指纹,以便用户自行核对。

假定通过风险衡量之后,用户决定接受这个远程主机的公钥。

Are you sure you want to continue connecting (yes/no)? yes

系统会出现一句提示,表示host主机已经获得承认。

Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.

而后,会要求输入密码。

Password: (enter password)

若是密码正确,就能够登陆了。

当远程主机的公钥被接受之后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再链接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

每一个SSH用户都有本身的known_hosts文件,此外系统也有一个这样的文件,一般是/etc/ssh/ssh_known_hosts,保存一些对全部用户均可信赖的远程主机的公钥。

config配置

在经过known_hosts的记录远程主机的公钥可信度以后,每次登录都须要书写一堆 登录命令 ,为了简而书写,能够经过config文件来进行配置,配置前咱们登录:

ssh username@hostname -p port

而后输入密码;在创建配置文件,touch ~/.ssh/config配置后,咱们只须要输入链接帐户的别名便可

ssh 别名

配置方法:

在.ssh/config中配置,若是没有config,建立一个便可,而后将下面的(别名,主机名,端口,用户名替换便可),端口若是默认22能够不要,删除那行便可。
Host 别名
    Hostname 主机名
    Port 端口
    User 用户名
    IdentifyFile 指定的私钥地址

配置好以后,就能够直接ssh 别名链接了,不须要输入一长串,可是仍是有一个问题,就是仍是须要输入密码。解决办法就是将咱们的公钥拷贝到链接的机器上来免密登录就能够了【config文件中的字段IdentifyFile就是制定了和公钥配对的私钥,已达到免密登入的便捷】。

免密登入【公钥登陆】

使用密码登陆,每次都必须输入密码,很是麻烦。好在SSH还提供了公钥登陆,能够省去输入密码的步骤。

所谓"公钥登陆",原理很简单,就是用户将本身的公钥储存在远程主机上。登陆的时候,远程主机会向用户发送一段随机字符串,用户用本身的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,若是成功,就证实用户是可信的,直接容许登陆shell,再也不要求密码。

这种方法要求用户必须提供本身的公钥。若是没有现成的,能够直接用ssh-keygen生成一个:

$ ssh-keygen

运行上面的命令之后,系统会出现一系列提示,能够一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),若是担忧私钥的安全,这里能够设置一个。

运行结束之后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pubid_rsa。前者是你的公钥,后者是你的私钥。

这时再输入下面的命令,将公钥传送到远程主机host上面:

$ ssh-copy-id user@host

好了,今后你再登陆,就不须要输入密码了【ssh-copy-id这个命令可能有问题,ssh-copy-id可能的问题】。

若是仍是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,检查下面几行前面"#"注释是否取掉。

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

而后,重启远程主机的ssh服务。

  // ubuntu系统
  service ssh restart

  // debian系统
  /etc/init.d/ssh restart

authorized_keys文件

远程主机将用户的公钥,保存在登陆后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就好了。

这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:

$ ssh user@host 'mkdir -p .ssh && chmod 700 ~/.ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

这条命令由多个语句组成,依次分解开来看:

  1. "$ ssh user@host",表示登陆远程主机;
  2. 单引号中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登陆后在远程shell上执行的命令:
  3. "$ mkdir -p .ssh"的做用是,若是用户主目录中的.ssh目录不存在,就建立一个;
  4. 'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的做用是,将本地的公钥文件~/.ssh/id_rsa.pub,重定向追加到远程文件authorized_keys的末尾【须要注意, .ssh/authorized_keys这个文件可能没有,执行touch .ssh/authorized_keys,有了authorized_keys以后,权限可能须要修改,chmod 640 ~/.ssh/authorized_keys,而后才是把公钥追加进去】。
最好把权限设置上
$ chmod 600 ~/.ssh/authorized_keys
$ chmod 700 ~/.ssh

写入authorized_keys文件后,公钥登陆的设置就完成了。

跳板机登入

在不少时候,咱们的本地机器是没法直接访问远程主机的,而是经过跳板机来完成的,A是本地机器,B是跳板机,C是线上机器。

+-----+             +-----+             +-----+
|     |             |     |             |     |
|  A  +-----------> |  B  +-----------> |  C  |
|     |             |     |             |     |
+-----+             +-----+             +-----+

而在这种过程中,咱们不得不输入两次密码【可能密码还不同】,不管是scp获取文件仍是登入都变得繁琐,为了可以直接A->C

+-----+             +-----+             +-----+ 
|     |             |     |             |     | 
|  A  +-------------------------------> |  C  |
|     |             |     |             |     | 
+-----+             +-----+             +-----+

这就是经过“ProxyCommand”选项,机器A可以灵活使用任意代理机制与机器C上的SSH Server端口创建链接,接着机器A上的SSH Client再与该链接进行数据交互,从而机器A上的SSH Client与机器C上的SSH Server之间创建了与通常“直接SSH链接”不太同样的“间接SSH链接”。不过因为“间接SSH链接”的透明性,逻辑上可认为机器A上的SSH Client与机器C上的SSH Server创建了“直接SSH链接”。

clipboard.png

本机、跳板机、目标机器三者已经作过公钥认证(若是不作密钥认证就会提示分别输入跳板机和目标机器的密码,须要多输入两次密码比较繁琐);下面的案例前提都是咱们能够免密登入跳板机;

$ mkdir -p ~/.ssh/persist
$ scp 用户名@跳板机:~/.ssh/id_rsa ~/.ssh/id_rsa.cn6  #拷贝跳板机的密钥到本地,不一样的跳板机能够起不一样的名字,好比id_rsa.cn8
# 能够是删除跳板机上的秘钥对设置的密码,从新生成无密码秘钥对,也能够跳过这一步。
$ cd .ssh
$ ssh-keygen -p
Enter file in which the key is : id_rsa.cn6 # 输入刚才的拷贝的密钥文件名
Enter old passphrase: # 输入passphrase
Key has comment 'id_rsa.cn6'
Enter new passphrase (empty for no passphrase): # 直接回车
Enter same passphrase again: # 直接回车
Your identification has been saved with the new passphrase.

方案都是使用ssh ProxyCommand:

ProxyCommand ssh proxyserver -W [%h]:%p

ProxyCommand ssh proxyserver nc -q0 %h %p 2> /dev/null

ProxyCommand ssh proxyserver exec nc -q0 %h %p 2> /dev/null

%h[host]和%p[port]被SSH客户端替换以指示预期目的地,ProxyCommand基本思路:SSH能够调用外部应用程序,指望它与目标主机创建链接。创建链接后,应用程序必须使用stdin / stdout公开链接。

代理机制一"ssh -W" mode

ProxyCommand选项值形式为[OpenSSH 5.3以上才支持]

ssh -W C:CPort -l USER -i PRIVATE_KEY -p BPort B

原理:ssh命令自提供的代理机制,在机器A上另外单独创建与B的SSH链接(使用-l USER -i PRIVATE_KEY -p BPort B这些参数),并在B端创建端口映射监听终端信息,然后B端与机器C上的SSH Server端口(即“C:CPort”)创建ssh链接,在C上创建端口映射监听终端信息,并在C端发起和B端的其余连接【tcp/socket】,将C端的标准输入输入映射到B端,供B和A的ssh链接使用。

假定A上ssh_config配置文件内容以下:

Host B
    HostName %h
    User dsl
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6

Host C
    HostName %h
    User dsl 
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
    ProxyCommand ssh -W %h:%p B

在A上执行ssh C命令,发现A与C成功创建SSH链接。根据以上所述,A机器经过ssh链接了B机器,而后B机器连接C机器,同时,须要C机器经过链接在stdin/stdout上与B创建通讯,而后将通讯结果返回给A。

常使用代理制剂二netcat

在最开始的时候,-W参数尚未引入,可使用nc实现【因此两个很相似,之是方式略有不一样,特别是B端和C端的nc的连接是由B端发起的,而不是C端发起】,ProxyCommand选项值形式为

nc -X 5 -x B:BPort C CPort
ProxyCommand nc %h %p

原理:利用nc | netcat命令,在登陆代理机器B后,B机器须要经过nc创建和机器C的连接,经过链接在stdin/stdout上与C创建通讯后,而后将通讯结果返回给A。

假定A上ssh_config配置文件内容以下:

Host B
    HostName %h
    User dsl
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
Host C
    HostName %h
    User dsl 
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
    ProxyCommand ssh B exec nc %h %p 2> /dev/null

全文参考:
SSH原理与运用,
proxycommand
支持跳板机间接连接线上机,
SSH穿越跳板机:一条命令跨越跳板机直接登录远程计算机
使用SSH ProxyCommand 配置跳板机登陆生产环境机器
ssh 如何快速免密码登陆服务器
What is the difference between ssh proxycommand -W, nc, exec nc
如何透过 SSH 代理穿越跳板机
Netcat with SSH Port Forwarding

相关文章
相关标签/搜索