由于个人服务器集群须要回收日志到中央进行统一处理,因此须要创建ssh
互信关系实现免密登陆。关于ssh的使用你们可能都很熟悉了,咱们今天主要来说下ssh
链接和免密登陆的原理。php
scp
传输文件
scp(secure copy)
是linux
系统下基于ssh
登陆进行安全的远程文件拷贝的命令。html
# 传递文件到远程 scp local_file remote_username@remote_ip:remote_file # 传递文件夹到远程 scp -r local_folder remote_username@remote_ip:remote_folder # 复制远程文件到本地,只是调换下文件参数位置便可 scp remote_username@remote_ip:remote_file local_file
远程拷贝的命令还有rsync
,scp
消耗资源少,不会提升多少系统负荷,在这一点上,rsync
就远远不及它了。rsync
比scp
会快一点,但当小文件多的状况下,rsync
会致使硬盘I/O
很是高,而scp
基本不影响系统正常使用。
与scp
类似的命令是cp
,可是cp
只能本机拷贝而不能跨服务器,所以须要与ssh
合做构成scp
命令。linux
咱们直接使用scp
来跨机器拷贝文件,会提示输入密码:git
# 提示输入server端服务器的work用户密码 [work@client.com ~]$ scp test.php work@server.com:/home/work work@server.com's password:
缘由就在于,scp
是先使用ssh
链接服务端机器后,再使用网络来执行远程拷贝(cp)
。算法
能够参考ssh
的过程:shell
# 一样的提示输入server端服务器的work用户密码 [work@client.com ~]$ ssh work@server.com work@server.com's password:
ssh
加密信息
Secure Shell
(安全外壳协议,简称SSH
)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH
经过在网络中建立安全隧道来实现SSH
客户端与服务器之间的链接。虽然任何网络服务均可以经过SSH
实现安全传输,SSH
最多见的用途是远程登陆系统,人们一般利用SSH
来传输命令行界面和远程执行命令。
SSH
是Telnet/rlogin
等非安全shell
的替代品,这些协议采用明文传输,会引入许多的安全性问题:
如图所示,telnet
使用23
号端口,全部的信息,包括用户名和密码都是明文传输;而ssh
使用22
号端口,全部的信息都会被加密传输,安全性获得了很大的提升。vim
ssh
使用十分简单,选择以什么用户链接哪台机器,而后输入密码便可:segmentfault
$ssh user@hostname user@hostname's password:
对称加密和非对称加密
ssh
的主要有点就是安全性,安全性依赖于加密方式,如今主要的加密方式有两种:对称加密和非对称加密。安全
对称加密
对称加密使用同一个密钥来进行加密和解密,这样在传输时是安全可靠的,可是如何安全的保存密钥呢,在集群中,客户端的数量巨大,一旦任意一个客户端的密钥被窃取,那么整个系统的安全性也不复存在。ruby
非对称加密
因为对称加密的这个弊端,产生了非对称加密,非对称加密中有两个密钥:公钥和私钥。公钥由私钥产生,但却没法推算出私钥;公钥加密后的密文,只能经过对应的私钥来解密。
非对称加密的登陆流程:
初始状态:topgun
终端要登陆Server
服务器,发起链接请求ssh work@server.com
- 服务端运行有
ssh
服务,并持续监听22
号端口,所以能够生成一对公钥和私钥;此时将公钥返回给客户端 - 客户端使用公钥,对登陆密码进行加密,(如服务器
work
用户密码为xxx
),生成公钥加密字符串 - 客户端将公钥加密字符串发送给服务端
- 服务端使用私钥,解密公钥加密字符串,获得原始密码
- 校验密码是否合法(此为本机
work
密码) - 返回登陆结果给客户端:成功登陆或密码错误
在非对称加密中,因为只有公钥会被传输,而私钥是服务端本地保存,所以即使公钥被监听,也没法拿到原始密码,从而登陆服务器。
中间人攻击
在非对称加密中能够有效保护登陆密码不被泄漏,但这是在创建链接到真实服务器的状况下。设想一下,若是供给者并不监听密码或公钥,而是直接假装成服务器呢:
在该示例图中,存在Hacker
服务器劫持了你的ssh
建连请求(如经过DNS
劫持等方式),致使你与Hacker
机器的链接一切正常,所以它能拿到你的明文密码,并经过明文密码来攻击真实的服务端。
那么SSH
采用了非对称的加密方式,是怎么解决这个问题的呢?
[work@client.com: ~]$ ssh work@server.com The authenticity of host 'server.com (10.10.10.24)' can't be established. RSA key fingerprint is ad:2e:92:41:6f:31:b1:c1:35:43:eb:df:f1:18:a1:c1. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'server.com,10.10.10.24' (RSA) to the list of known hosts. Password: (enter password)
在这个认证信息中,能够看到提示:没法确认主机server.com (10.10.10.24)
的真实性,不过知道它的公钥指纹,是否继续链接?
输入yes
继续链接后,就会确认该服务器为可信任服务器,而后添加到known_hosts
文件中,下次不用再次确认,而后跳转到输入密码的验证阶段。这种简单粗暴的方式至关于让咱们肉眼比对来判断目标服务器是不是真实服务器,我以为并非最理想的方式,但愿后续会有更完美的认证方式。
之因此用fingerprint
(公钥指纹)代替key
,主要是key
过于长(RSA
算法生成的公钥有1024
位),很难直接比较。因此,对公钥进行hash
生成一个128
位的指纹,这样就方便比较了。
SSH
免密登陆
咱们已经掌握如何使用ssh
登陆远程服务器了,可是每次登陆都要输入密码,比较麻烦。ssh
提供一种免密登陆的方式:公钥登陆。
- 在客户端使用
ssh-keygen
生成一对密钥:公钥+私钥 - 将客户端公钥追加到服务端的
authorized_key
文件中,完成公钥认证操做 - 认证完成后,客户端向服务端发起登陆请求,并传递公钥到服务端
- 服务端检索
authorized_key
文件,确认该公钥是否存在 - 若是存在该公钥,则生成随机数
R
,并用公钥来进行加密,生成公钥加密字符串pubKey(R)
- 将公钥加密字符串传递给客户端
- 客户端使用私钥解密公钥加密字符串,获得
R
- 服务端和客户端通讯时会产生一个会话
ID(sessionKey)
,用MD5
对R和SessionKey
进行加密,生成摘要(即MD5
加密字符串) - 客户端将生成的
MD5
加密字符串传给服务端 - 服务端一样生成
MD5(R,SessionKey)
加密字符串 - 若是客户端传来的加密字符串等于服务端自身生成的加密字符串,则认证成功
- 此时不用输入密码,即完成建连,能够开始远程执行
shell
命令了
实现免密登陆
ssh-genkey
是生成密钥的工具,执行完成后生成公钥和密钥,这两个文件会默认保存在~/.ssh/
路径下。经常使用的参数为:
-t:
指定生成密钥类型(rsa、dsa)
。默认为rsa
-f:
指定存放私钥的文件,公钥文件名为私钥文件名加.pub
后缀。默认为id_rsa
-P:
指定passphrase
(私钥的密码),用于确保私钥的安全。默认为空-C:
备注。默认为user@hostname
咱们直接执行来生成密钥,全部的参数均可觉得空,也就是一直回车确认:
$ ssh-keygen
Generating public/private rsa key pair. Enter file in which to save the key (/home/work/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in id_rsa. Your public key has been saved in id_rsa.pub. The key fingerprint is: 74:17:74:38:b2:c7:70:fd:1d:33:eb:e2:71:71:cc:11 work@client.com
此时,生成的文件在~/.ssh/
目录下,咱们会看到这些文件:
id_rsa // 私钥文件 id_rsa.pub // 公钥文件 authorized_keys // 存放客户端公钥的文件 known_hosts // 确认过公钥指纹的可信服务器列表的文件 config // 指定不一样域名使用哪一个密钥的配置文件
由于一台机器即能是客户端,又能是服务端,所以同时存在authorized_keys
(在该机器为服务端时使用)和Known_hosts
(在该机器为客户端时使用)。
咱们的服务器会有不少的用户,若是全部的用户都用同一份密钥,可能就没办法划分权限或者区分用户,如多个用户提交git
就须要按照用户名来生成密钥,用于区分用户。同时你可能也但愿针对不一样的服务器使用不一样的密钥对,所以须要config
配置文件来配置针对不一样服务器的配置:
$vim ~/.ssh/config Host a.baidu.com User work IdentityFile ~/.ssh/id_rsa Host b.baidu.com User zhaoshuaiqiang IdentityFile ~/.ssh/zhaoshuaiqiang
这样在链接不一样的服务器时,就会使用不一样的密钥文件来登陆。
在客户端生成密钥对以后,将公钥追加到服务器的authorized_keys
文件中便可。
...
15 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAn30bjwtkLW82vTlLMQnI/a42J2g7o+HBCpSzBgNG+xfZuSNQOAU8+FNKQvriT4AL7ToiTtrZDLOEGqyQzaxQejuNnWG6aQ9ETh96qXhVLecWidaBieFGuv+F uXz6x551xtFXx64AzG+706dhnv1nOACYlrnfvXhi5kZzWzprET+CxMIeYhJQwwc19pF5zCWeU9QUvd1mOu0n8JVycevmuXRdVx9WpXq2+aaaaaaaa3uYGMBxvSLtT40O1AiEZ+k9EeYCnTEV tnGoVWCyxpwv6rR/GDOtJL/d+/Wb6I0HEKxxe087yZz8GWpQN5TEIAjq3oEjI/aiGw== work@a.baidu.com 16 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzRmK+CAVLnryXqQwweu8Yji8bGAvqzf8PSDzYn1nmE6ZeDkBbrWvFlVZ2yOip3IX8RjvuPc28mTCr0LsIOOmpvET0SzOkt0hzLBPiyCN/QvbKU/RbUv8v5y2 hEAlbUkMEzv7qOHQEruGEvA5y99gf/nYjK5OFKVpmg838OScUV3i88Xbqk8rtcuRZHWuZLnuB5spBsEE5r1UrnH/Ik7frZr8Vb4X6aZWbAp1yc0SqZ8JXVbmOiakqq0WqkLm+zqhEwr+Ooh2guH23x9zjMqY Uy+aaaaaBEBC+LepCvskArBt/SRwJDJkcItz8T7kBC3CP0Y0X4hB+6k6/yM/pup5w== work@b.baidu.com
此时,便可免密登陆服务器。
私钥的安全性
假设你已经实现了服务器集群的免密登陆,那么若是你的一台客户端被攻击成功了,那么整个集群的安全性便荡然无存了。所以,咱们有时还须要对密钥作安全性保障,即设置私钥密码:
// 使用rsa方法加密,生成test密钥对,私钥密码为123456 ssh-keygen -t rsa -f test -P 123456
此时,各机器仍然是免密登陆,可是须要你输入私钥密码:
$ssh work@a.baidu.com
Enter passphrase for key '/home/work/.ssh/test':
参考资料
- RUNOOB-Linux scp命令:http://www.runoob.com/linux/l...
- linux-doc scp跨机远程拷贝:https://linuxtools-rst.readth...
- 维基百科 Secure Shell:https://zh.wikipedia.org/wiki...
- 简书 图解SSH原理:https://www.jianshu.com/p/334...
- CSDN scp在linux中实现两台主机传件--互信无需输入密码: https://blog.csdn.net/posonri...