如何为SSH客户端配置自定义连接选项
介绍
SSH 或安全外壳是连接到 Linux 主机以进行远程管理的最常用方式。 虽然连接到单个主机的基础知识通常相当简单,但当您开始使用大量远程系统时,这可能会变得笨拙且复杂得多。
幸运的是,OpenSSH 允许您提供自定义的客户端连接选项。 这些可以保存到可用于定义每个主机值的配置文件中。 这有助于将您用于每个主机的不同连接选项保持分离和组织,并且可以使您不必在需要连接时在命令行上提供广泛的选项。
在本指南中,我们将介绍 SSH 客户端配置文件的基础知识,并介绍一些常用选项。
先决条件
要完成本指南,您将需要 SSH 的应用知识以及连接时可以提供的一些选项。 您可能还希望为某些用户或主机配置基于 SSH 密钥的身份验证,至少用于测试目的。
SSH 配置文件结构和解释算法
本地系统上的每个用户都可以维护一个客户端 SSH 配置文件。 这些可以包含您将在命令行上用于指定连接参数的任何选项,允许您存储常用连接项并在连接时自动处理它们。 始终可以通过 ssh
命令的正常标志覆盖连接时配置文件中定义的值。
SSH 客户端配置文件的位置
客户端配置文件称为 config
,它位于 .ssh
配置目录内的用户主目录中。 通常,默认情况下不会创建此文件,因此您可能需要自己创建它:
touch ~/.ssh/config
配置文件结构
config
文件由主机组织。 每个主机定义都可以定义特定匹配主机的连接选项。 通配符也可用于允许应具有更广泛范围的选项。
每个部分都以一个标题开始,该标题定义了应该与后面的配置选项匹配的主机。 然后在下面定义该匹配主机的特定配置项。 仅需要指定与默认值不同的项目,因为主机将继承任何未定义项目的默认值。 从 Host
头到后面的 Host
头定义了一个节。
通常,出于组织目的和可读性,为每个主机设置的选项是缩进的。 这不是硬性要求,而是一个有用的约定,可以让您一目了然地进行解释。
一般格式如下所示:
Host firsthost SSH_OPTION_1 custom_value SSH_OPTION_2 custom_value SSH_OPTION_3 custom_value Host secondhost ANOTHER_OPTION custom_value Host *host ANOTHER_OPTION custom_value Host * CHANGE_DEFAULT custom_value
在这里,我们有四个部分将应用于每次连接尝试,具体取决于相关主机是否匹配。
解释算法
了解 SSH 解释文件以应用其中定义的配置值的方式非常重要。 这在使用通配符和 Host *
通用主机定义时有很大的影响。
SSH 会将命令行中给出的主机名与定义配置部分的每个 Host
标头匹配。 它将从文件顶部向下执行此操作,因此顺序非常重要。
现在是指出 Host
定义中的模式不必与您将连接的实际主机匹配的好时机。 您基本上可以使用这些定义为主机设置别名,以代替实际主机名。
例如,考虑这个定义:
Host devel HostName devel.example.com User tom
该主机允许我们通过在命令行上键入以下内容以 tom@devel.example.com
的身份进行连接:
ssh devel
考虑到这一点,我们现在可以讨论 SSH 在文件中向下移动时应用每个配置选项的方式。 它从顶部开始并检查每个 Host
定义以查看它是否与命令行中给出的值匹配。
当找到第一个匹配的 Host
定义时,每个关联的 SSH 选项都将应用于即将到来的连接。 然而,解释并没有到此结束。
然后 SSH 向下移动文件,检查其他 Host
定义是否也匹配。 如果找到与命令行中给出的当前主机名匹配的另一个定义,它将考虑与新部分关联的 SSH 选项。 然后,它将应用为新部分定义的 之前的部分 尚未定义的任何 SSH 选项。
最后一点对于内化非常重要。 SSH 将按顺序解释与命令行中给出的主机名匹配的每个 Host
部分。 在此过程中,它将始终使用为每个选项提供的 first 值。 无法覆盖先前匹配的部分已经给出的值。
这意味着您的 config
文件应该遵循将最具体的配置放在顶部的简单规则。 为了应用前面匹配部分未定义的选项,稍后应提供更一般的定义。
让我们再看一下我们在上一节中使用的模型 config
文件:
Host firsthost SSH_OPTION_1 custom_value SSH_OPTION_2 custom_value SSH_OPTION_3 custom_value Host secondhost ANOTHER_OPTION custom_value Host *host ANOTHER_OPTION custom_value Host * CHANGE_DEFAULT custom_value
在这里,我们可以看到前两个部分是由文字主机名(或别名)定义的,这意味着它们不使用任何通配符。 如果我们使用 ssh firsthost
连接,第一个部分将是第一个应用的部分。 这将为此连接设置 SSH_OPTION_1
、SSH_OPTION_2
和 SSH_OPTION_3
。
它将检查第二部分并发现它不匹配并继续前进。 然后它将找到第三部分并发现它匹配。 它将检查 ANOTHER_OPTION
以查看它是否已经具有前面部分中的值。 发现它没有,它将应用本节中的值。 然后它将匹配最后一个部分,因为 Host *
定义匹配每个连接。 由于它没有其他部分的模拟 CHANGE_DEFAULT
选项的值,因此它将采用该部分的值。 然后使用从该过程中收集的选项建立连接。
让我们再试一次,假装从命令行调用 ssh secondhost
。
同样,它将从第一部分开始并检查它是否匹配。 由于这仅匹配到 firsthost
的连接,因此将跳过此部分。 它将进入第二部分。 在发现此部分与请求匹配后,它将收集此连接的 ANOTHER_OPTION
的值。
SSH 然后查看第三个定义,发现通配符与当前连接匹配。 然后它将检查它是否已经具有 ANOTHER_OPTION
的值。 由于此选项是在已匹配的第二部分中定义的,因此第三部分中的值将被删除并且无效。
SSH 然后检查第四部分并应用之前匹配的部分未定义的选项。 然后它使用它收集的值尝试连接。
基本连接选项
现在您已经了解了在设计配置文件时应该使用的一般格式,让我们讨论一些常用选项以及用于在命令行中指定它们的格式。
我们将介绍的第一个是连接到远程主机所需的基本信息。 即,运行 SSH 守护程序的主机名、用户名和端口。
要以名为 apollo
的用户身份从命令行连接到名为 example.com
的主机,该主机在端口 4567
上运行其 SSH 守护程序,我们可以以各种形式提供变量信息方法。 最常见的可能是:
ssh -p 4567 apollo@example.com
但是,我们也可以使用带有 -o
标志的完整选项名称,如下所示:
ssh -o "User=apollo" -o "Port=4567" -o "HostName=example.com" anything
在这里,我们已经设置了我们希望与 -o
标志一起使用的所有选项。 我们甚至将主机指定为“任何东西”作为别名,就像我们在上面描述的配置文件中一样。 实际主机名取自我们正在设置的 HostName
选项。
我们在第二种形式中使用的大写选项名称与我们必须在 config
文件中使用的相同。 您可以通过键入以下内容找到可用选项的完整列表:
man ssh_config
要在我们的 config
文件中设置这些,我们首先必须决定我们希望这些选项用于哪些主机。 由于我们正在讨论特定于相关主机的选项,因此我们可能应该使用文字主机匹配。
此时我们也有机会为此连接分配别名。 让我们利用这一点,这样我们就不必每次都输入整个主机名。 我们将使用别名“home”来指代此连接和相关选项:
Host home
现在,我们可以定义此主机的连接详细信息。 我们可以使用上面使用的第二种格式来告知我们应该在本节中放置什么。
Host home HostName example.com User apollo Port 4567
我们使用键值系统定义选项。 每对应该在单独的一行上。 可以通过空格或带有可选空格的等号将键与其关联的值分开。 因此,这些都与我们的 SSH 客户端所解释的相同:
Port 4567 Port=4567 Port = 4567
唯一的区别是,根据选项和值,使用不带空格的等号可以让您在命令行上指定选项而无需引用。 由于我们专注于我们的 config
文件,这完全取决于您的偏好。
配置共享选项
到目前为止,我们设计的配置非常简单。 总的来说,它看起来像这样:
Host home HostName example.com User apollo Port 4567
如果我们在工作和家庭计算机上使用相同的用户名怎么办? 我们可以在定义工作机器的部分中添加冗余选项,如下所示:
Host home HostName example.com User apollo Port 4567 Host work HostName company.com User apollo
这行得通,但我们正在重复价值观。 这只是一个选项,所以不是什么大不了的事,但有时我们希望共享大量选项。 最好的方法是将共享选项分成单独的部分。
如果我们在我们连接的所有机器上使用用户名“apollo”,我们可以将其放入我们的通用“主机”定义中,该定义由匹配每个连接的单个 *
标记。 请记住,更通用的部分应该更靠近底部:
Host home HostName example.com Port 4567 Host work HostName company.com Host * User apollo
这清除了我们配置中的重复问题,并且如果“apollo”是您连接到的大多数新系统的默认用户名,它将起作用。
如果有些系统不使用此用户名怎么办? 有几种不同的方法可以解决此问题,具体取决于用户名的共享范围。
如果在 几乎 所有主机上使用“apollo”用户名,最好将其保留在通用 Host *
部分中。 这将适用于尚未从上述部分收到用户名的任何主机。 对于我们使用不同用户名的异常机器,我们可以通过提供替代方法来覆盖默认值。 只要在通用部分之前定义,这将具有优先权:
Host home HostName example.com Port 4567 Host work HostName company.com Host oddity HostName weird.com User zeus Host * User apollo
对于 oddity
主机,SSH 将使用用户名“zeus”进行连接。 所有其他连接在达到通用 Host *
定义之前都不会收到他们的用户名。
如果“apollo”用户名由几个连接共享,但不够常用,不能用作默认值,会发生什么? 如果我们愿意重命名我们正在使用的别名以获得更通用的格式,我们可以使用通配符将附加选项应用于这两个主机。
我们可以将 home
别名更改为 hapollo
之类的名称,并将工作连接更改为 wapollo
之类的名称。 这样,两个主机共享其别名的 apollo
部分,允许我们使用通配符将其定位到不同的部分:
Host hapollo HostName example.com Port 4567 Host wapollo HostName company.com Host *apollo User apollo Host * User diffdefault
在这里,我们将共享的 User
定义移动到主机部分,该部分匹配尝试连接到以 apollo
结尾的主机的 SSH 连接。 任何不以 apollo
结尾的连接(并且没有定义 User
的自己的 Host
部分)将收到用户名 diffdefault
。
请注意,我们在文件中保留了从最具体到最不具体的顺序。 由于文件的解释顺序,最好将不太具体的 Host 部分视为备用而不是默认值。
常用 SSH 配置选项
到目前为止,我们已经讨论了建立连接所必需的一些基本选项。 我们已经介绍了这些选项:
- HostName:应该用于建立连接的实际主机名。 这将替换
Host
标头中定义的任何别名。 如果Host
定义指定要连接的实际有效主机名,则此选项是 not 必需的。 - User:用于连接的用户名。
- Port:远程 SSH 守护程序正在运行的端口。 仅当远程 SSH 实例未在默认端口
22
上运行时,才需要此选项。
还有许多其他有用的选项值得探索。 我们将讨论一些更常见的选项,按功能分开。
一般调整和连接项
您可能希望在 Host *
部分中广泛配置的其他一些调整如下。
- ServerAliveInterval:此选项可以配置为让 SSH 知道何时发送数据包以测试来自服务器的响应。 如果您的连接不可靠并且您想知道它是否仍然可用,这将很有用。
- LogLevel:这配置了 SSH 将在客户端登录的详细级别。 这可用于在某些情况下关闭日志记录或在尝试调试时增加详细程度。 从最详细到最详细,级别为 QUIET、FATAL、ERROR、INFO、VERBOSE、DEBUG1、DEBUG2 和 DEBUG3。
- StrictHostKeyChecking:此选项配置 ssh SSH 是否会自动将主机添加到
~/.ssh/known_hosts
文件。 默认情况下,这将设置为“询问”,这意味着如果从远程服务器收到的主机密钥与known_hosts
文件中的主机密钥不匹配,它将向您发出警告。 如果您经常连接到大量临时主机,您可能希望将其设置为“否”。 然后 SSH 会自动将任何主机添加到文件中。 这可能会产生安全隐患,因此在启用它之前请仔细考虑。 - UserKnownHostsFile:此选项指定 SSH 将存储有关它已连接到的主机的信息的位置。 通常您不必担心此设置,但如果您已关闭上面的严格主机检查,您可能希望将其设置为
/dev/null
。 - VisualHostKey:此选项可以告诉 SSH 在连接时显示远程主机密钥的 ASCII 表示。 启用此功能是熟悉主机密钥的一种简单方法,如果您将来必须从另一台计算机连接,则可以轻松识别它。
- Compression:打开压缩对于非常慢的连接很有帮助。 大多数用户不需要这个。
考虑到上述配置项,我们可以进行一些有用的配置调整。
例如,如果我们在云提供商处非常快速地创建和销毁主机,这样的事情可能会很有用:
Host home VisualHostKey yes Host cloud* StrictHostKeyChecking no UserKnownHostsFile /dev/null LogLevel QUIET Host * StrictHostKeyChecking ask UserKnownHostsFile ~/.ssh/known_hosts LogLevel INFO ServerAliveInterval 120
这将为您的家庭连接打开您的可视主机密钥,让您熟悉它,以便您可以识别它是否发生变化或何时从不同的机器连接。 我们还设置了任何以 cloud* 开头的主机,不检查主机也不记录故障。 对于其他主机,我们有合理的后备值。
连接转发
SSH 的一种常见用途是转发连接,或者允许本地连接通过远程主机建立隧道,或者允许远程计算机访问通过本地计算机建立隧道。 SSH 还可以使用诸如 SOCKS5 之类的协议进行动态转发,其中包括远程主机的转发信息。
控制此行为的选项是:
- LocalForward:此选项用于指定将本地端口的流量转发到远程计算机的连接,将其通过隧道传输到远程网络。 第一个参数应该是您希望将流量定向到的本地端口,第二个参数应该是您希望将该流量定向到远程端的地址和端口。
- RemoteForward:此选项用于定义一个远程端口,可以将流量定向到该端口,以便从本地计算机隧道传输出去。 第一个参数应该是将流量定向到远程系统的远程端口。 第二个参数应该是流量到达本地系统时指向的地址和端口。
- DynamicForward:用于配置本地端口,可与 SOCKS5 等动态转发协议一起使用。 然后可以将使用动态转发协议的流量定向到本地计算机上的此端口,而在远程端,它将根据包含的值进行路由。
这些选项可用于双向转发端口,如您在此处看到的:
# This will allow us to use port 8080 on the local machine # in order to access example.com at port 80 from the remote machine Host local_to_remote LocalForward 8080 example.com:80 # This will allow us to offer access to internal.com at port 443 # to the remote machine through port 7777 on the other side Host remote_to_local RemoteForward 7777 internal.com:443
其他转发
除了连接转发,SSH 还允许其他类型的转发。
我们可以转发存储在本地机器上的代理中的任何 SSH 密钥,允许我们从远程系统连接,就像使用存储在本地系统上的凭据一样。 我们还可以在远程系统上启动应用程序并使用 X11 转发将图形显示转发到我们的本地系统。
这些是与这些功能相关的指令:
- ForwardAgent:此选项允许将存储在我们本地计算机上的身份验证密钥转发到您正在连接的系统上。 这可以让您使用主密钥从主机跳到主机。
- ForwardX11:如果您希望能够转发远程系统上运行的应用程序的图形屏幕,您可以打开此选项。
这两个都是“是”或“否”选项。
指定键
如果您为主机配置了 SSH 密钥,这些选项可以帮助您管理要为每个主机使用的密钥。
- IdentityFile:此选项可用于指定要用于每个主机的密钥的位置。 如果您的密钥位于默认位置,则将尝试每个密钥,您无需对此进行调整。 如果您有许多键,每个键用于不同的用途,则可用于指定可以找到正确键的确切路径。
- IdentitiesOnly:此选项可用于强制 SSH 仅依赖于
config
文件中提供的身份。 如果 SSH 代理在内存中有对相关主机无效的备用密钥,则这可能是必要的。
如果您必须跟踪不同主机的大量密钥并使用一个或多个 SSH 代理来提供帮助,这些选项特别有用。
通过单个 TCP 连接多路复用 SSH
SSH 能够将单个 TCP 连接用于与同一主机的多个 SSH 连接。 如果与远程端建立 TCP 握手需要一段时间,这将很有用,因为它消除了额外 SSH 连接的开销。
以下选项可用于配置与 SSH 的多路复用:
- ControlMaster:此选项告诉 SSH 是否在可能的情况下允许多路复用。 通常,如果您希望使用此选项,您应该在连接缓慢的主机部分或通用
Host *
部分中将其设置为“自动”。 - ControlPath:此选项用于指定用于控制连接的套接字文件。 它应该位于文件系统上的某个位置。 通常,这是使用 SSH 变量来轻松按主机标记套接字的。 要根据用户名、远程主机和端口命名套接字,可以使用
/path/to/socket/%r@%h:%p
。 - ControlPersist:此选项确定在最终 SSH 连接关闭后 TCP 连接应保持打开状态的时间量(以秒为单位)。 将此设置为较高的数字将允许您在关闭第一个连接后打开新连接,但您通常可以将其设置为较低的值,例如“1”,以避免保持未使用的 TCP 连接打开。
通常,您可以使用如下所示的部分进行设置:
Host * ControlMaster auto ControlPath ~/.ssh/multiplex/%r@%h:%p ControlPersist 1
之后,您应该确保创建了目录:
mkdir -p ~/.ssh/multiplex
如果您不希望对特定连接使用多路复用,您可以在命令行上选择 no multiplexing,如下所示:
ssh -S none user@host
结论
到现在为止,应该清楚您可以大量自定义用于连接到远程主机的选项。 只要记住 SSH 解释值的方式,就可以建立丰富的特定值集和合理的后备。