本章涵盖了你可能应该知道的SSH主体的杂集,但这些主题不值得单独讨论。
我们将讨论OpenSSH中的主机密钥轮换,连接到只支持过时密码和转义字符的主机。
在主机接受来自公共互联网的连接一两年后,你应该考虑轮换主机密钥。随着计算能力的提高,算法不仅变得更容易破解,而且潜在的入侵者有更多的时间暴力破解你的私钥。不过,如果你要求用户每年左右验证新的主机密钥,他们会很恼火。你可以使用现有的主机密钥将新的主机密钥安全地传输到客户端。如果现有的主机密钥已被泄露,这没有用,但它可以让你在丢弃旧密钥之前主动将即将到来的主机密钥分发给客户端。
一旦你有了更多服务器,OpenSSH证书比偶尔的密钥轮换更有用。证书完全消除了known_hosts和更新客户端的需要。
在服务器和客户端上配置SSH密钥轮换。
受限创建下一组密钥。创建你打算支持的每种密钥。当然,它们需要不同的文件名。我将新密钥命名为创建年份的前缀。
# ssh-keygen -f 2018_ssh_host_rsa_key -t rsa -N ''
# ssh-keygen -f 2018_ssh_host_ecdsa_key -t ecdsa -N ''
# ssh-keygen -f 2018_ssh_host_ed25519_key -t ed25519 -N ''
这给了我们四个新的密钥。限制使用sshd_config中的HostKey关键字添加这些密钥。在现有主机密钥之后添加这些新密钥:
xxxxxxxxxx
HostKey /etc/ssh/2018_ssh_host_rsa_key
HostKey /etc/ssh/2018_ssh_host_dsa_key
HostKey /etc/ssh/2018_ssh_host_ecdsa_key
HostKey /etc/ssh/2018_ssh_host_ed25519_key
你的服务器现在已准备好将这些主机密钥分发给客户端。
一旦你确定所有客户端都有新主机密钥的副本,并且你已经放弃等待哪个从不更新所有内容的用户,你就可以禁用旧主机的密钥。
告诉ssh使用ssh_config文件中的UpdateHostKeys选项查找其他密钥。默认情况下,告诉ssh忽略新的主机密钥。将其设置为yes会自动使用此主机的任何新密钥更新known_hosts。ask设置意味着询问用户是否应该接受新密钥。这反映了StrictHostKeyChecking关键字。
xxxxxxxxxx
$ ssh avarice
The authenticity of host 'avarice.mwl.io (203.0.113.209)' can't be established.
ECDSA key fingerprint is SHA256:JUf1lzyEVYxhbJCfXLvPi6eLJdYCZhEBzJD8c+NGLzw.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
验证主机的公钥指纹,如果正确则接受。但随后你会收到另一组警告。
xxxxxxxxxx
Learned new hostkey: RSA SHA256:nNUnWCojrzeHAALXyM/yGpGM7uUIPrP/ph8zV3qUx9M
Learned new hostkey: ED25519 SHA256:nNtyIQidY3MXAEfpWZ0wzkXKQFnCoQhe0CRIldc4…
Accept updated hostkeys? (yes/no): yes
你的客户端已获取此主机的RSA和ED25519密钥的公钥。你只能集体接受或拒绝这些额外的公钥。这是一种非常罕见的攻击者,它会在破坏其他密钥的同时保持主主机密钥不变,但你真的应该验证所有密钥。
当服务器添加新的主机密钥时,客户端会显示指纹,并给你一个验证它们的机会:
xxxxxxxxxx
$ ssh avarice
Learned new hostkey: RSA SHA256:aDqGAPMnT6b3aYqT3DXjRofYfHznOMbVFWZg3yw/fTI
Learned new hostkey: ECDSA SHA256:9eHjmXAFrGmRT2iz/WY5pHLcvoo0HQ5paiLcpEcXWns
Learned new hostkey: ED25519 SHA256:BZ5X6sIbfa5AWcQY0RjnMRL9zLX1+som5TmTV/k/…
Accept updated hostkeys? (yes/no):
主机密钥更新与连接多路复用(ControlPersist)关键字不兼容。启用ControlPersist将禁用主机密钥更新。
虽然PuTTY可以获取它不用于连接的算法的公钥(转到左上角菜单,选择特殊命令->缓存新主机密钥类型),但它不能接受同一类型的多个密钥。当您删除旧的主机密钥时,您的PuTTY用户必须重新验证主机密钥。
在过去的几年里,OpenSSH已经弃用了一大堆协议和加密算法。明显不安全的SSH版本1已经从源代码中删除。但是,在1990's年代行之有效的加密算法已经不再适合今天的互联网。OpenSSH仍然支持这些类型的加密,但默认情况下未启用。你必须使用特殊的命令行选项才能使用它们。
为什么要禁用这些算法?意识。你应该知道SSH连接何时使用弱加密。如果你从未意识到服务器或嵌入式设备只支持糟糕的加密算法,你就永远不会升级或更换它。
当OpenSSH由于加密功能较弱而无法连接到SSH服务器时,它会"告诉"你需要手动连接的所有信息。不过,你必须了解SSH的加密特性。
SSH协议在四个不同的角色中使用密码学。每个角色都需要不同的算法。OpenSSH使用关键字在ssh_config或命令行中设置每个参数。
密钥交换方法(Key Exchange Method——KEX)用于生成每个连接的一次性对称密钥。关键字KeyAlgorithms设置密钥交换方法。
使用Ciphers关键字设置通用加密算法。
消息认证码(Message Authentication Codes——MAC)检测流量中的更改。MACs关键字设置它们。
HostKeyAlgorithems允许你设置主机密钥的算法。
最后,一些公钥算法被淘汰了。PubkeyAcceptedKeyTypes关键字允许你启用过时的密钥类型。
我的家庭娱乐网络通过一个廉价的嵌入式路由器连接到互联网。它在某种程度上提供SSH。
xxxxxxxxxx
$ ssh admin@203.0.113.1
Unable to negotiate with 203.0.113.1 port 22: no matching host key type found. Their offer: ssh-dss
路由器不提供当前OpenSSH默认接受的主机密钥类型。HostKeyAlgorithms关键字允许你重新启用支持但不再启用的主机密钥算法。ssh-dss算法(也称为DSA)非常弱,在现代ssh中被抛弃了,但由于这是我的家庭网络,我在这里信任它。使用HostKeyAlgorithms关键字将其添加回ssh支持的选项中。
xxxxxxxxxx
$ ssh -o HostKeyAlgorithms=+ssh-dss admin@203.0.113.1
Fssh_ssh_dispatch_run_fatal: Connection to 203.0.113.1 port 22: DH GEX group out of range
又一个错误,当连接到只支持过时加密的SSH服务器时,你可能需要在命令行上设置一些关键字。确定哪些是必要的设置是一个迭代过程。
这个错误有点模糊。与主机密钥算法错误不同,这里没有明显的关键字可供选择。如果你不熟悉Diffie-Hellman密钥交换,最好的方法是使用互联网搜索引擎查看是否有人以前犯过同样的错误。如果你是世界上第一个遇到这个问题的人,请在详细模式下运行ssh,收集输出,并联系供应商。
这个特殊的错误被证明是一个密钥交换问题,这个供应商对此很熟悉。我必须重新激活一个过时的密钥交换算法。
xxxxxxxxxx
$ ssh -o HostKeyAlgorithms=+ssh-dss -o KexAlgorithms=diffie-hellman-group14-sha1 admin@203.0.113.1
我现在可以连接了。
总有一天,OpenSSH会完全弃用这些算法。在此之前升级你的设备。不过,作为临时修复,你可以在ssh_config中设置这些选项。
xxxxxxxxxx
Host 203.0.113.1
HostKeyAlgorithms +ssh-dss
KexAlgorithms +diffie-hellman-group14-sha1
不过,既然我已经写了这一节,我就可以升级我的路由器了。
当你通过SSH连接到服务器时,你的击键都会传递到服务器。不过,使用转义字符,你可以与本地运行的SSH进程进行通信。转义字符暂时并短暂地暂停你的SSH会话。你可以使用转义字符中断挂起的SSH会话,添加端口转发,向网络设备发送老式的串行式中断等等。
默认转义符式波浪号(~)。很少有Unix命令使用波浪号,但你可以点击两次发送一次。点击~~表示”是的,我真的想发送一个波浪号“。如果你需要更改转义符,请使用ssh的-e参数和引号中的所需转义符。
按回车键、转义符和第二个字符发出指令。断开连接是~.,编辑端口转发是~C,以此类推。
转义字符最简单的用法是终止SSH会话。如果远程服务器挂起,请输入波浪号句点:
xxxxxxxxxx
wrath# ~.
Connection to server wrath.mwl.io closed
client$
你现在回到本地了。
(好像FreeBSD14.1无效)
转义字符可以让你在时间上倒退,调整你用来连接到主机的命令。虽然你不能摆弄密钥算法等,但你可以调整端口转发。输入~C进入命令行,然后输入所需的端口转发。
假设我正在进行SSH会话,并且我想添加一个从桌面上的9999端口转发到服务器的动态端口。如果我用这个打开SSH会话,我会在命令行中添加标记-D 9999。我首先键入~C,然后得到一个ssh>提示符。
xxxxxxxxxx
ssh>
这是内部ssh(1)命令提示符。在此处添加您的命令行更改。
xxxxxxxxxx
ssh> -D9999
Forwarding port.
回到我的客户端,我会看到ssh(1)的端口9999是打开的。动态转发是实时的。
要取消端口转发,请返回SSH命令行。使用-K标志和用于创建端口转发的命令。在这里,我禁用了刚刚创建的动态转发。
xxxxxxxxxx
ssh> -KD9999
Canceled forwarding.
动态前进消失了。
转义符还有其他功能,但它们中的大多数在今天都没有用。不过,如果你很好奇,~?显示所有可用转义字符的列表。
你可以用SSH做更多的事情。如果你能做到这一切,那么你比几乎所有人都更有能力使用SSH。祝贺 你!