码迷,mamicode.com
首页 > 其他好文 > 详细

ssh 原理和基本使用

时间:2015-05-01 01:54:54      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:linux   ssh   安全   openssh   密钥   

一、什么是 SSH ?

 SSH(Secure SHell)是一种网络协议,顾名思义就是非常安全的shell,主要用于计算机间加密传输。早期,互联网通信都是基于明文通信,一旦被截获,内容就暴露无遗。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。SSH的主要目的是用来取代传统的telnet 和 R 系列命令(rlogin, rsh, rexec 等)远程登录和远程执行命令的工具,实现对远程登录和远程执行命令加密,防止由于网络监听而密码泄露问题。

    需要指出的是,SSH 只是一种协议(规范),存在很多实现方式,既有商业实现,也有开源实现

    ssh协议目前有SSH1和SSH2两个主流版本,SSH2协议兼容SSH1。目前实现SSH1和SSH2协议的主要软件有OpenSSH 和SSH Communications Security Corporation 公司的SSH Communications 软件。前者是OpenBSD组织开发的一款免费的SSH软件,后者是商业软件,因此在linux、FreeBSD、OpenBSD、NetBSD等免费类UNIX系统种,通畅都使用OpenSSH作为SSH协议的实现软件。因此,本文重点介绍一下OpenSSH的使用。需要注意的是OpenSSH和SSH Communications的登陆公钥/私钥的格式是不同的,如果想用SSH Communications产生的私钥/公钥对来登入到使用OpenSSH的linux系统需要对公钥/私钥进行格式转换。

        

    OpenSSH 是一组用于安全地访问远程计算机的连接工具。 它可以作为 rlogin、 rsh rcp 以及 telnet 的直接替代品使用。 更进一步, 其他任何 TCP/IP 连接都可以通过 SSH 安全地进行隧道/转发。 OpenSSH 对所有的传输进行加密, 从而有效地阻止了窃听、 连接劫持, 以及其他网络级的攻击。

    在出现SSH之前,系统管理员需要登入远程服务器执行系统管理任务时,都是用telnet 或者 rlogin 来实现的,telnet协议采用明文密码传送,在传送过程中对数据也不加密,很容易被不怀好意的人在网络会话中窃取到传输的用户名/密码和数据。同样,在SSH工具出现之前R系列命令也很流行(由于这些命令都以字母r开头,故把这些命令合称为R系列命令R是remote的意思),比如rexec是用来执行远程服务器上的命令的,和telnet的区别是telnet需要先登陆远程服务器再实行相关的命令,而R系列命令可以把登陆和执行命令并登出系统的操作整合在一起。这样就不需要为在远程服务器上执行一个命令而特地登陆服务器了。

    SSH是一种加密协议,不仅在登陆过程中对密码进行加密传送,而且对登陆后执行的命令的数据也进行加密,这样即使别人在网络上监听并截获了你的数据包,他也看不到其中的内容。OpenSSH已经是目前大多数linux和BSD操作系统(甚至cygwin)的标准组件,因此关于如何安装OpenSSH本文就不再叙述了,如果不出意外,你的系统上必定已经安装好了OpenSSH。

    OpenSSH 软件包包含了以下程序:

sshd -- SSH服务端程序

sftp-server -- SFTP服务端程序(类似FTP但提供数据加密的一种协议)

scp -- 非交互式sftp-server的客户端,用来向服务器上传/下载文件,安全复制

sftp -- 交互式sftp-server客户端,用法和ftp命令一样。

slogin -- ssh的别名

ssh -- SSH协议的客户端程序,用来登入远程系统或远程执行命令

ssh-add  --   SSH代理相关程序,用来向SSH代理添加dsa key

ssh-agent  --   ssh代理程序

ssh-keygen  -- ssh public key 生成器

    

    SSH最常用的使用方式是代替telnet进行远程登陆。不同于telnet的密码登陆,SSH还同时支持Publickey、Keybord Interactive、GSSAPI等多种登入方式,不像telnet那样只有输入系统密码一种途径。目前最常用的登陆方式还是传统的Password方式Publickey方式登陆。

SSH提供两种方式的登录验证:

1、密码验证:以服务器中本地系统用户的登录名称,密码进行验证。

2、秘钥对验证:要求提供相匹配的秘钥信息才能通过验证。通常先在客户机中创建一对秘钥文件(公钥和私钥),然后将公钥文件放到服务器中的指定位置。

注意:当密码验证和私钥验证都启用时,服务器将优先使用秘钥验证。


二、基本使用

1、用于代替 telnet, 进行远程登录。
# ssh user@host
2、如果bending用户名与远程主机用户名一致,登录时可以省略用户名。
# ssh host
3、ssh 协议默认端口 22,也就是缺省情况是连接远程主机的22号端口,使用 -p 参数可以指定端口号
# ssh -p 2222 user@host

4、ssh 远程执行命令
# ssh user@host ‘ls -l /etc‘
输入正确的密码后,ssh会链接远程服务器的sshd服务器程序,然后执行远程服务器上的 ls –l /etc 命令 ,并把输入结果传到本地服务器。相当于你先登陆到远程服务器,然后再实行命令ls –l /,最后再登出服务器。

三、中间人攻击

    SSH之所以能够保证安全,原因在于它采用了公钥加密。

    整个过程是这样的:

(1)远程主机收到用户的登录请求,把自己的公钥发给用户。

(2)用户使用这个公钥,将登录密码加密后,发送回来。

(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

    这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。

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

SSH协议是如何应对的呢?

如果你是第一次通过ssh登录远程主机,会出现下面的提示:

# 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.

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

    出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 警告”无法建立ssh连接。如果远程系统重装过系统, ssh指纹已经改变,你需要把 .ssh 目录下的 know_hosts 文件中相应远程主机IP一致的指纹删除,再通过ssh登录一次回答 yes,重新认证一次方可登录。注意 .ssh 目录是以 "." 开头的隐藏目录,需要 # ls -a 参数才能看到。

而且这个目录的权限必须是700,并且用户的home目录也不能给其他用户写权限,否则ssh服务器会拒绝登陆。如果发生不能登陆的问题,请察看服务器上的日志文件/var/log/secure。通常能很快找到不能登陆的原因。

    每个SSH用户都有自己的 known_hosts 文件,此外系统也有一个这样的文件,通常是 /etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。


四、公钥登录

    使用密码登录,每次都必须输入密码,感觉太浪费时间,而且非常麻烦。尤其是密码超级复杂,维护的服务器又比较多的情况下。好在SSH还提供了公钥(public key)登录,可以省去输入密码的步骤。

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

    基于密钥的安全验证必须为用户自己创建一对密钥,并把共有的密钥放在需要访问的服务器上。当需要连接到SSH服务器上时,客户端软件就会向服务器发出请求,请求使用客户端的密钥进行安全验证。服务器收到请求之后,先在该用户的根目录下寻找共有密钥,然后把它和发送过来的公有密钥进行比较。如果两个密钥一致,服务器就用公有的密钥加密“质询”,并把它发送给客户端软件(putty,xshell等)。客户端收到质询之后,就可以用本地的私人密钥解密再把它发送给服务器,这种方式是相当安全的。

    因为puttygen生成的密钥有问题可能会出现:“Server refused our key”,最好使用XShell生成密钥或者在远程Linux VPS/服务器生成密钥。

1、在Linux下通过 ssh-keygen生成密钥

    这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:

第一步:生成密钥文件

1、在本地生成一对密钥文件(公钥和私钥)
# ssh-keygen
# 以上命令等价于 ssh-keygen -t rsa
# -t:指定密钥的类型,默认为SSH-2 的rsa类型;

[root@localhost ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase):          # 如果设置密码,通过密钥连接也需要输入密码
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
35:dd:d8:49:05:be:e9:7e:89:b7:86:e2:96:17:a0:2b root@localhost.localdomain
The key‘s randomart image is:
+--[ RSA 2048]----+
|              oo.|
|           . * . |
|          o o =  |
|         . o   o |
|        S . . o   |
|         .   o   |
|          . . = . |
|       E . + = +.   |
|        . o.o +o.    |
+-----------------+

    运行上面的命令以后,系统会出现一系列提示,可以一路回车。特别说明,其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个,但是设置之后,利用私钥连接也需要输入密码。

    运行结束以后,在 $HOME/.ssh/ 目录下,会新生成两个文件:id_rsa.pub 和 id_rsa。前者是你的公钥,后者是你的私钥。再一次强调用户自己的目录(~/.ssh)必须不能有其他人可写的权限, .ssh 目录的权限必须是 700chmod 700 ~/.ssh 必须。否则ssh服务器会拒绝登录。

    sshd服务器端默认的公钥文件是用户home目录下的.ssh目录下的 authorized_keys 文件,因此需要把产生的公钥以这个文件名放到服务器的 $HOME/.ssh/ 目录下,这个文件中可以存放多个客户端的公钥文件,就好比一个大门上可以上很多锁,可以有不同的钥匙来尝试开锁,只要有一个锁被打开了,门就可以打开了。~/.ssh/authorized_keys 必须是600权限,否则ssh服务器会拒绝用户登陆。chmod 600 ~/.ssh/authorized_keys

第二步:把生成的密钥文件上传到远程主机

这时再输入下面的命令,将生成的公钥传送到远程主机host上面对应用户home目录下的 .ssh 目录下:

2、将公钥上传到欲远程连接的主机上面
# ssh-copy-id user@host

    好了,经过以上两步之后,从此你再登录,就不需要输入密码了。此命令执行后,远程主机直接将用户的公钥保存在 ~/.ssh/authorized_keys 文件中。


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

技术分享

然后重新启动远程主机的sshd服务:

## RHEL / CentOS
# service sshd restart

## ubuntu
# /etc/init.d/ssh restart


2、通过 SecureCRT生成密钥

1、Tools - Create Public Key

技术分享

2、Select Key type:   RSA

技术分享

3、对私钥设置口令, 也可以不设置

技术分享

4、设置密钥长度

技术分享

5、关键,一定要选择 "OpenSSH Key format" , 为什么呢? 等一下再说,这和多种实现 key 格式不一致有关。

    这里选择生成的密钥使用 OpenSSH Key 格式。如果选择默认的格式,上传到服务器的时候需要执行格式转换的工作,需要通过命令行来连接的也需要通过securecrt来转换私钥为openssh格式,这里建议采用openssh key格式!点击完成后会生成两个文件,默认是IdentityIdentity.pub,其中Identity为私钥,Identity.pub为公钥。

技术分享

6、上传 公钥 到远程服务器

    通过 sftp, 或者 ftp(ASCII模式)把刚才创建生成的公钥(Identity.pub) 上传到远程服务器, $HOME/.ssh 目录下。如果此用户home目录没有 .ssh 目录,则手动创建。

## 如果没有 .ssh 目录执行 mkdir .ssh 进行创建

# mkdir .ssh
# chmod 700 .ssh
# cd .ssh
# mv Identity.pub authorized_keys
# chmod 600 authorized_keys

# 如果密钥的格式不是OpenSSH的,需要进行转换
# ssh-keygen –i –f <公钥文件>  >> ./.ssh/authorized_keys  //转换为公钥为openssh能识别的公钥格式,转换后的文件名为authorized_keys,这是ssh的公钥文件) 

# ssh-keygen -i -f Identity.pub >> authorized_keys

7、编辑 sshd_config 配置文件

# vi /etc/sshd_config

Protocol 2 
ServerKeyBits 2048 
PermitRootLogin no  #禁止root登录而已,与本文无关,加上安全些 
 
#以下三行没什么要改的,把默认的#注释去掉就行了 
RSAAuthentication yes 
PubkeyAuthentication yes 
AuthorizedKeysFile    .ssh/authorized_keys 
 
PasswordAuthentication no   #初次试验的时候最好用yes,否则配置错误的话重启sshd后你就悲剧了 
PermitEmptyPasswords no 

# 在确定你的公钥加入到authorzed_keys后重启sshd服务
# /etc/init.d/sshd restart

8、通过SecureCRT 登录

    首先设置登录模式为PublicKey,并选择刚刚创建的公钥文件 Identity.pub

右键要连接的服务器—会话属性, 在authentication选项中只勾选PublicKey或者将PublicKey选项提到首选,再选中它点击Properties。

技术分享

指定我们刚创建的私钥。

技术分享

OK,Over...


通过 Xshell 生成密钥

    Xshell是一款Windows下面功能强大的SSH客户端,能够按分类保存N多会话、支持Tab、支持多密钥管理等等,管理比较多的VPS/服务器使用XShell算是比较方便的,而且对于 home/school 是free的,推荐使用。

1、Tools

技术分享

技术分享

技术分享

技术分享

技术分享


二、将密钥添加到远程Linux服务器

1、用winscp,将id_rsa.pub文件上传到/root/.ssh/下面(如果没有则创建此目录),并重命名为:authorized_keys(如果是在Linux服务器上生成的密钥直接执行:mv /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys),再执行:chmod 600 /root/.ssh/authorized_keys 修改权限。

2、修改/etc/ssh/sshd_config 文件,将RSAAuthentication 和 PubkeyAuthentication 后面的值都改成yes ,保存。

3、重启sshd服务,Debian/Ubuntu执行/etc/init.d/ssh restart ;CentOS执行:/etc/init.d/sshd restart


五、增强 ssh 安全性 

##SSH服务器监听的选项  
#修改监听的端口,可以增加入侵者探测系统是否运行了 sshd守护进程的难度。  
Port 42333   
#使用SSH V2协议  
Protocol 2  
#监听的地址为所有地址  
#ListenAdderss 0.0.0.0  
ListenAdderss 192.168.5.0/24
#禁止DNS反向解析  
UseDNS no  
# 密钥长度
ServerKeyBits 2048
  
##用户登录控制选项  
#是否允许root用户登录,如果允许用户使用root用户登录,那么黑客们可以针对root用户尝试暴力破解密码,给系统安全带来风险。  
PermitRootLogin no  
#是否允许空密码用户登录,允许使用空密码系统就像不设防的堡垒,任何安全措施都是一句空话。 
PermitEmptyPasswords no  
#登录验证时间(2分钟)  
LoginGraceTime 2m  
#最大重试次数  
MaxAuthTries 6  
#只允许user用户登录,与DenyUsers选项相反  
AllowUsers user1 user2  
# 禁止指定的 用户或组
DenyUsers apache

#注:Allow 和 Deny 可以组合使用,它们的处理顺序是:DenyUsers, AllowUsers, DenyGroups, AllowGroups

##登录验证方式  
#关闭密码验证  
PasswordAuthentication no  

#以下三行没什么要改的,把默认的#注释去掉就行了
RSAAuthentication yes
#启用秘钥验证  
PubkeyAuthentication yes  
#指定公钥数据库文件  
AuthorsizedKeysFile .ssh/authorized_keys

另外,限制登录设置主要是对hosts.allow与hosts.deny就行改动

  首先限制所有IP都无法连接,我们顺便将FTP的限制也加入其中。注意要想FTP限制起作用,需要修改配置中的tcp_wrappers=YES。

  vi /etc/hosts.deny

  sshd:ALL
  vsftpd:ALL

  设定允许指定的IP地址连接:

  vi /etc/hosts.allow # xxx.xxx.xxx.表示网段
  sshd:192.168.1.
  vsftpd:192.168.1.



本文出自 “Share your knowledge” 博客,请务必保留此出处http://skypegnu1.blog.51cto.com/8991766/1641064

ssh 原理和基本使用

标签:linux   ssh   安全   openssh   密钥   

原文地址:http://skypegnu1.blog.51cto.com/8991766/1641064

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!