引子:
第一次接触到SSH,也是第一次接触到Linux(Unix Like)系统,时间上说不上来了,SSH算得上是Linux系统的的一个标准配置,对SSH的印象,它就是一种远程连接的工具,有了它就能安全的与远程主机进行连接。
(一)、什么是SSH
SSH的全称是Secure Shell,简单说来ssh是一种安全的外壳协议,用于两个计算机间安全的远程登陆,说它安全,是因为ssh采用公钥加密的机制。
最开始时用作远程管理的工具是telnet,这个协议工作时在网络上传输的数据全是明文,出于安全性的考虑,此协议的使用率越来越少。而ssh的安全性使用它成为一种互联网上远程登陆主机的解决方案。
在windows系统上常用到的有Putty、SecureCRT、XManager中的Xshell工具,而XManager工具是我见到的IT工作者中使用频率极高的一个工具,在windows上好像没有ssh协议的服务器端的实现,ssh协议的实现也分为商业的实现和开源的实现,在这里将是对ssh协议的一个开源实现的学习与记录。Openssh即是Linux系统下开源的实现,它开放且免费。
(二)、ssh工作原理
说ssh是种安全的协议,是因为它采用公钥加密。用主机A连接主机B来说明这个过程:
1、主机A向主机B发起登陆请求;
2、主机B向主机A发送公钥文件;
3、主机A把登陆密码用接收到的公钥加密后发送给主机B;
4、主机B用自己的私钥解密加密信息,得到登陆密码;
5、主机B验证密码的正确性,正确则让其登陆,否则则断开。
(三)、中间人攻击(Man-in-the-middleattack)
基于公钥加密这种验证方式看起比较完美,登陆密码的传输都是经过公钥加密处理,即使被恶意劫持,只要私钥文件没有被泄露,那也不能解密加密信息,密码的保密性得到保障。但这种看似完美的工作方式也有其致命的弱点,如果主机B是黑客伪装的,他接收到主机A的登陆主机B的登陆请求,用自己的公钥发送给主机A,而主机A很难辨别主机B的真伪,黑客就可以采取这种方式获得主机B正确的登陆密码,这就是有名的中间人攻击(Man-in-the-middleattack)。
要想应对中间人的攻击,则需避免登陆时输入用户口令的操作,ssh中的认证方式有两种,一种是基于口令的方式,另一种是基于公钥的认证方式,后者就能在用户不输入口令的情况下登陆主机。
(四)、配置文件
系统环境:
[[email protected]~]# cat /etc/redhat-releaseCentOSrelease 6.4 (Final)[[email protected]~]# uname -mx86_64
先看一下系统中安装openssh所用的安装包:
[[email protected]~]# rpm -qa *ssh*openssh-5.3p1-84.1.el6.x86_64openssh-clients-5.3p1-84.1.el6.x86_64libssh2-1.4.2-1.el6.x86_64openssh-server-5.3p1-84.1.el6.x86_64
可以用“rpm -ql 安装包名称”命令来查看各个安装名生成的目录结构,如下:
[[email protected]~]# rpm -ql openssh-clients
对于openssh,我们需要关注的配置文件分为两类,一类是公共配置文件,另一类是私有配置文件。公共配置文件又分为服务端的配件文件和客户端的配置文件。
/etc/ssh/sshd_config #服务端配置文件
/etc/ssh/ssd_config #客户端配置文件
~/.ssh/* #私有配置文件
我们主要关注的是服务端的配置文件和私有配置文件。
(五)、认证方式
ssh支持两种认证方式,一种是基于用户名与口令的认证,另一种是基于密钥的认证。
5.1 基于用户名与口令认证:客户端通过输入用户名与用户登陆密码的方式完成远程登陆,虽说是要求输入用户名及密码来验证,但ssh也会涉及到公钥的发送,即远程主机收到用户远程登陆请求时会把自己的公钥发送给用户端。
在windows下以ssh的方式登陆linux主机时,以xmanager为例,当用xmanager中的xshell第一次登陆linux主机时会有以下的提示:
大致意思就是用户包要连接的主机在用户本地的存储key的数据库中没有存储,主机是不可信任的,并且给出了远程主机公钥的摘要信息,是否要断续的连接此主机?那怎样来验证我所要连接的主机(192.168.0.201)是真实的,不是一个伪装的主机,避免中间人攻击。当点击“Accept&Save”,那xshell会把远程主机的公钥信息保存下来,在这里可以查看到:
应对中间人攻击,SSH有2种方法,一是远程主机把自己的公钥拿到CA处做认证,申请一个数字证书;二是远程主机把自己公钥的指纹信息公布出来,比如公布在网站上,大家都可查看到公钥的指纹信息。这样用户在登陆时就可以鉴别主机的真伪了。提取主机的指纹信息的方法如下:
[[email protected] ~]# ssh-keygen -lf/etc/ssh/ssh_host_dsa_key.pub 102439:61:e5:80:e8:09:b3:83:10:39:c8:b4:5e:ca:45:7e /etc/ssh/ssh_host_dsa_key.pub(DSA)
远程主机可以把这个采用dsa算法的指纹信息发布在一个网站上,那我用xshell去远程连接时就可对比一下指纹信息是不是一样,如果是一样的那就能证明我连接的是真实的主机。
在linux下用ssh方式登陆另一linux主机时,如果第一次登陆会有如下的提示:
[[email protected]~]# ssh 192.168.0.201Theauthenticity of host ‘192.168.0.201 (192.168.0.201)‘ can‘t be established.RSAkey fingerprint is 4c:a3:2f:29:69:86:f6:0f:38:25:8c:7c:7c:3b:d5:91.Areyou sure you want to continue connecting (yes/no)?
表示的意义与用xshell登陆时的提示相同,输入“yes”,再输入远程主机的口令即可登陆,登陆成功后本地主机会生成“~/.ssh/known_hosts”文件,这文件里保存着远程主机的公钥信息,这样下次再远程登陆时就不需要发送公钥信息了,直接输入口令即可。
5.2 基于公钥的认证:基于用户口令的认证方式每次都要求用户提供正确的口令,比较麻烦,且增加了口令泄露的机率。而基于公钥的认证则不需要用户输入口令即可完成远程登陆。这种认证方式是这样工作的:用户把自己的公钥存储在远程主机上,在登陆时,远程主机向用户发送一段随机字符串,用户用自己的私钥加密这段随机数字,并把加密后的信息发送给远程主机,远程主机用事先存储的公钥来解密这个数据,如果解密成功,则说明请求登陆的用户是可信任的,这样就直接允许用户登陆,而不要求输入密码了。
这种认证方式,需要用户自己的公钥,并把公钥保存到远程主机上。若没有现成的公钥,那就生成:
[[email protected]~]# ssh-keygen -t rsaGeneratingpublic/private rsa key pair.Enterfile in which to save the key (/root/.ssh/id_rsa): Enterpassphrase (empty for no passphrase): Entersame passphrase again: Youridentification has been saved in /root/.ssh/id_rsa.Yourpublic key has been saved in /root/.ssh/id_rsa.pub.Thekey fingerprint is:9b:ef:2c:6a:92:05:c7:f4:4b:b8:4e:b4:ce:05:2f:[email protected]Thekey‘s randomart image is:+--[RSA 2048]----+| || . || o o || E * o || * *S. || B +o || B oo || o = .o || o.. o+ |+-----------------+[[email protected]~]# ls .ssh/id_rsa id_rsa.pub known_hosts
此时在家目录下的“./ssh”目录下生成了两个文件,一个id_rsa(私钥文件),id_rsa.pub(公钥文件)。接着把公钥文件拷贝到远程主机:
[[email protected] ~]# scp .ssh/id_rsa.pub 192.168.0.201:/root/.ssh/authorized_keys
这里的“authorized_keys”这个文件名不能更改,这是由“/etc/ssh/sshd_config”文件定义的。
测试一下能否不输入密码就能远程登陆Server_B主机:
[[email protected] ~]# ssh 192.168.0.201Address 192.168.0.201 maps to bogon, butthis does not map back to the address - POSSIBLE BREAK-IN ATTEMPT![[email protected] ~]#
没错,成功了,但有报告信息,这是因为在/etc/hosts文件里没有增加两主机的映射关系,增加就可以了,在两主机中的“/etc/hosts”文件中都增加以下两行:
[[email protected] ~]# echo"192.168.0.200 Server-A">> /etc/hosts[[email protected] ~]# echo "192.168.0.201 Server-B" >> /etc/hosts
上边用“scp”命令直接把主机的公钥文件拷贝到远程主机用户家目录下的“root/.ssh/authorized.keys”,其实还有一个更好的方法,ssh为我们提供了一个客户端工具,即“ssh-copy-id”,这个工具能将本地主机的公钥自动拷贝到远程主机上生成“authorized.keys”文件,且会让这个文件的权限为“600”这样更为安全,此命令的用法如下:
[[email protected] ~]# ssh-copy-id [email protected]
建议用这个命令来实现无密码公钥登陆,因为用“scp”命令把公钥拷贝到远程主机后,不把authorized.keys文件的权限修改成“600”,在某些linux版本下是无法实现基于公钥登陆的。
用xshell这个神器也可实现基于公钥的认证,方法与在linux上类似,只是连接主机成了windows下的了,方法如下:
1、打开密钥生成向导工具
2、选择密钥的类型与加密长度
3、直接下一步
4、下一步
5、导出公钥信息
6、完成
这样就生成了一个“id_rsa_1024.pub”公钥文件,把这个公钥文件上传到远程主机,并把公钥信息追加到“~/.ssh/authorized_keys”。
最后配置xshell使用密钥方式登陆服务器:
1、打开Xshell,点击“New”按钮,弹出“NewSession Properties”对话框,在“Connection”栏目中,填写好相关信息,如下图:
2、在“Authentication”中填写认证方式和私钥,如下图:
这样设置好后,xshell也可以基于密钥登陆远程主机了。