查看源代码 在 SSH 中配置算法

简介

要完全理解如何配置算法,必须对 SSH 协议以及 OTP SSH 应用程序如何处理相应的项有一个基本的了解。

第一小节将简要介绍 SSH 协议的背景,而后面的章节将描述实现并提供一些示例。

有关不同级别的配置如何“干扰”此项,请参阅算法配置章节中的SSH 中的配置

ssh 协议的算法处理基础

SSH 在会话的不同阶段使用不同的算法集。要使用哪些算法由客户端和服务器在会话开始时协商。有关详细信息,请参见RFC 4253,《安全外壳(SSH)传输层协议》。

协商很简单:双方都会将它们支持的算法列表发送给对方。选择客户端列表中也出现在服务器列表中的第一个算法。因此,客户端的列表顺序决定了算法的优先级。

在连接设置中交换了五个列表。其中三个列表还分为两个方向,即发送到服务器和从服务器发送。

列表如下(名称与 SSH 应用程序的选项中相同)

  • kex - 密钥交换

    选择一个算法来计算秘密加密密钥。示例包括:如今已弱的旧算法 'diffie-hellman-group-exchange-sha1' 以及非常强大和现代的 'ecdh-sha2-nistp512'

  • public_key - 服务器主机密钥

    服务器的私钥-公钥对中使用的非对称加密算法。示例包括著名的 RSA 'ssh-rsa' 和椭圆曲线 'ecdsa-sha2-nistp521'

  • cipher - 用于有效负载加密的对称密码算法。此算法将使用在 kex 阶段计算的密钥(以及其他信息)来生成实际使用的密钥。示例包括 triple-DES '3des-cbc' 和多种 AES 变体之一 'aes192-ctr'

    此列表实际上是两个 - 每个方向一个,服务器到客户端和客户端到服务器。因此,在同一连接的两个方向上使用不同的算法是可能的,但很少见。

  • mac - 消息认证码

    对等方之间发送的每条消息的“校验和”。示例包括 SHA 'hmac-sha1' 和 SHA2 'hmac-sha2-512'

    此列表也分为两个方向

  • compression - 是否以及如何压缩消息。示例包括 none,即不压缩,以及 zlib

    此列表也分为两个方向

SSH 应用程序的机制

SSH 应用程序默认使用的算法集取决于以下算法支持的算法:

  • crypto 应用程序,
  • OTP 链接到的 cryptolib,通常是操作系统使用的 cryptolib,可能是 OpenSSL,
  • 以及最终 SSH 应用程序实现的算法。

因此,不可能在文档中列出特定安装中可用的算法。

有一个重要的命令可以列出实际的算法及其顺序:ssh:default_algorithms/0

0> 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',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
              'rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['[email protected]',
                          'aes256-ctr','aes192-ctr','[email protected]',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['[email protected]','aes256-ctr',
                          'aes192-ctr','[email protected]','aes128-ctr',
                          '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]}]}]

要更改算法列表,可以在 ssh:connect/2,3,4ssh:daemon/2,3 中使用两个选项。当然,这些选项也可以用于启动连接的所有其他函数。

这两个选项是 preferred_algorithmsmodify_algorithms。第一个选项替换默认集合,而后者修改默认集合。

替换默认集:preferred_algorithms

有关详细信息,请参阅参考手册

以下是一系列示例,范围从简单到更复杂。

为了预见选项的效果,有一个实验函数 ssh:chk_algos_opts(Opts)。它以与 ssh:daemonssh:connect 及其友元相同的方式处理 preferred_algorithmsmodify_algorithms 选项。

示例 1

将 kex 算法列表替换为单个算法 'diffie-hellman-group14-sha256'

1> ssh:chk_algos_opts(
               [{preferred_algorithms,
                     [{kex, ['diffie-hellman-group14-sha256']}
                     ]
                }
              ]).
[{kex,['diffie-hellman-group14-sha256']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
              'rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['[email protected]',
                          'aes256-ctr','aes192-ctr','[email protected]',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['[email protected]','aes256-ctr',
                          'aes192-ctr','[email protected]','aes128-ctr',
                          '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]}]}]

请注意,未提及的列表(public_keyciphermaccompression)保持不变。

示例 2

在分为两个方向的列表(例如 cipher)中,可以同时更改两个方向

2> ssh:chk_algos_opts(
               [{preferred_algorithms,
                     [{cipher,['aes128-ctr']}
                     ]
                }
              ]).
[{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',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
              'rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['aes128-ctr']},
          {server2client,['aes128-ctr']}]},
 {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]}]}]

请注意,cipher 中的两个列表都已更改为提供的值('aes128-ctr')。

示例 3

在分为两个方向的列表(例如 cipher)中,可以仅更改其中一个方向

3> ssh:chk_algos_opts(
               [{preferred_algorithms,
                     [{cipher,[{client2server,['aes128-ctr']}]}
                     ]
                }
              ]).
[{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',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
              'rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['aes128-ctr']},
          {server2client,['[email protected]','aes256-ctr',
                          'aes192-ctr','[email protected]','aes128-ctr',
                          '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]}]}]

示例 4

当然,可以更改多个列表

4> ssh:chk_algos_opts(
               [{preferred_algorithms,
                     [{cipher,['aes128-ctr']},
		      {mac,['hmac-sha2-256']},
                      {kex,['ecdh-sha2-nistp384']},
		      {public_key,['ssh-rsa']},
		      {compression,[{server2client,[none]},
		                    {client2server,[zlib]}]}
                     ]
                }
              ]).
[{kex,['ecdh-sha2-nistp384']},
 {public_key,['ssh-rsa']},
 {cipher,[{client2server,['aes128-ctr']},
          {server2client,['aes128-ctr']}]},
 {mac,[{client2server,['hmac-sha2-256']},
       {server2client,['hmac-sha2-256']}]},
 {compression,[{client2server,[zlib]},
               {server2client,[none]}]}]

请注意,列表中元组的顺序无关紧要。

修改默认集:modify_algorithms

当需要使用受支持但已禁用的算法时,添加算法可能会很有用。一个例子是 'diffie-hellman-group1-sha1',它现在非常不安全,因此已被禁用。但是,它仍然受支持,并且可能会被使用。

对于添加或删除单个算法,preferred_algorithms 选项可能比较复杂。首先,必须使用 ssh:default_algorithms() 列出它们,然后在列表中进行更改。

为了方便添加或删除算法,提供了 modify_algorithms 选项。有关详细信息,请参阅参考手册

该选项接受一个列表,其中包含追加、前置或删除算法的指令

{modify_algorithms, [{append,  ...},
                     {prepend, ...},
		     {rm,      ...}
		    ]}

每个 ... 都可以是 preferred_algorithms 选项的参数的 algs_list()

示例 5

例如,让我们将 Diffie-Hellman Group1 添加到 kex 列表的开头。根据支持的算法,它是受支持的。

5> ssh:chk_algos_opts(
         [{modify_algorithms,
	       [{prepend,
	           [{kex,['diffie-hellman-group1-sha1']}]
		   }
	       ]
          }
        ]).
[{kex,['diffie-hellman-group1-sha1','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',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
              'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
              'rsa-sha2-512','ssh-dss']},
 {cipher,[{client2server,['[email protected]',
                          'aes256-ctr','aes192-ctr','[email protected]',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['[email protected]','aes256-ctr',
                          'aes192-ctr','[email protected]','aes128-ctr',
                          '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]}]}]

结果表明 Diffie-Hellman Group1 已添加到 kex 列表的开头

示例 6

在此示例中,我们将 'diffie-hellman-group1-sha1' 放在第一位,并将 'ecdh-sha2-nistp521' 移动到 kex 列表的末尾,即 append 它。

6> ssh:chk_algos_opts(
         [{modify_algorithms,
	       [{prepend,
	           [{kex, ['diffie-hellman-group1-sha1']}
		   ]},
		{append,
                   [{kex, ['ecdh-sha2-nistp521']}
                   ]}
	       ]
          }
        ]).
[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
       'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
       'diffie-hellman-group16-sha512',
       'diffie-hellman-group18-sha512',
       'diffie-hellman-group14-sha256',
       'diffie-hellman-group14-sha1',
       'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']},
 {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
   .....
]

请注意,追加的算法会从其原始位置删除,然后追加到同一列表中。

示例 7

在此示例中,我们同时使用两个选项(preferred_algorithmsmodify_algorithms),并且尝试预置一个不受支持的算法。任何不受支持的算法都将被悄悄删除。

7> ssh:chk_algos_opts(
         [{preferred_algorithms,
               [{cipher,['aes128-ctr']},
	        {mac,['hmac-sha2-256']},
                {kex,['ecdh-sha2-nistp384']},
		{public_key,['ssh-rsa']},
		{compression,[{server2client,[none]},
		              {client2server,[zlib]}]}
               ]
           },
          {modify_algorithms,
	       [{prepend,
	           [{kex, ['some unsupported algorithm']}
		   ]},
		{append,
                   [{kex, ['diffie-hellman-group1-sha1']}
                   ]}
	       ]
          }
        ]).
[{kex,['ecdh-sha2-nistp384','diffie-hellman-group1-sha1']},
 {public_key,['ssh-rsa']},
 {cipher,[{client2server,['aes128-ctr']},
          {server2client,['aes128-ctr']}]},
 {mac,[{client2server,['hmac-sha2-256']},
       {server2client,['hmac-sha2-256']}]},
 {compression,[{client2server,[zlib]},
               {server2client,[none]}]}]

当然,任何人都可能想同时使用这两个选项,这很值得怀疑,但是如果出现不可预见的需要,这是可能的。

示例 8

在此示例中,我们需要使用 diffie-hellman-group1-sha1 密钥交换算法,尽管它不安全且默认情况下处于禁用状态。

我们使用 modify_algorithms 选项,因为我们想保留所有其他算法定义。

我们将选项添加到

  {modify_algorithms, [{append, [{kex,['diffie-hellman-group1-sha1']}]}]}

函数调用中的 Options 列表,ssh.app 文件中,或 erl 命令的 .config 文件中。请参阅 SSH 用户指南中的SSH 中的配置章节。

示例 9

在此示例中,我们需要使用 DSA 密钥进行签名和验证。它可能是用户的密钥、主机的密钥,也可能是两者。

为此,我们启用了出于安全原因默认情况下禁用的 'ssh-dss' 算法。我们使用 modify_algorithms 选项,因为我们想保留所有其他算法定义。

我们将选项添加到

  {modify_algorithms, [{append, [{public_key,['ssh-dss']}]}]}

函数调用中的 Options 列表,ssh.app 文件中,或 erl 命令的 .config 文件中。请参阅 SSH 用户指南中的SSH 中的配置章节。