一、SSH简介
SSH (Secure Shell Protocol 安全外壳协议)是建立在应用层基础上的安全协议,是目前较可靠、专为远程登录会话和其他网络服务提供安全性的协议。
二、SSH组成部分
2.1SSH的三个组件ssh、sftp、scp介绍
ssh:
1)ssh 远程登录用法 : ssh 用户名@IP地址
2)不允许空密码或错误密码认证登录
3)不允许root用户登录,也可以设置让root用户登录
4)有两个版本 ssh,ssh2。ssh2由于加上了连接检测机制,可以避免连接期间被人插入恶意代码,安全性更高
sftp:
sftp 文件共享连接 , xftp连接就是 sftp实现的
scp:
与sftp一样也可以实现文件拷贝共享
2.2 SSH的三个组件ssh、sftp、scp用法
1)SSH直接登录远程主机指令:
在SSH客户端使用ssh这个指令可以连接到远程主机。
ssh语法:
ssh [-f] [-o 参数项目] [-p 非标准端口] [账号@]IP [命令]
选项与参数:
-f :需要配合后面的 [命令] ,不登录远程主机直接发送一个指令过去而已;
-o 参数项目:主要的参数项目有:
ConnectTimeout=秒数 :联机等待的秒数,减少等待的时间
StrictHostKeyChecking=[yes|no|ask]:预设是 ask,若要让 public key主动加入 known_hosts ,则可以设定为 no 即可。
-p :如果你的 sshd 服务启动在非标准的端口 (22),需使用此项目;
[命令] :不登入远程主机,直接发送命令过去。但与 -f 意义不太相同
例如:直接联机登入到对方主机的方法 (以登入本机为例):
ssh 127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
RSA key fingerprint is eb:12:07:84:b9:3b:3f:e4:ad:ba:f1:85:41:fc:18:3b.
Are you sure you want to continue connecting (yes/no)? yes #输入yes后将远程服务器的主机的公匙指纹码写入客户端本地~/.ssh/known_hosts
Warning: Permanently added '127.0.0.1' (RSA) to the list of known hosts.
root@127.0.0.1's password: <==在这里输入 root 的密码即可!
Last login: Mon Jul 25 11:36:06 2011 from 192.168.1.101
# exit <==离开这次的 ssh 联机
# 由于 ssh 后面没有加上账号,因此预设使用当前的账号来登入远程服务器
例如: 登入对方主机执行过命令后立刻离开的方式:
ssh student@127.0.0.1 find / &> ~/find1.log
student@localhost's password:
此时你会发现怎么画面卡住了?这是因为上头的命令会造成,你已经登入远程主机,但是执行的命令尚未跑完,因此你会在等待当中
例如: 登入对方主机执行过命令让远程主机自己执行不影响客户端本机的方法
ssh -f student@127.0.0.1 find / &> ~/find1.log
例如:使用root连接到本机并且不用输入yes,自动加上公匙的方法
rm ~/.ssh/known_hosts
#删除本地远程主机公匙记录,模拟第一次连接
ssh -o StrictHostKeyChecking=no root@localhost
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
root@localhost's password:
#如上所示,不会问你 yes 或 no 啦!直接会写入 ~/.ssh/known_hosts 当中!
2)模拟 FTP 的文件传输方式: sftp
如果你只是想要从远程服务器下载或上传文件呢? 那就不是使用 ssh ,而必须要使用 sftp 或 scp。这两个指令也都是使用 ssh 的通道 (port 22),只是模拟成 FTP 与复制的动作而已。我们先谈谈 sftp ,这个命令的用法与 ssh 很相似,只是 ssh 是用在登录,而 sftp 在上传/下载文件而已。
语法:
sftp student@localhost
Connecting to localhost...
student@localhost's password: <== 这里请输入密码!
sftp> exit <== 这里就是在等待你输入 ftp 相关指令的地方了!
sftp 这个接口下可使用的指令;
针对远程服务器主机 (Server) 的行为 :
功能 | 命令 |
---|---|
切换目录到 /etc/test 或其他目录 | cd /etc/test,cd PATH |
列出目前所在目录下的文件名 | ls ,dir |
建立目录 | mkdir directory |
删除目录 | rmdir directory |
显示当前所在目录 | pwd |
更改文件或目录属组 | chgrp groupname PATH |
更改文件或目录属主 | chown username PATH |
更改文件或者目录权限 | chmod 644 PATH |
建立连接文件 | ln oldname newname |
删除文件或目录 | rm PATH |
更改文件或目录 | rename oldname newname |
离开远程主机 | exit ,bye ,quit |
针对本机(client)的行为(都加上l)
功能 | 命令 |
---|---|
切换目录到本机的 PATH 当中 | lcd PATH |
列出目前本机所在目录下的文件名 | lls |
在本机建立目录 | lmkdir |
显示当前所在本机目录 | lpwd |
针对资料上传下载的操作
功能 | 命令 |
---|---|
将文件由本机上传到远程主机 | put [本机目录或文件] [远程] , put [本机目录或文件],如果后一种格式,则文件会存储到当前远程主机的目录下 |
将文件由远程主机下载回来 | get [远程主机目录或文件] [本机] , get [远程主机目录或文件] , 若是后一种格式,则文件会存储在目前本机所在的目录当中。可以使用通配符,例如:get * ,get *.rpm |
3)文件异地直接复制: scp
通常使用 sftp 是因为可能不知道服务器上面已经存在的文件名信息,如果已经知道服务器上的文件名, 那么最简单的文件传输则是通过 scp 这个指令。最简单的 scp 用法如下:
语法:
scp [-pr] [-l 速率] file [账号@]主机:目录名 <==上传
scp [-pr] [-l 速率] [账号@]主机:file 目录名 <==下载
是传还是下载的重点是那个冒号 :。
选项与参数:
-p :保留文件原有的权限信息;
-r :复制来源为目录时,可以复制整个目录 (含子目录)
-l :可以限制传输的速度,单位为 Kbits/s ,例如 [-l 800] 代表传输速限 100Kbytes/s
例如:. 将本机的 /etc/hosts* 全部复制到 127.0.0.1 上面的 student 家目录内
scp /etc/hosts* student@127.0.0.1:~
三、SSH工作原理
-
3.1远程加密技术简介
如何实现数据的安全呢?首先想到的实现方案肯定是对数据进行加密。加密的方式主要有两种:
1) 对称加密(也称为秘钥加密)
2)非对称加密(也称公钥加密)
对称加密的加密强度高,很难破解。但是在实际应用过程中不得不面临一个棘手的问题:如何安全的保存密钥呢?尤其是考虑到数量庞大的Client端,很难保证密钥不被泄露。这时就出现了非对称加密技术。ssh协议使用的就是更加安全的非对称加密技术。 -
3.2 SSH加密原理
ssh加密主要是通过两把不一样的公钥与私钥 (Public and Private Key) 来进行加密与解密的过程。由于这两把钥匙是提供加解密的功用, 所以在同一个方向的联机中,这两把钥匙当然是需要成对的!它的功用分别如下:
1)公钥 (public key):提供给远程主机进行数据加密的行为,也就是说,大家都能取得你的公钥来将数据加密的意思;
2)私钥 (private key):远程主机使用你的公钥加密的数据,在本地端就能够使用私钥来进行解密。
ssh非对称加密方案登录具体流程如图所示:
1)远程Server收到Client端用户TopGun的登录请求,Server把自己的公钥发给用户。
2)Client使用这个公钥,将密码进行加密。
3)Client将加密的密码发送给Server端。
4)远程Server用自己的私钥,解密登录密码,然后验证其合法性。
5)若验证结果,给Client相应的响应。
说明:
私钥是Server端独有,这就保证了Client的登录信息即使在网络传输过程中被窃据,也没有私钥进行解密,保证了数据的安全性,这充分利用了非对称加密的特性。
server端是如何产生自己的公私钥
服务端每一次启动 sshd 服务时,该服务会主动去找 /etc/ssh/ssh_host*文件,若系统刚刚安装完成时,由于没有这些公钥文件,因此 sshd 会主动去计算出这些需要的公钥文件。
产生公私钥:rm /etc/ssh/ssh_host* <==删除密文件 /etc/init.d/sshd restart 正在停止 sshd: [ 确定 ] 正在产生 SSH1 RSA 主机密钥: [ 确定 ] <==底下三个步骤重新产生密钥! 正在产生 SSH2 RSA 主机密钥: [ 确定 ] 正在产生 SSH2 DSA 主机密钥: [ 确定 ] 正在激活 sshd: [ 确定 ] ll /etc/ssh/ssh_host* -rw-------. 1 root root 668 Jul 25 11:35 /etc/ssh/ssh_host_dsa_key -rw-r--r--. 1 root root 590 Jul 25 11:35 /etc/ssh/ssh_host_dsa_key.pub -rw-------. 1 root root 963 Jul 25 11:35 /etc/ssh/ssh_host_key -rw-r--r--. 1 root root 627 Jul 25 11:35 /etc/ssh/ssh_host_key.pub -rw-------. 1 root root 1675 Jul 25 11:35 /etc/ssh/ssh_host_rsa_key -rw-r--r--. 1 root root 382 Jul 25 11:35 /etc/ssh/ssh_host_rsa_key.pub
上面这样就一定安全了吗?还是不够安全。如果一个攻击者中途拦截Client的登录请求,向其发送自己的公钥,Client端用攻击者的公钥进行数据加密。攻击者接收到加密信息后再用自己的私钥进行解密,不就窃取了Client的登录信息了吗?这就是所谓的中间人攻击,Client端保证不了接受到的公钥就是目标Server端的。为了解决这个问题在SSH version2 中加入了连接检查机制。
SSH中是如何解决这个问题的?
1. 基于口令的认证从上面的描述可以看出,问题就在于如何对Server的公钥进行认证?在https中可以通过CA来进行公证,可是SSH的publish key和private key都是自己生成的,没法公证。只能通过Client端自己对公钥进行确认。通常在第一次登录的时候,系统会出现下面提示信息:
The authenticity of host 'ssh-server.example.com (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)?
上面的信息说的是: 无法确认主机 (12.18.429.21)的真实性,不过知道它的公钥指纹,是否继续连接?
如果输入yes后,会出现下面信息:Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts. Password: (enter password)
该host已被确认,并被追加到文件known_hosts中,然后就需要输入密码,之后再进行如上图所示的流程。
对于客户端公钥记录文件:~/.ssh/know_hosts说明
当你登入远程服务器时,本机会主动利用接收到的服务器的 public key 去比对 ~/.ssh/known_hosts 有无相关的公钥, 然后进行底下的动作:
1)若接收的公钥尚未记录,则询问用户是否记录。若要记录 (回答 yes 的那个步骤) 则写入 ~/.ssh/known_hosts 且继续登入的后续工作;若不记录 (回答 no) 则不写入该文件,并且退出登录工作;
2)若接收到的公钥已有记录,则比对记录是否相同,若相同则继续登入动作;若不相同,则出现警告信息, 且离开登录的动作。这是客户端的自我保护功能,避免你的服务器是被别人伪装的。
2.基于公钥认证
在上面介绍的登录流程中可以发现,每次登录都需要输入密码,很麻烦。SSH提供了另外一种可以免去输入密码过程的登录方式:公钥登录。流程如下:
ssh基于公钥免密登录过程:
过程说明:
1)Client将自己的公钥存放在Server上,追加在文件authorized_keys中。
2)Server端接收到Client的连接请求后,会在authorized_keys中匹配到Client的公钥pubKey,并生成随机数R,用Client的公钥对该随机数进行加密得到pubKey®,然后将加密后信息发送给Client。
3)Client端通过私钥进行解密得到随机数R,然后对随机数R和本次会话的SessionKey利用MD5生成摘要Digest1,发送给Server端。
4)Server端会也会对R和SessionKey利用同样摘要算法生成Digest2。
5)Server端会最后比较Digest1和Digest2是否相同,完成认证过程
具体操作流程如下:
1)客户端建立两把钥匙:想一想,在密钥系统中,是公钥比较重要还是私钥比较重要? 当然是私钥比较重要!因此私钥才是解密的关键啊!所以,这两把钥匙当然得在发起连接的客户端建置才对。利用的指令为 ssh-keygen 这个命令;2)客户端放置好私钥文件:将 Private Key 放在 Client 上面的用户家目录,亦即 $HOME/.ssh/ , 并且得要注意权限。
3)将公钥放置到服务器端的正确目录与文件中:最后,将那把 Public Key 放在任何一个你想要用来登录的服务器端的某 User用户的家目录内 .ssh/ 里面的认证文件即可完成整个程序。
客户端建立两把钥匙:
命令: ssh-keygen [-t rsa|dsa] <==可选 rsa 或 dsa,默认是rsa算法
例如:ssh-keygen #默认的算法来建立秘钥 Generating public/private rsa key pair. Enter file in which to save the key (/home/wode/.ssh/id_rsa): <==按 enter Created directory '/home/wode/.ssh'. <==此目录若不存在则会主动建立 Enter passphrase (empty for no passphrase): <==按 Enter 不给密码 Enter same passphrase again: <==再输入一次 Enter 吧! Your identification has been saved in /home/wode/.ssh/id_rsa. <==私钥文件 Your public key has been saved in /home/wode/.ssh/id_rsa.pub. <==公钥文件 查看权限 ls -ld ~/.ssh; ls -l ~/.ssh drwx------. 2 wode wode 4096 2011-07-25 12:58 /home/wode/.ssh -rw-------. 1 wode wode 1675 2011-07-25 12:58 id_rsa <==私钥文件 -rw-r--r--. 1 wode wode 416 2011-07-25 12:58 id_rsa.pub <==公钥文件
权限说明:
注意~/.ssh/目录权限必须是700权限才行,而且那个私匙id_rsa文件的权限必须是 -rw-------且属于wode自己才行。
将客户端产生的公钥文件上传到服务端
我们是以 wode的身份登录wode客户端主机,因此我们就得要将上个步骤建立的公钥 (id_rsa.pub) 上传到服务器上的 wode 用户才行。那如何上传呢?最简单的方法当然就是使用 scpscp ~/.ssh/id_rsa.pub wode@192.168.100.254:~ # 上传到 wode的家目录底下即可。
将公钥放置到服务器端的正确目录与文件名
sshd_config 里面的 AuthorizedKeysFile 这个设定值就是指定公钥数据应该要放置的文件名(.ssh/authorized_keys)
在服务端创建wode这个用户并把公钥写入家目录:useradd wode #添加用户 passwd mkdir /home/wode/.ssh chmod 700 /home/wode/.ssh
将公钥文件的数据用cat转存到authorized_keys内
cat id_rsa.pub >> .ssh/authorized_keys chmod 644 .ssh/authorized_keys ls -l .ssh -rw-r--r--. 1 wode wode 416 Jul 02 13:07 authorized_keys
这样以后你从客户端以wode用户登录到服务端wode这个用户时就不需要任何密码了。
四、 sshd 服务器详细配置说明
sshd 服务器详细设置都放在 /etc/ssh/sshd_config 配置文件里面,只要是未被注释的设置值(设置值前面加“#”号),即为默认值。
vim /etc/ssh/sshd_config # 1. 关于 SSH Server 的整体设定,包含使用的 port 啦,以及使用的密码演算方式 # Port 22 # SSH 预设使用 22 这个port,也可以使用多个port,即重复使用 port 这个设定项目! # 例如想要开放 sshd 在 22 与 443 ,则多加一行内容为:『 Port 443 』 # 然后重新启动 sshd 这样就好了!不过,不建议修改 port number 啦! Protocol 2 # 选择的 SSH 协议版本,可以是 1 也可以是 2 ,CentOS 5.x 预设是仅支援 V2。 # 如果想要支持旧版 V1 ,就得要使用『 Protocol 2,1 』才行。 # ListenAddress 0.0.0.0 # 监听的主机适配器!举个例子来说,如果你有两个 IP,分别是 192.168.1.100 及 # 192.168.100.254,假设你只想要让 192.168.1.100 可以监听 sshd ,那就这样写: # 『 ListenAddress 192.168.1.100 』默认值是监听所有接口的 SSH 要求 # PidFile /var/run/sshd.pid # 可以放置 SSHD 这个 PID 的档案!上述为默认值 # LoginGraceTime 2m # 当使用者连上 SSH server 之后,会出现输入密码的画面,在该画面中, # 在多久时间内没有成功连上 SSH server 就强迫断线!若无单位则默认时间为秒! # Compression delayed # 指定何时开始使用压缩数据模式进行传输。有 yes, no 与登入后才将数据压缩 (delayed) # 2. 说明主机的 Private Key 放置的档案,预设使用下面的档案即可! # HostKey /etc/ssh/ssh_host_key # SSH version 1 使用的私钥 # HostKey /etc/ssh/ssh_host_rsa_key # SSH version 2 使用的 RSA 私钥 # HostKey /etc/ssh/ssh_host_dsa_key # SSH version 2 使用的 DSA 私钥 # 在主机的 SSH 连接流程里面谈到的,这里就是 Host Key ~ # 3. 关于登录文件的讯息数据放置与 daemon 的名称! SyslogFacility AUTHPRIV # 当有人使用 SSH 登入系统的时候,SSH 会记录信息,这个信息要记录在什么 daemon name # 底下?预设是以 AUTH 来设定的,即是 /var/log/secure 里面!什么?忘记了! # 回到 Linux 基础去翻一下。其他可用的 daemon name 为:DAEMON,USER,AUTH, # LOCAL0,LOCAL1,LOCAL2,LOCAL3,LOCAL4,LOCAL5, # LogLevel INFO # 登录记录的等级!嘿嘿!任何讯息!同样的,忘记了就回去参考! # 4. 安全设定项目!极重要! # 4.1 登入设定部分 # PermitRootLogin yes # 是否允许 root 登入!预设是允许的,但是建议设定成 no! # StrictModes yes # 是否让 sshd 去检查用户家目录或相关档案的权限数据, # 这是为了担心使用者将某些重要档案的权限设错,可能会导致一些问题所致。 # 例如使用者的 ~.ssh/ 权限设错时,某些特殊情况下会不许用户登入 # PubkeyAuthentication yes # AuthorizedKeysFile .ssh/authorized_keys # 是否允许用户自行使用成对的密钥系统进行登入行为,仅针对 version 2。 # 至于自制的公钥数据就放置于用户家目录下的 .ssh/authorized_keys 内 PasswordAuthentication yes # 密码验证当然是需要的!所以这里写 yes 啰! # PermitEmptyPasswords no # 若上面那一项如果设定为 yes 的话,这一项就最好设定为 no , # 这个项目在是否允许以空的密码登入!当然不许! # 4.2 认证部分 # RhostsAuthentication no # 本机系统不使用 .rhosts,因为仅使用 .rhosts太不安全了,所以这里一定要设定为 no # IgnoreRhosts yes # 是否取消使用 ~/.ssh/.rhosts 来做为认证!当然是! # RhostsRSAAuthentication no # # 这个选项是专门给 version 1 用的,使用 rhosts 档案在 /etc/hosts.equiv # 配合 RSA 演算方式来进行认证!不要使用啊! # HostbasedAuthentication no # 这个项目与上面的项目类似,不过是给 version 2 使用的! # IgnoreUserKnownHosts no # 是否忽略家目录内的 ~/.ssh/known_hosts 这个档案所记录的主机内容? # 当然不要忽略,所以这里就是 no 啦! ChallengeResponseAuthentication no # 允许任何的密码认证!所以,任何 login.conf 规定的认证方式,均可适用! # 但目前我们比较喜欢使用 PAM 模块帮忙管理认证,因此这个选项可以设定为 no 喔! UsePAM yes # 利用 PAM 管理使用者认证有很多好处,可以记录与管理。 # 所以这里我们建议你使用 UsePAM 且 ChallengeResponseAuthentication 设定为 no #4.3 与 Kerberos 有关的参数设定!因为我们没有 Kerberos 主机,所以底下不用设定! # KerberosAuthentication no # KerberosOrLocalPasswd yes # KerberosTicketCleanup yes # KerberosTgtPassing n # 4.4 底下是有关在 X-Window 底下使用的相关设定! X11Forwarding yes # X11DisplayOffset 10 # X11UseLocalhost yes # 比较重要的是 X11Forwarding 项目,他可以让窗口的数据透过 ssh 信道来传送喔! # 在本章后面比较进阶的 ssh 使用方法中会谈到。 # 4.5 登入后的项目: # PrintMotd yes # 登入后是否显示出一些信息呢?例如上次登入的时间、地点等等,预设是 yes # 亦即是打印出 /etc/motd 这个档案的内容。但是,如果为了安全,可以考虑改为 no ! # PrintLastLog yes # 显示上次登入的信息!可以啊!预设也是 yes ! # TCPKeepAlive yes # 当达成联机后,服务器会一直传送 TCP 封包给客户端藉以判断对方式否一直存在联机。 # 不过,如果联机时中间的路由器暂时停止服务几秒钟,也会让联机中断喔! # 在这个情况下,任何一端死掉后,SSH可以立刻知道!而不会有僵尸程序的发生! # 但如果你的网络或路由器常常不稳定,那么可以设定为 no UsePrivilegeSeparation yes # 是否权限较低的程序来提供用户操作。我们知道 sshd 启动在 port 22 , # 因此启动的程序是属于 root 的身份。那么当 student 登入后,这个设定值 # 会让 sshd 产生一个属于 sutdent 的 sshd 程序来使用,对系统较安全 MaxStartups 10 # 同时允许几个尚未登入的联机画面?当我们连上 SSH ,但是尚未输入密码时, # 这个时候就是我们所谓的联机画面啦!在这个联机画面中,为了保护主机, # 所以需要设定最大值,预设最多十个联机画面,而已经建立联机的不计算在这十个当中 # 4.6 关于用户抵挡的设定项目: DenyUsers * # 设定受抵挡的使用者名称,如果是全部的使用者,那就是全部挡吧! # 若是部分使用者,可以将该账号填入!例如下列! DenyUsers test DenyGroups test # 与 DenyUsers 相同!仅抵挡几个群组而已! # 5. 关于 SFTP 服务与其他的设定项目! Subsystem sftp /usr/lib/ssh/sftp-server # UseDNS yes # 一般来说,为了要判断客户端来源是正常合法的,因此会使用 DNS 去反查客户端的主机名 # 不过如果是在内网互连,这项目设定为 no 会让联机达成速度比较快。