查看源代码 SSH 中的配置

简介

OTP SSH 应用程序可以通过大量的选项进行配置。本章不会详细介绍每个选项的功能。它将描述和定义可以输入这些选项的不同方式。

关于强化的选项在 SSH 强化 章节中进行了描述。算法配置选项如何交互在 在 SSH 中配置算法 章节中进行了描述。

选项配置

从 OTP-23.0 开始,主要有两种方式来设置选项

  • 像以前一样,在调用 Erlang 代码中的 Options 参数中,例如 ssh:daemon/3ssh:connect/3 或它们的任何变体。示例

    ssh:connect(22, [{user,"foo"}])
  • OTP 配置参数

    • 在 erl 命令行中

      erl -ssh user \"foo\"
    • ssh.app 文件中,在 env 部分

      {application, ssh,
       [{description, "SSH-2 for Erlang/OTP"},
        {vsn, "4.9"},
        {modules, [ssh,
              ...
               ssh_xfer]},
        {registered, []},
        {applications, [kernel, stdlib, crypto, public_key]},
        {env, [{user, "bar"]}, % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE
        {mod, {ssh_app, []}},
             ...
    • 在一个 .config 文件中

      erl -config ex1

      其中 ex1.config 包含

      [
      {ssh, [{user, "foo"}]}
      ].

    如果某个选项仅用于服务器或客户端,则可以按以下方式设置

    [
    {ssh, [{server_options,[{user, "foo"}]},
           {client_options,[{user, "bar"}]}
    ].

    服务器(守护进程)将使用用户名 foo,而客户端将使用名称 bar

优先级

如果一个选项以多种方式设置,会发生什么?

存在一个排序,即

  • 级别 0:OTP SSH 源代码中的硬编码默认值
  • 级别 1:OTP 配置参数
  • 级别 2:OTP 配置参数 中的 server_optionsclient_options 中的选项
  • 级别 3:函数参数列表中的选项

如果同一个选项在两个不同的级别设置,则使用最高级别的选项。

唯一的例外是 modify_algorithms 通用选项。它们都按升序级别顺序应用于算法集。因此,级别一的 modify_algorithms 会在级别二的 modify_algorithms 之前应用,依此类推。

如果在某个级别存在 preferred_algorithms 选项,则整个集合将被该选项中的集合替换,并且所有 modify_algorithms 都将按级别顺序应用

按级别顺序应用所有 modify_algorithms 的原因是,允许用户在不更改代码的情况下,仅通过在配置文件中添加选项来添加已从默认集合中删除的算法。这可用于与仍然使用不再被认为足够安全而默认支持的算法的旧系统进行互操作。

算法配置

关于 preferred_algorithmsmodify_algorithms 如何协同工作,有一个 单独的章节。不同的配置级别如何影响它们,在本节中进行了描述。

ssh:start/0 函数

如果应用程序 SSH 没有 启动,命令 ssh:default_algorithms/0 将根据当前 cryptolib 中的支持情况,传递默认(硬编码)算法的列表。

如果应用程序 SSH 启动,命令 ssh:default_algorithms/0 将在应用级别 0 和级别 1 的配置后,传递算法列表。

这是一个示例。配置文件具有以下内容

$ cat ex2.config
[
 {ssh, [{preferred_algorithms, [{cipher, ['aes192-ctr']},
       			        {public_key, ['ssh-rsa']},
                                {kex, ['ecdh-sha2-nistp384']},
                                {mac, ['hmac-sha1']}]}]}
].

Erlang 以 ex2.config 作为配置启动,我们在启动 ssh 之前检查默认的算法集

$ erl -config ex2
Erlang/OTP 23 [RELEASE CANDIDATE 1] [erts-10.6.4] [source-96a0823109] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.6.4  (abort with ^G)
1> ssh:default_algorithms().
[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
       'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
       'diffie-hellman-group16-sha512',
       'diffie-hellman-group18-sha512',
       'diffie-hellman-group14-sha256','curve25519-sha256',
       '[email protected]','curve448-sha512',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-ed25519','ssh-ed448','ssh-rsa',
              'rsa-sha2-256','rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['[email protected]',
                          '[email protected]','aes256-ctr','aes192-ctr',
                          '[email protected]','aes128-ctr','aes256-cbc',
                          'aes192-cbc','aes128-cbc','3des-cbc']},
          {server2client,['[email protected]',
                          '[email protected]','aes256-ctr','aes192-ctr',
                          '[email protected]','aes128-ctr','aes256-cbc',
                          'aes192-cbc','aes128-cbc','3des-cbc']}]},
 {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
                       'hmac-sha1']},
       {server2client,['hmac-sha2-256','hmac-sha2-512',
                       'hmac-sha1']}]},
 {compression,[{client2server,[none,'[email protected]',zlib]},
               {server2client,[none,'[email protected]',zlib]}]}]

请注意,文件 ex2.config 中的算法尚未应用。它们将在我们启动 ssh 时应用

2> ssh:start().
ok
3> ssh:default_algorithms().
[{kex,['ecdh-sha2-nistp384']},
 {public_key,['ssh-rsa']},
 {cipher,[{client2server,['aes192-ctr']},
          {server2client,['aes192-ctr']}]},
 {mac,[{client2server,['hmac-sha1']},
       {server2client,['hmac-sha1']}]},
 {compression,[{client2server,[none,'[email protected]',zlib]},
               {server2client,[none,'[email protected]',zlib]}]}]
4>

我们看到算法集已更改为 ex2.config 中的算法集。由于文件中未指定 compression,因此该条目仍然使用硬编码的默认值。

建立连接(ssh:connect 等)或启动守护进程 (ssh:daemon)

当客户端使用 ssh:connect 或其他函数建立连接,或者使用 ssh:daemon 启动守护进程时,函数调用中的选项列表也会被使用。

如果启动了客户端 (ssh:connect 等),则会使用环境变量 client_options。类似地,对于守护进程,会处理 server_options 变量。

如果存在任何 preferred_algorithms,则使用最高级别的选项,即 Option 列表参数具有最高优先级。然后,从级别 0 开始按顺序应用所有级别上的 modify_algorithms

我们通过连接到服务器并修改 kex 算法集来继续上面的示例。我们删除唯一一个 ('ecdh-sha2-nistp384') 并通过将其附加到现在为空的列表来添加 '[email protected]'

4> {ok,C} = ssh:connect(loopback, 22,
                        [{modify_algorithms,
                                 [{rm,
                                     [ {kex,['ecdh-sha2-nistp384']} ]
				  },
                                  {append,
			             [ {kex,['[email protected]']} ]
				  }
				 ]
	                 }
                        ]).
{ok,>0.118.0>}

我们检查客户端和服务器协商了哪些算法,并注意到选择了(唯一的)kex 算法 '[email protected]'

5> ssh:connection_info(C, algorithms).
{algorithms,[{kex,'[email protected]'},
             {hkey,'ssh-rsa'},
             {send_mac,'hmac-sha1'},
             {recv_mac,'hmac-sha1'},
             {encrypt,'aes192-ctr'},
             {decrypt,'aes192-ctr'},
             {compress,none},
             {decompress,none},
             {send_ext_info,false},
             {recv_ext_info,true}]}

modify_algorithms 处理的示例

现在,我们将检查较低级别的 modify_algorithms 是否应用于较高级别的 preferred_algorithms。我们将通过启用支持但不在默认集合中的 ssh-dss 算法来实现这一点。

配置文件 ex3.config 的内容如下

[
 {ssh, [{modify_algorithms,
         [ {prepend, [{public_key, ['ssh-dss']}]} ]
        }]}
].

新启动的 erlang shell 显示 public_key 条目中不存在 'ssh-dss'

1> proplists:get_value(public_key, ssh:default_algorithms()).
['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
 'ecdsa-sha2-nistp256','ssh-ed25519','ssh-ed448',
 'rsa-sha2-256','rsa-sha2-512','ssh-rsa']
2>

调用 ssh:connect/3 会删除所有算法,但每种类型保留一个

2> ssh:start().
ok
3> {ok,C} = ssh:connect(loopback, 22,
                        [{preferred_algorithms,
                         [{public_key, ['ecdsa-sha2-nistp256']},
			  {kex, ['ecdh-sha2-nistp256']},
		          {cipher, ['[email protected]']},
			  {mac, ['hmac-sha2-256']},
			  {compression, [none]}
			  ]}
			 ]).
{ok,<0.101.0>}
4> ssh:connection_info(C,algorithms).
{algorithms,[{kex,'ecdh-sha2-nistp256'},
             {hkey,'ssh-dss'},
             {send_mac,'[email protected]'},
             {recv_mac,'[email protected]'},
             {encrypt,'[email protected]'},
             {decrypt,'[email protected]'},
             {compress,none},
             {decompress,none},
             {send_ext_info,false},
             {recv_ext_info,true}]}
5>

但是选择了 'ssh-dss',尽管调用插入了 'ecdsa-sha2-nistp256' 作为可接受的算法。

此示例表明,我们可以在无需更改实际调用的情况下,使用配置文件来增强算法集。

出于演示目的,我们使用了 prepend 而不是 append。这强制协商选择 ssh-dss,因为公钥算法的完整列表是 ['ssh-dss','ecdsa-sha2-nistp256']。通常,附加一个非默认算法更安全。