1. 关于ssh
SSH 是 Secure Shell 的缩写,SSH 为建立在应用层基础上的安全协议。SSH 是目前广泛采用的安全登录协议,专为远程登录会话和其他网络服务提供安全性的协议,替代以前不安全的Telnet协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
scp、sftp等都是基于ssh协议来进行远程传输的。
2. 对称加密和非对称加密
-
对称加密:例如AES,加密和解密使用同一个密钥,不安全,如果密钥丢失,加密的信息就会被窃取,并且可以篡改信息,重新加密;对于接收方来说,并不知道这串加密的信息是受信任的发来的还是黑客伪造的。
-
非对称加密:例如RSA,加密和解密使用不同的密钥,存在一对密钥对,公钥和私钥,公钥可以发送给别人,私钥需要自己保存。常用的公钥加密,私钥解密,例如:小明要发送消息给小红,小红把自己的公钥给小明,小明利用小红的公钥加密发送给小红,小红再使用自己的私钥进行解密。即使小红的公钥被窃取,黑客没有小红的私钥也解密不了信息。
3. ssh免密登录原理
服务器A要免密登录服务器B,则要把服务器A的公钥存到服务器B的授权公钥文件中;先在服务器A上生成一对秘钥(ssh-keygen),然后将公钥拷贝到服务器B的authorized_keys文件中。
原理:
- 服务器A向服务器B发送一个连接请求,信息包括服务器A此时登录的用户名、服务器A的ip以及要免密登录的服务器B的用户名;
- 服务器B收到请求,会从服务器A要免密登录服务器B的用户名家目录下 authorized_keys 中查找是否有相同的服务器A用户名、服务器Aip;
- 如果有,服务器B会随机生成一个字符串,然后使用服务器A的公钥进行加密,再发送给服务器A;
- 服务器A接到服务器B发来的信息后,会使用私钥进行解密,然后将解密后的字符串发送给服务器B;
- 服务器B接到服务器A发来的信息后,会和之前生成的字符串进行比对,如果一致,则允许免密登录。
4. ssh免密登录配置
在进行配置之前需要先关闭防火墙,并且最好给服务器设置主机名,并配置 /etc/hosts 文件映射。
systemctl status firewalld.service # 查看防火墙状态
systemctl stop firewalld.service # 关闭防火墙
systemctl disable firewalld.service # 移除防火墙开机自启动
步骤:
- 假设A服务器需要免密登录B服务器,那么在A服务器执行命令:
ssh-keygen -t rsa
(默认就是RSA加密算法,可不用加-t rsa);密钥对生成过程会提示输入私钥加密密码,可以直接回车不使用密码保护。命令执行完成后会在~/.ssh目录下生成两个文件:id_rsa(私钥)和id_rsa.pub(公钥) - 将公钥文件id_rsa.pub中的内容拷贝到B服务器的~/.ssh目录下的授权公钥文件authorized_keys中
5. ssh免密登录注意事项
首先,假设A服务器要免密登录B服务器,我们将A服务器通过ssh-keygen
命令生成的公钥写进B服务器authorized_keys文件中。涉及以下注意事项:
A服务器生成的公钥如下:root@sangfor-node7
代表这是root用户生成的公钥
如果我们将其拷贝到B服务器/root/.ssh/authorized_keys
文件中,那么A服务器就能以B服务器的root账号免密登录成功,也就是:ssh root@B服务器
可以免密登录成功;但是如果是以B服务器的其它账号进行登录,则无法免密,例如:ssh admin@B服务器
需要输入admin账号的密码才可以登录。
如果我们希望A服务器也能以B服务器的admin账号免密登录成功,那么还需要将A服务器的公钥拷贝到B服务器:/home/admin/.ssh/authorized_keys
文件中(即admin用户的家目录下)。
另外,A服务器生成的公钥文件中包含 root@sangfor-node7
代表这是root用户生成的公钥;如果A服务器是以root账号去执行命令:ssh root@B服务器
可以免密登录成功;但是如果A服务器是以其它账号,例如wyf,去执行命令:ssh root@B服务器
则需要输入密码;因为B服务器/root/.ssh/authorized_keys
文件中存储的是A服务器root用户的公钥,如果我们希望A服务器以wyf账号登录去执行命令:ssh root@B服务器
也可以免密登录成功;那么需要在A服务器切换成wyf账号,执行 ssh-keygen
,那么生成的公钥文件位于 /home/wyf/.ssh/
目录下,并且包含 wyf@sangfor-node7
,代表这是wyf用户的公钥。再把这个公钥写入B服务器authorized_keys文件中即可。
如下:
最后,还需要注意域名问题,由于A服务器配置了主机名为 sangfor-node7
,因此生成的公钥文件包含主机名,如:root@sangfor-node7
,但是B服务器并不知道这个主机名代表哪个ip地址,因此需要在B服务器的 /etc/hosts
文件中配置 sangfor-node7
主机名和ip的映射。
6. github配置本机ssh公钥步骤及原理
如果我们要把本地代码以ssh方式push到github上,为避免每次push都需要输入github账号和密码,则需要配置本机免密登录github,免密登录原理和A服务器免密登录B服务器一样。
配置步骤参考文档:https://blog.csdn.net/wenfu814/article/details/120625844
7. known_hosts文件
A通过ssh首次连接到B,B会将公钥1(host key)传递给A,A将公钥1存入known_hosts文件中,以后A再连接B时,B依然会传递给A一个公钥2,OpenSSH会核对公钥,通过对比公钥1与公钥2 是否相同来进行简单的验证,如果公钥不同,OpenSSH会发出警告,并且需要用户交互式的输入yes/no, 避免受到DNS Hijack之类的攻击;如果公钥相同,则不会发出警告。
例如:
A服务器首次ssh登录B服务器,由于A服务器的known_hosts文件中没有B服务器的公钥,因此控制台会发出警告,并且需要用户输入yes/no
当我们输入yes之后,A服务器的known_hosts文件会增加一条记录(B服务器的公钥);再输入B服务器的密码,ssh登录成功
当A服务器再次ssh登录B服务器,B依然会传递给A一个公钥,OpenSSH会核对公钥,将该公钥和A服务器known_hosts文件保存的B服务器的公钥进行对比,由于相同,则不会发出警告,直接让用户输入密码
如果我们不希望在进行ssh登录时进行公钥检查,可以加上 "StrictHostKeyChecking no"
跳过公钥检查,就不需要用户手动输入yes/no(这在一些自动化场景经常使用到)
备注:如果A通过ssh登陆B时提示 Host key verification failed.
;原因是A的known_hosts文件中记录的B的公钥1与连接时B传过来的公钥2不匹配。
解决方法:删除A的known_hosts文件中记录的B的公钥,当再次ssh登录B时,重新写入B服务器最新的公钥即可。