SSH相信大家都不陌生,常用的远程登录有两种方式:
- 口令登录(每次登录输入用户名密码)
- 公钥登录
第一种方式登录只需要知道账号密码,相对第二种方式要更方便,然而第一种方式相对不那么安全。具体原因我们从它们的原理入手。
口令登录
口令登录命令
$ ssh <user>@<host>
原理如下:
- 客户端向服务端发起请求
- 服务收到请求将自己生成的公钥返回给客户端
- 客户端用返回来的公钥加密自己的登录密码,发送给服务端
- 服务端用自己的私钥解密,并验证密码是否正确,如果正确,允许登录
整个验证机制是没什么问题的,但是当遇到 中间人攻击
这种机制的安全性便会遭到破坏,什么是 中间人攻击
- 客户端向服务端发起请求
- 攻击人截获请求,并向客户端返回自己的公钥
- 客户端用公钥加密登录密码并返回
- 攻击人用自己的私钥解密,获得服务器的登录密码
中间人攻击使你每次登录都带有潜在风险,中间人在和你同一个网络环境,比如公共wifi环境,就能轻易截获和伪装成服务器窃取你的密码。那么有什么应对方式呢?
$ ssh <user>@<host>
The authenticity of host 'hostname (<ip>)' can't be established.
RSA key fingerprint is 97:8c:1c:f2:6f:15:6b:5c:3a:ec:aa:48:46:79:7c:20.
Are you sure you want to continue connecting (yes/no)?
当首次登录一台远程主机的时候,会出现以上提示,大致意思是无法确认远程主机是否真实,这是主机的公钥指纹97:8c:1c:f2:6f:15:6b:5c:3a:ec:aa:48:46:79:7c:20
,询问是否继续,如果接受这个风险,便可继续连接并会保存这个公钥到know_hosts
文件中,如果下次再连接,会自动对比公钥。如果下次连接公钥变化了,会发出一下告警并拒绝连接
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED
通过以上机制,我们只需要确保第一次登录时候,远程的登录的主机是真实的,除非远程主机重装了,或手动修改了,通常情况公钥不会修改。唔...那么问题又来了,我们怎么知道真实远程主机的公钥指纹是什么?目前来说没什么好办法,只能依靠远程主机提供商把公钥指纹贴出来。
公钥登录
公钥登录命令
$ ssh -i PrivateKey.pem <user>@<host>
原理如下:
- 客户端自己生成密钥对,事先将公钥上传存储到远程服务器上,私钥自己保管
- 客户端发起登录请求
- 服务器发一串随机字符串给客户端
- 客户端用自己的私钥加密随机字符串,返回给服务端
- 服务端用事先存储好的公钥解密,确认字符串是原来发出的字符串,便允许登录
公钥登录的前提是事先将自己生成的公钥存储到远程的服务器,通常有两种方式
- 如果你的远程服务器是云提供商上的,一般都会提供密钥对管理的功能,有些甚至可以自动创建密钥对,并提供私钥的下载(比如AWS),没有的话也没关系,通过以下命令生成密钥对,并将
公钥(id_rsa.pub)
上传到云上即可。$ ssh-keygen -t rsa -b 4096 #一路回车即可,密钥默认保存在 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub
- 如果远程服务器提供商没有密钥对管理的功能,那只能手动操作上传了
- 生成密钥对并上传公钥
以下操作需要能够密码登录远程主机
$ ssh-keygen -t rsa -b 4096 #在~/.ssh/目录下生成两个文件,其中id_rsa是私钥,id_rsa.pub是公钥,分别保存以备用 $ ssh-copy-id <user>@<host> #需要输入登录密码,成功后可以在服务器 ~/.ssh/authorized_keys文件中看到添加的公钥
- 确保客户端和服务器上的 .ssh 的权限是700,authorized_keys的权限是600
$ chmod 700 ~/.ssh $ chmod 600 ~/.ssh/authorized_keys
- 确保服务器上
/etc/ssh/sshd_config
中以下是没有注释的RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys
- (可选)把密码登录关闭,在服务器上
/etc/ssh/sshd_config
设置PasswordAuthentication no
- 重启服务器上的sshd
$ systemctl restart sshd