加密与认证,服务器通信安全(Procedure)

前言
在建立CCTV服务的时候经常要将一些文件传输到另外一个服务器上,而且都是Linux的命令行环境,那么对于我来讲scp就是最直接有效的方法了,其他诸如FTP、SMB以及Winscp这些有界面的文件传输工具到反而有些多余了。使用过scp的都知道需要指定远端服务器的帐号并手动输入密码,那么如何避免每次都需要输入密码这个操作呢?下面就给出两种方案进行解决。

  • 方法一(最好的办法):建立SSH的信任关系
    • 在A上的Linux上使用ssh-keygen工具来生成公私钥对id_rsaid_rsa.pub
MBP:.ssh qxxxxxzeng$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/qxxxxxzeng/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/qxxxxxzeng/.ssh/id_rsa.
Your public key has been saved in /Users/qxxxxxzeng/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:qJmWKqbhGQSpyrQtntfMLK5ExiixuJczILIly1T6RWU qxxxxxzeng@MBP
The key's randomart image is:
+---[RSA 3072]----+
|       E         |
| .    o          |
|+  . .           |
|*oo .  .         |
|@O.  .. S        |
|&B+..=           |
|*B=o@            |
|=+=B =           |
|+B=..            |
+----[SHA256]-----+
MBP:.ssh qxxxxxzeng$ 
  • id_rsa.pub发给B,B将id_rsa.pub放入B用户名下的信任秘钥Authentication_keys内
      1. scp ~/.ssh/id_rsa.pub B@ip:~/.ssh
      2. cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
      3. 赋权和修改用户755(群晖需要将用户777变成755来实现免密码登录)
      4. 修改sshd_config,启动RSA Authentication
      5. 重启B的ssh服务
    • 从此,在A上利用scp加密传输的内容就自动由B的Authentication Keys给与登录认证的信息,而无需再次输入密码。
#赋权:(注意~/.ssh一定要是700,也就是只用作者“可读可写可执行”,否则还会被判定不安全
chmod 755 ~
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
#修改 sshd_config,启动RSA Authentication,将#去掉就是enable,具体如下
sudo vim /etc/ssh/sshd_config
#RSAAuthentication yes
#PubkeyAuthentication yes
#AuthorizedKeysFile .ssh/authorized_keys
  • 预备,两个知识点
    • 公钥和私钥
      • 公钥
        • SSH公钥(~/.ssh/id_rsa.pub), 在~/.ssh/id_rsa.pub文件中包含了认证的公钥信息,而且该文件可以被任何人读取;
        • 公钥授权文件(~/.ssh/authorized_keys),在~/.ssh/authorized_keys文件中则列举了登录用户的公钥信息(换句话说就是使用这些公钥信息可以登录当前设备),而为了安全考虑,该文件一般建议只有本用户可以有读写权限。
        • 这两个文件的作用具体可以参考ssh的man手册:
      • 私钥,
        • 提到公钥对应的就会有私钥,在谈这两个概念之前我们先了解另外一组概念:
    • 加密和认证:
      • 加密,是对数据进行处理,添加保护信息,如果非法用户得到被加密过的数据,也无法获取到原始的有效数据内容,所以加密的重点在于数据的安全性。
      • 认证,是对数据进行处理,添加鉴权信息,如果在传输的过程中被非法篡改,接收方就会校验失败并丢弃该非法数据,所以认证的重点在于数据的合法性。登录就是一种认证,我等下要用秘钥登录就是认证的应用。
      • 上面是从业务概念来上描述了加密和认证的区别,但是从具体技术实现上,认证使用的是加密中的非对称加密算法来实现鉴权和认证的操作。非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥分别是
        • 公开密钥(public key,简称公钥)
        • 私有密钥(private key,简称私钥)

 ~/.ssh/id_rsa.pub
         Contains the public key for authentication.  These files are not sensitive and can (but need not) be readable by anyone.

~/.ssh/authorized_keys
         Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as this user.  The format of this file is described in the sshd(8) manual page.  This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others.

对称加密算法在加密和解密时使用的是同一个秘钥;

下面就分别描述一下,采用非对称算法(即使用公钥和私钥)的加密和认证各自的过程。

ssh-keygen : authentication key generation, management and conversion
 -t    type
     Specifies the type    of key to create.  The possible    values are ‘rsa1’ for protocol version 1 and ‘dsa’, ‘ecdsa’, ‘ed25519’, or ‘rsa’ for protocol version 2.

  • 基于公钥和私钥的加密过程
    • 有两个用户Alice和Bob,Alice想把一段数据加密后发送给Bob以及Bob公司所有人(注意这里强调的是数据的安全性),那么如何保证除了Bob之外的人即使窃取了数据也无法解密得到原始的数据?基于公钥和私钥的加密可以完成这个需求,具体流程如下:
      • Bob将他的公钥发送给Alice
      • Alice用Bob的公钥加密需要传输的数据然后发送给Bob和其他所有人
        只有Bob用他的私钥解密Alice的消息,其他人没有私钥,解密不了。
  • 基于公钥和私钥的认证过程
    • 还是Alice和Bob,Alice想把一段数据发送给Bob(注意这里并不强调数据的安全性),当Bob收到数据时如何判断该数据确实是Alic发送的且传输过程中没有被篡改?基于公钥和私钥的认证可以完成这个需求,具体流程如下:
      • Alice用她的私钥对数据加密(或者对于数据的哈希值进行加密作为签名)
      • Alice将加密后的数据(或者明文数据+签名)发送给Bob
      • Bob 执行 cat id_rsa.pub >> authorized_keys
      • Bob用Alice的公钥解密数据(或校验签名),如果解密(校验)成功则可以保证数据的发送方肯定是Alice
  • 基于公钥和私钥的信任关系
    • 了解了公钥/私钥以及加密/认证这些概念后,我们就可以在scp中使用公钥/私钥来建立一个信任关系,从而在数据传输时完成自动认证而无需输入密码
    • 如何认证:
      • 如何加密:User在A主机上需要创建一个公私钥对,公钥scp给B,私钥给A。在B主机上,将User在A主机的公钥加入到ssh的信任公钥列表authorized_keys中(即公钥授权文件~/.ssh/authorized_keys)
      • User在A主机将SCP请求使用自己的私钥进行加密,然后传输给B主机
      • B主机在收到SCP请求时,使用User的公钥进行解密
      • 如果解密成功,则表示该请求确实是User发送的请求,则允许操作;如果解密失败,则表示该请求无效,直接丢弃
    • 所以这里的需要做的就是:
      • 创建公私钥对
        • 在A上的Linux上使用ssh-keygen工具来生成公私钥对,在man手册中关于ssh-keygen工具的说明如下:


我自己的样式:(注意,cctv就是上文的A,而存储服务器就是B)

pi@raspberrypi:~ $ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/pi/.ssh/id_rsa): 
Created directory '/home/pi/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/pi/.ssh/id_rsa.
Your public key has been saved in /home/pi/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:rmcdf8g3xs1131WujDZIsDTkwLnltMoWrO3Gxg3nP1Q pi@raspberrypi
The key's randomart image is:
+---[RSA 2048]----+
|     ..o=       .|
|o     o+ +. .  ..|
|..  .  .o+..... o|
|     + o.++o.+ oo|
|      = So+o+ o o|
|  oo   *..E. .   |
|        *O.      |
|       + =B      |
| ..o  .  +o.     |
+----[SHA256]-----+
pi@raspberrypi:~ $ 
pi@raspberrypi:~/.ssh $ scp /home/pi/.ssh/id_rsa.pub pi@192.168.1.106:/home/pi/.ssh/authorized_keys 
The authenticity of host '192.168.1.106 (192.168.1.106)' can't be established. ECDSA key fingerprint is SHA256:lMiyrBGB1xz40/x4syemMcbIA0kS5eMAGFp1zrz9Moo. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.106' (ECDSA) to the list of known hosts. pi@192.168.1.106's password:  id_rsa.pub                                                        100%  396    48.1KB/s   00:00
pi@raspberrypi:~ $ ssh pi@192.168.1.106 
Linux raspberrypi3 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l The programs included with the Debian GNU/Linux system are free software; 
the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. 
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. 
Last login: Sun Feb  2 12:09:14 2020 from 192.168.1.117 pi@raspberrypi3:~ $ exit 
logout Connection to 192.168.1.106 closed. 
pi@raspberrypi:~ $ 

在上面提到了ssh-keygen支持rsa1、dsa、ecdsa、ed25519和rsa这几种非对称加密算法,其中最常用的就是RSA和DSA.
注意上面有三处需要输入信息,分别是:
存储公私钥的文件夹位置,如果不输入,则默认为~/.ssh/,文件名则默认是id_rsa和id_rsa.pub
使用该公私钥时是否需要密码,如果不输入则表示不需要密码(我的建议是:能不输入就不输入
再次确认是否需要密码
将User在A主机的公钥加入到ssh的信任公钥列表中
将刚才创建的~/.ssh/id_rsa.pub文件中的内容拷贝添加到B主机上的~/.ssh/authorized_keys文件中(如果没有则创建一个),这个时候就建立了一条A–>B的信任关系。注意这个信任关系是有方向性的,如果要建立从B–>A的信任关系,则操作步骤和上面的类似,只不过要反过来。

建立好信任关系后,这个时候使用任何ssh相关的工具则都无需输入远端的登陆密码(如果在创建公私钥对时输入了密码,那么这个时候还需要输入这个密码才能使用公私钥对)。

方法二:使用sshpass工具来自动输入密码
其实上面的建立信任关系的做法是最方便和安全的做法,但是在有些场景下(比如远端的authorized_keys是不能随意更改的),那么这个时候我们就可以借助sshpass这个第三方工具来完成ssh连接时的密码输入。先看一下sshpass的man手册中是如何描述的:(省略)

方法三:使用expect脚本来自动输入密码

注:关于expect部分详细请参考《shell结合expect写的批量scp脚本工具》(省略)

总结
在本文中提供了三种方法来实现scp的时候无需输入密码的需求,从安全性和速度上考虑建立信任关系都是最佳的方法,至于在具体的环境中选择什么则由你自己来决定。
————————————————
版权声明:本文为CSDN博主「nfer_cn」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nfer_zhuang/article/details/42646849