SSH客户端软件驻留在用户的工作站上,并允许连接到SSH服务器。
本书讨论两个常见的客户端:用于类Unix主机的OpenSSH命令行客户端ssh和用于MS Windows的PuTTY客户端。
这两个客户端都可以以源代码或二进制形式自由使用和重新分发,限制和约束非常小。
OpenSSH客户端ssh与OpenSSH服务器同步开发。由于新功能通常在OpenSSH中先于其他SSH实现出现,因此使用最新的OpenSSH客户端可以获得SSH功能的最前沿。
OpenSSH客户端是作为OpenBSD的一部分开发的,但每六个月就会出现一个新的可移植版本。
用户的个人SSH设置记录为$HOME/.ssh/中的文件。与主目录一样,此目录必须只能由用户和root写入,尽管你可以允许它具有全球可读性。
如果其他人可以写入此目录,则各种客户端和服务器的功能将停止工作。当ssh创建具有正确权限的$HOME/.ssh时,如果你的ssh套件行为异常,请检查权限。
ssh的运行方式是,输入命令,然后输入要连接的主机:
xxxxxxxxxx
$ ssh gluttony.mwl.io
这将使用客户端的默认设置连接到主机gluttony.mwl.io,包括你当前的用户名。
如果ssh的行为不符合预期,可尝试使用-v在详细模式下运行它。你将看到:服务器和客户端协商协议版本和加密算法,服务器提供其主机密钥,客户端验证该密钥,以及两种协商身份验证方法。虽然这可能无法解决你的问题,但它会告诉你登录失败的位置,并提示你在哪里查找。仔细阅读输出可能会告诉你,例如,服务器只允许使用公钥登录,或者你在试图使用不受支持的加密方法。
xxxxxxxxxx
$ ssh -v gluttony.mwl.io
如果仍然有问题,多个-v选项可以提高调试级别。
在正常情况下,就是这样。本书的其余部分是关于异常情况的。
通过在命令行或配置文件中设置选项来配置ssh。使用配置文件进行永久更改,使用命令行进行临时更改。我们先看看配置文件。
两个文件控制ssh行为:/etc/ssh/ssh_config和$HOME/.ssh/config。
这两个文件都包含关键字和值,如第二章所述。
前者为所有系统用户建立默认行为。后者是用户的个人SSH客户端配置。用户的配置会覆盖所有全局设置,但大多数用户不会费心输入自己的自定义配置。
配置文件更改会影响更改后启动的所有SSH会话。没有重启的过程,但更改配置不会影响现有的SSH会话。这两个文件具有相同的语法,并接受完全相同的选项。为了简洁起见,我们将参考ssh_config,但所有内容都同样适用于$HOME/.ssh/config。
虽然大多数连接选项都可以在命令行上设置,但我们建议将悠久信息存储在ssh_config中。scp和sftp等程序读取ssh_config,每个程序的命令行选项略有不同。使用配置文件可以集中配置。
用户的个人配置会覆盖全局配置。在命令行上设置的选项会覆盖这两个选项。
使用Host关键字可以更改ssh连接到某些主机的方式。使用Port关键字可以更改ssh连接到的TCP端口,但仅适用于mwl.io域中的主机。它将端口22用于所有其他主机,如/etc/services中指定的。
xxxxxxxxxx
Host *.mwl.io
Port 2222
也可以指定一个IP地址或IP地址网络:
xxxxxxxxxx
Host 192.0.2.*
Port 2224
注意,ssh根据用户在命令行上输入的内容匹配这些ssh_config条目。Host条目必须与用户键入的内容完全匹配,区分大小写。假设我的ssh_config包含上述两个Host条目,让我们看看这在实践中是如何工作的:
xxxxxxxxxx
$ ssh gluttony.mwl.io
这条命令匹配第一个Host条目,所以ssh连接到端口2222。
我的桌面的/etc/resolv.conf会自动将域mwl.io附加到任何单独的主机名上,所以我可能不会键入完全限定的域名(FQDN)。相反,我会输入以下命令:
xxxxxxxxxx
$ ssh gluttony
以上命令与第一条Host条目不匹配,因为没有明确键入ssh_config中给出的域名。但是,如果主机的IP地址在192.0.2.0/24中,那么第二个Host条目会匹配吗?不会,因为Host条目在命令行上匹配;没有针对DNS的检查。
为了根据Host条目中的IP地址匹配,我需要显式运行ssh 192.0.2.whatever。
此主机的自定义设置需要以下Host条目:
xxxxxxxxxx
Host gluttony
Port 2222
在第一次匹配的基础上解析条件。主机条目后列出的配置选项将一直有效,直到下一个主机条目。这个ssh_config可能是错误的:
xxxxxxxxxx
Host *.mwl.io
Host 192.0.2.*
Port 2222
用户可能希望Port关键字应用于mwl.io中的所有主机和192.0.2.0/24中的所有IP地址。
我们在mwl.io域中为任何主机都有一个条目,但没有进行特殊配置。
192.0.2.0/24中的任何主机都在端口2222上运行sshd。
与其这样做,不如在同一行上列出多个主机,用空格分隔。例如:
xxxxxxxxxx
Host 129.0.2.* mwl.io *.mwl.io gluttony avarice lust pride wrath envy sloth
Port 2222
我列出了*.mwl.io和mwl.io,因为有一台名为mwl.io的特定计算机,域名前的星号和句点将与该主机不匹配。
将所有全局默认值放在配置文件的开头。假设你的组织有一个在端口981上运行SSH的策略,因为他们喜欢通过隐藏来实现安全性,但你的特殊服务器使用不同的端口来实现更多的隐藏:
xxxxxxxxxx
Port 981
Host *.mwl.io
Port 2222
这里的默认端口是981,但指定的主机使用端口2222。
有时,你希望在不干扰工作配置的情况下测试更改,或者你可能有一个需要特殊配置文件的自动化过程。要使用ssh_config以外的配置文件,可在命令行中使用-F选项指定它:
xxxxxxxxxx
$ ssh -F test-config avarice
现在,您可以在不破坏工作配置的情况下尝试功能。
如果你有足够的主机,你可以考虑在ssh_config中建立规范的主机名。
在足够大的网络上,或者在服务器动态创建和销毁的编排环境中,列出所有SSH服务器很快就变得不切实际。
canonicalize——规范化
CanonicalizeHostname关键字告诉ssh将ssh_config中的独立Host条目重写到特定域中,然后使用该主机名进行配置和密钥管理。
这使你可以消除许多冗长的主机关键字。将CanonicalizeHostname设置为yes,将CanonicalDomains设置为你的域,参考以下配置:
xxxxxxxxxx
CanonicalizeHostname yes
CanonicalDomains mwl.io
Host *.mwl.io
Port 2222
下次我运行ssh gluttony,ssh会检查是否有gluttony.mwl.io。如果该主机名存在,ssh会像运行 ssh gluttony.mwl.io一样套用ssh_config中的配置。此连接将会获取适用于mwl.io域中主机的特殊规则。
你可以列出多个规范域。按照列出的顺序测试规范名称,第一场比赛获胜。参考以下条目:
xxxxxxxxxx
CanonicalDomains mwl.io michaelwlucas.com
当我运行ssh wrash时,ssh会搜索wrath.mwl.io,如果找到该主机,它将打开一个连接。如果找不到,ssh会继续搜索下一个wrath.michaelwlucas.com。
如果你激活主机名规范化(canonicalization),ssh默认会尝试对包含一个或更少点(fewer dots)的主机进行规范化。这使得规范化捕获子域,例如www.detroit.mwl.io对应的www.detroit。
要更改主机名中的最大点数,请使用CanonicalizeMaxDots关键字。下面示例允许零个或更少的点:
xxxxxxxxxx
CanonicalizeMaxDots 0
OpenSSH还有其他一些主机名规范化特性,参阅ssh_confg(5)手册页。
最常见功能时更改用户名、端口或添加SSH选项。
大多数SSH客户端假设你的用户名在客户端和服务器上都是相同的,并尝试使用你在本地计算机上的相同用户名登录远程系统。
如果本地用户名和远程用户名不同,可使用用户名加@符号,然后加远程主机名来连接主机:
xxxxxxxxxx
$ ssh jerkface@devio.us
也可以使用-l指定用户名:
xxxxxxxxxx
$ ssh -l jerkface devio.us
对于上述情况,可以在ssh_config中使用User关键字指定用户名:
xxxxxxxxxx
Host devio.us
User jerkface
下次通过ssh登录devio.us时就不用再输入用户名了。
一些站点在22以外的端口上运行SSH,通常是为了提供更高的安全性(这样做通常不能保护SSH,但确实可以降低日志噪声)。
使用-p和端口号更改ssh连接到的端口:
xxxxxxxxxx
$ ssh -p 2222 gluttony
你可以在ssh_config中指定端口:
xxxxxxxxxx
Port 2222
同样,我建议将永久连接信息存储在ssh_config中。
SSH不仅仅是一个命令,这是一个协议。该协议有各种边缘情况。有时,你需要在命令行上设置一些边线。
虽然OpenSSH支持的所有内容都可以作为ssh_config关键字获得,但并非所有这些关键字都有命令行等效项。
要在命令行设置这些关键字,请使用-o命令行选项、选项名称、等号和该关键字的值:
xxxxxxxxxx
$ ssh -o Port=2222 sloth
这个例子很简单——Port关键字有一个专用的命令行选项-p。稍后会有更复杂的例子。
你可以设置命令行选项、用户配置文件中的选项和全局客户端配置文件的选项。
Host关键字可能会破坏你精心调整的默认值,或者你精心调整后的默认值可能要求你为特定服务器使用Host关键字。当你连接到主机时,你如何知道ssh实际使用了哪些选项?
使用-G选项运行ssh,它告诉ssh解析目标主机的所有配置,打印出要使用的配置,然后立即退出而不进行连接。
你可以查看你的设置,以验证你是否获得了所需的内容。
系统管理员经常需要从一台主机连接到另一台主机。也许你信任这个中间主机,也许不信任。
OpenSSH支持跳转主机,允许你使用SSH服务器作为中继连接到第二台服务器。
你可以通过登录到中间主机然后再次运行ssh来手动完成此操作,但使用内置支持意味着跳转主机看不到你的纯文本。跳转主机无法控制客户端和目标服务器协商的选项。这意味着你可以通过一个不接受任何一个的跳转主机转发X或你的SSH代理。
使用-J指定跳转主机。如果需要,可以添加用户名:
xxxxxxxxxx
$ ssh -J mwl@envy jerkface@pride
我试图以jerkface登录pride,使用mwl帐户借用envy主机作为跳转主机。
系统将提示我输入跳转主机上的身份验证凭据,然后输入目标上的凭据。最好在两台主机上都使用公钥身份验证。
在ssh_config中使用ProxyJump关键字设置跳转主机:
xxxxxxxxxx
Host pride.mwl.io
ProxyJump mwl@envy.mwl.io
你有多信任跳转机?你的所有按键都不会到达跳转机,因此你不必担心会话日志记录。跳转机可以更改或中断加密流,但这正是SSH旨在检测的篡改类型。
一些Linux发行版在其客户端中禁用跳转主机。
OpenSSH客户端运行你通过设置地址族和源地址来选择它如何使用TCP/IP。
主机可以同时同时拥有IPv4和IPv6地址。AddressFamily关键字告诉客户端仅使用IPv4(inet)或仅连接IPv6(inet6)。默认值是any,表示两者都可以。
有时,通过某一种协议可以获得更好的连接。以下示例禁用IPv4:
xxxxxxxxxx
AddressFamily inet6
你可以通过命令行选项 -4选择仅使用IPv4:
xxxxxxxxxx
$ ssh -4 lust
使用-6强制使用IPv6。
在单个接口上具有多个IP地址的主机默认从该接口的主IP地址发起所有连接。这并不总是可取的。服务可以从一个主机迁移到另一个主机,通常不受任何防火墙更改的影响。您可以在ssh_config中使用BindAddress关键字告诉ssh使用主IP地址以外的源IP地址:
xxxxxxxxxx
BindAddress 192.0.2.9
BindAddress必须附加到本地计算机。
BindAddress没有方便的命令行标志。您必须用-o指定它。
OpenSSH客户端在$HOME/.ssh/known_hosts中记录用户批准的主机密钥。每个密钥都出现在known_hosts中自己的行上,就像这样:
xxxxxxxxxx
wrath.mwl.io ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbm…
每一行都包含机器的主机名(wrath.mwl.io)、主机密钥类型(ecdsa-sha2-nistp256)和公钥本身。
你打算如何更新密钥缓存?在某些环境中,用户必须手动验证主机密钥,然后手动将其添加的哦密钥缓存中。在其他环境中,自动向缓存添加新密钥是可以接受的。
最常见的情况是,用户希望ssh询问他们该做什么。ssh_config的StrictHostKeyChecking选项告诉ssh如何处理新的主机密钥。
将StrictHostKeyChecking设置为yes,ssh将拒绝所有在known_hosts中没有条目的主机。客户端连接的唯一方法是将主机密钥手动添加到known_hosts中。在主机密钥自动分发的环境中,这是最有意义的。
将StrictHostKeyChecking设置为accept-new,将无条件接受新的主机密钥。这样很危险。
默认设置是ask。当遇到未知密钥时,ssh会询问怎么做。你可以验证密钥、接受密钥,并让ssh将其添加到known_hosts中;或者拒绝主机密钥。
选择最适合你的环境的选项。
known_hosts文件对于闯入你桌面的入侵者来说非常方便。这是一个方便的SSH服务器目标列表。
由于你的SSH服务器可能共享一个共同的系统管理员,因此用于渗透桌面的技术可能适用于任何这些服务器。
此外,系统管理员和其他用户可以查看known_hosts的内容。
防止窥探的最佳方法是更改known_hosts,使其不再包含主机名列表。通过哈希主机名来实现这一点,就像/etc/passwd对密码做的那样。
如果用哈希替换主机名,则没有人可以从文件中读取主机名,也没有人可以反向计算主机名。然而,当你连接到主机时,ssh可以轻松计算服务器主机名的哈希值,并在known_hosts中查找该哈希值。
一个哈希过的known_hosts条目看起像这样:
xxxxxxxxxx
|1|PBM07JCRBjfg8qOz1BokTtCDly0=|DVXu0IFq/dC4GMfbEbfVkhptVjQ= ecdsa-sha2-nistp256 AAAAE2VjZ…
如果你检查条目,你会在下面看到密钥算法和主机密钥指纹。
要让ssh自动对添加到known_hosts的新主机密钥进行哈希运算,可以使用ssh_config关键字HashKnownHosts:
xxxxxxxxxx
HashKnownHosts yes
然而,这不会对现有条目进行哈希运算。可以使用ssh-keygen命令的-H选项对现有的known_hosts条目进行哈希运算:
xxxxxxxxxx
$ ssh-keygen -H
/home/mwlucas/.ssh/known_hosts updated.
Original contents retained as /home/mwlucas/.ssh/known_hosts.old
WARNING: /home/mwlucas/.ssh/known_hosts.old contains unhashed entries
Delete this file to ensure privacy of hostnames
哈希你的known_hosts会将现有的缓存复制到known_hosts.old,然后哈希known_hosts中的所有内容。验证ssh是否仍然可以连接到所有常用主机。一旦你确信你的密钥缓存仍然可用,就删除未哈希的known_hosts.old文件。
要在哈希known_hosts文件中查找单个主机条目,请使用ssh-keygen -F和目标主机名:
xxxxxxxxxx
$ ssh-keygen -F avarice.mwl.io
# Host avarice.mwl.io found: line 17
|1|5hcRwDHWxwxCWrFTngG4jT4OhJ0=|TyJXB6z+oEJXSP5MzakulFWgPDI= ecdsa-sha2-nistp256…
现在您知道此条目位于文件的第17行,并且可以轻松复制它。
要删除哈希主机名,请使用ssh-keygen -R:
xxxxxxxxxx
$ ssh-keygen -R avarice.mwl.io
# Host avarice.mwl.io found: line 17
/home/mwlucas/.ssh/known_hosts updated.
Original contents retained as /home/mwlucas/.ssh/known_hosts.old
如果你没有删除未哈希的known_hosts.old,那么它现在就不见了。
当从中央系统分发known_hosts时(第11章),没有理由不提供哈希版本。
PuTTY是一个SSH、telnet和串行客户端,也是一个终端模拟器,适用于Windows和类Unix系统。
虽然它不是由OpenBSD团队中的专业偏执狂编写的,但PuTTY的免费源代码已经过反复审核。PuTTY可能是部署最广泛的Windows SSH软件。
不建议使用开发版,虽然可能包含最新的补丁和功能,但也可能包含最新的、未知的错误。
putty主界面的右侧,您将配置到不同服务器的连接。我们现在只有一个连接,默认设置。它不会连接到任何东西,但您将使用它来设置PuTTY默认值。您始终可以通过点击左侧的Session返回此屏幕。
在左侧,您可以配置PuTTY如何呈现自己以及如何处理支持的协议的选项。PuTTY支持多种协议。如果你需要一个灵活的通用终端模拟器,PuTTY可能可以满足你的需求。不过,我们只会介绍SSH。请注意SSH选项,从底部起第二个。点击此处,或展开那个小“加号”,查看和编辑PuTTY如何执行SSH的详细信息。
如果您在左侧选择了某些内容,右侧将更改以显示所选选项的详细信息。选择SSH,右侧将显示一些基本协议选项,例如协议版本和共享SSH连接(请参阅本章后面的“连接多路复用”) 我们将使用这些设置来建立PuTTY默认值。
您的新PuTTY安装只列出了一个连接,即Default Settings。您创建的每个新连接都是从复制默认设置中的所有内容开始的。单击Default Settings连接,然后单击Load。然后,您可以编辑并保存默认设置连接。
PuTTY将其配置和主机密钥缓存存储在Windows的注册表中:
[HKEY_CURRENT_USER\SOFTWARE\SimonTatham]
要将PuTTY配置从一个主机移动到另一个主机,可以将注册表的这部分复制到新主机。有些人甚至使用这些注册表设置通过Active Directory向用户分发有效的PuTTY配置。
PuTTY有两个调试工具:事件日志和会话日志。
事件日志记录了当前SSH会话期间发生的事情。您可以看到您连接的名称、IP地址和端口、选定的加密算法以及建立SSH会话所需的所有各种协商。要查看事件日志,请单击PuTTY窗口的左上角,然后转到事件日志。
对于严重的调试,请使用会话日志。在打开SSH连接之前,请查看左侧窗格。在“会话”下,您将找到“日志记录”选项。选择它。此窗口为您提供了几个记录SSH会话的选项。我通常选择“所有会话输出”。给PuTTY一个日志文件的名称,然后浏览选择一个目录。一旦会话运行了一段时间,此文件将包含有关会话的大量详细信息,就像OpenSSH客户端调试选项一样。
您可以更改现有PuTTY会话中的一些设置。用户名和加密信息在登录时设置,但您可以更改日志记录、终端行为和隧道设置。
转到现有PuTTY会话的左上角,然后单击PuTTY图标。从下拉菜单中,选择“Change Settings”。这将打开一个简化的“New Session”窗口,仅显示您可以更改的选项。一旦你进行了编辑,并确认会话按照你想要的方式工作,你就可以保存会话,要么覆盖现有名称,要么选择一个新名称。
SSH会话可能需要很长时间才能打开,特别是如果SSH服务器找不到客户端IP地址的反向DNS条目。或者,您可能有一个幼稚的防火墙,限制了网段之间同时连接的数量。也许其中一台机器太旧了,初始密钥交换需要几秒钟的时间。SSH支持这些情况下的连接多路复用,允许您在一个TCP连接上运行多个SSH会话。虽然这并不能消除第一次连接的延迟,但额外的会话开始得更快。
PuTTY默认支持并使用连接多路复用。OpenSSH可以多路复用连接,但需要额外的配置。
OpenSSH的ssh客户端使用UNIX套接字来管理多路连接。用户必须为套接字创建一个目录并设置权限,以便只有她可以读取它们。
xxxxxxxxxx
$ cd $HOME/.ssh
$ mkdir sockets
$ chmod 700 sockets/
你现在可以在ssh_config中启用复用:
xxxxxxxxxx
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlMaster设置告诉ssh尝试使用连接多路复用,但如果多路复用失败,则返回到单独的TCP连接。这允许您默认启用多路复用,但仍可以连接到非OpenSSH服务器。
ControlPath告诉ssh在哪里可以找到多路复用管理文件。此语句接受令牌,与sshd_config非常相似。%u宏扩展为用户名,%h扩展为主机,%p扩展为端口。
如果我以用户mwl的身份在端口2222上连接到主机avarice,SSH会自动在指定目录中创建套接字文件 mwl@avarice:2222。
PuTTY默认启用连接多路复用。要在打开会话之前关闭它,请打开PuTTY并从左侧窗格中选择SSH。您将看到一个名为“Share SSH connections if possible”的复选框。取消选择它。
任何可以读取OpenSSH的多路复用控制文件或访问PuTTY类似套接字的人都可以访问通过SSH连接传输的所有数据。原始连接已经过身份验证,因此这样的入侵者甚至不需要您的密码就可以在远程机器上获取终端。仅在您信任所有具有管理权限的人的客户端上使用连接多路复用。
通过多路SSH会话复制大文件可能会减慢其他会话的速度。
X转发在连接多路复用时效果不佳。
请记住,在多路复用时,您与服务器的所有SSH连接都会在您打开的第一个主机连接上运行。如果该连接失败,与之复用的所有连接也将失败。
就我个人而言,我只在单用户桌面系统上启用多路复用。其他人不同意我的观点。做对你的环境有意义的事情。
你会在很多地方听到SSH可以在通过网络发送数据之前压缩数据。这在33.6调制解调器是人们在家连接的标准方式时非常有用。在现代多兆比特连接上,压缩通常会减慢连接速度。只有在带宽严重受限的情况下,才考虑使用压缩。
压缩有意义的一种情况是转发X(第8章)。在ssh(1)中添加-C标志可以使转发的X连接的吞吐量增加一倍。
这涵盖了PuTTY和OpenSSH客户端的基础知识。现在让我们看看使用SSH在网络中移动文件。