ssh 免密登陆 中间人攻击 网络安全
1. SSH 应对中间人攻击的方法#
SSH 采用了公钥加密, 过程如下:
(1)Remote Host 收到用户的登录请求, 把自己的公钥发给用户
(2)用户使用这个公钥, 将登录密码加密后, 发送过去
(3)Remote Host 用自己的私钥, 解密信息, 验证密码是否正确
这个过程存在一个漏洞:如果有人截获了用户的登录请求,然后冒充 Remote Host,将伪造的公钥发给用户,那么用户很难辨别真伪。这就是 Man-in-the-middle attack, 应对方法有两种:
- 利用公钥指纹人工进行对比验证,
- 上传公钥实现免密登录
接下来我们一一介绍这两种方法,
2. 利用公钥指纹人工进行对比验证#
看来面的例子, 在Mac上通过ssh连接远程的服务器, 第一次连接的时候会问下面提示:
这是 ssh 在提醒它无法确认 remost host 是不是就是你要连接的那个主机, 因为可能会发生中间人攻击嘛, 但知道它的公钥指纹是sa5vDYS0...
, 问我们还要继续连接吗 (注意单词 establish 在这是 “认证确认” 的意思),
那我们怎么知道远程主机的公钥指纹应该是多少?当然是去你的服务器上查看公钥指纹:
注意如果你的服务器使用的是其他hash function生成的公钥指纹, 那你就要查看其他文件了:
可以发现输出内容与上面 ssh 警告的指纹相同, 所以我们要来接的这个是我们的真正主机,
可能有人会说, 那我们买的服务器物理主机在谷歌阿里, 怎么去直接验证? 你可以在你购买VPS的网站上连接自己服务器保证你连接的一定是你的主机, 但我们只是测试, 所以你直接忽略 ssh 的提示警告, 输入yes, 连上服务器后去验证一下就好了, 因为肯定不会有中间人闲的蛋疼来攻击我们的连接吧? 几块钱一个月的服务器, 谁来攻击你,
有人可能又会疑问, 那我们也可以直接去远程主机查看他的公钥啊, 为啥还要用个hash函数来生成它的指纹, 再去比对, 不是多此一举吗? 首先你没发现公钥的指纹很短吗? 我们去远程主机验证一般是用肉眼来比对吧, 那公钥那么长, 几百个字符, 很容易比对错, 而公钥指纹的主要目的就在于它很短, 方便我们比对,
最后关于 ssh 输出的信息, 还有其它想说的, 根据输出:
该 remote host 上的 ssh 使用的公私钥是由 ED25519 算法生成的, ED25519 是非对称加密算法, 常见的非对称加密算法还有 RSA, 所以 RSA 和 ED25519 是并列的: Today, the RSA is the most widely used public-key algorithm for SSH key. But compared to Ed25519, it’s slower and even considered not safe if it’s generated with the key smaller than 2048-bit length. EdDSA is a digital signature scheme, Ed25519 is the EdDSA signature scheme using SHA-512 (SHA-2) and Curve25519. –Wiki
另外, 该公钥指纹是由 SHA256 hash function 生成的, 另外常见的 hash function 还有md5,
2.1. 验证公私钥位置#
这个时候我们在电脑终端输入yes, 然后就会提示输入密码 (比如root用户对应的密码), 然后系统会提示如下:
当远程主机的公钥被接受以后, 它会被保存在文件~/.ssh/known_hosts
之中, 下次再连接这台主机, 系统就会认出它的公钥已经保存在本地了, 从而跳过警告部分, 直接提示输入密码, 我们来查看Mac上的输出:
再看看服务器上的输出,
这两个一个是公钥, 一个是公钥的指纹, 可以看出和上面Mac的存储的内容是一样, 然后上面在服务器 ls /etc/ssh
的输出, 有 ssh_host_rsa_key.pub
, ssh_host_ecdsa_key.pub
这就是使用不同的算法产生的不同的key,
最后 Mac 上 ~/.ssh/known_hosts
的输出 github 那部分有 ssh-ed25519, ecdsa-sha2-nistp256, 这是什么呢?
For
ssh-ed25519
andecdsa-sha2-nistp256
which one is used for a given connection depends on the capabilities and preferences of the client, namely your ssh program. If you are usingOpenSSH
versions 6.5 to 8.1, then it prefersecdsa
thened25519
, and only 8.2 up prefersed25519
first. Why does GitHub recommend ed25519 SSH key encryption scheme, but itself uses ECDSA? - Super User
- ecdsa-sha2-nistp256: Specifies the ECDSA algorithm with 256-bit key strength
- rsa: Specifies the public key algorithm rsa
3. Public Key Authentication (上传公钥实现免密登陆)#
3.1. 过程分析#
使用密码登录, 每次都必须输入密码, 非常麻烦, 好在SSH还提供了公钥登录, 可以省去输入密码的步骤, 具体验证过程如下:
- The client generates a public/private key pair, typically with RSA or ECC. The client keeps the private key secret and registers the public key with the SSH server.
- When the client connects to the server, the server authenticates the client by checking if it has the corresponding public key registered for that client.
- The server will send a challenge message to the client, requesting authentication.
- The client will take the challenge message and use its private key to generate a digital signature. This proves that the client has the correct private key without revealing the key itself.
- The client sends the digital signature back to the server as a response to the challenge.
- The server verifies the signature using the client’s registered public key. If the signature is validated, the server knows the client has proven possession of the corresponding private key and grants it access.
注意关于验证过程, 不同 ssh 版本可能会有不同的实现, 你可能会看到有人说远程主机用 用户的公钥进行解密验证, 其实公钥并不可以用来解密, 别人指的应该是公钥可以用来验证数字签名, 即这种情况下私钥加密其实应该是私钥签名。 私钥 “加密” 以后,谁用公钥都可以打开,就已经失去了加密的意义,所以它只能起到一个“签名”的效果,来达到-大家知道这条信息是我,而且只有我发出的。
记住公钥只能用来加密, 不可以用来解密, 不然就不叫公钥了, 所以是远程主机用 用户的公钥进行用户的验证数字签名, 总结公钥有俩功能:
- 加密
- 验证数字签名
3.2. 具体操作#
远程主机需要使用用户的公钥来验证用户的身份, 所以本地机器要生成公私钥:
一路回车之后在~/.ssh/
会新生成两个文件:id_rsa.pub
和id_rsa
, 前者是你的公钥, 后者是你的私钥, 这时再输入下面的命令, 将公钥传送到远程主机host上面:
完成, 之后再登录就不需要输入密码了:
其实你也可以直接编辑远程主机
~/.ssh/authorized_keys
文件, 把你本地主机的公钥的内容添加进去就行了,ssh-copy-id root@144.202.16.29
做的就是这件事. 下面我们会验证.
4. authorized_keys
file#
上面 ssh-copy-id root@144.202.16.29
执行后, 本机公钥存储在了远程主机~/.ssh/authorized_keys
:
在Mac上查看我自己的公钥, 是一样的:
5. ssh_config
vs sshd_config
file#
I would like to change my SSH port running Linux CentOS 6. I also noticed there’s an /etc/ssh_config
file along with /etc/sshd_config
. What’s the difference between the two? Should I change both?
The sshd_config
is the ssh daemon (or ssh server process) configuration file. As you’ve already stated, this is the file you’ll need to modify to change the server port.
Whereas, the ssh_config
file is the ssh client configuration file. The client configuration file only has bearing on when you use the ssh
command to connect to another ssh host. So, in this case, you don’t need to modify it. It will be other client machines connecting to your server.
Source: Should I modify only sshd_config, or also ssh_config?
References:
- https://en.wikipedia.org/wiki/EdDSA
- https://en.wikipedia.org/wiki/Digital_signature
- https://superuser.com/a/1688126
- https://security.stackexchange.com/questions/230708/should-i-be-using-ecdsa-keys-instead-of-rsa
- Man-in-the-middle attack
- How to check your SSH key fingerprint (verify the authenticity of the remote host)