檢視原始碼 在 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 階段計算出的金鑰(以及其他資訊)來產生實際使用的金鑰。範例包括三重 DES '3des-cbc' 和許多 AES 變體中的一種 'aes192-ctr'

    此清單實際上是兩個 - 每個方向一個,即從伺服器到客戶端和從客戶端到伺服器。因此,在一個連線中,兩個方向使用不同的演算法是可能的,但很少見。

  • mac - 訊息驗證碼

    對等方之間發送的每條訊息的「校驗和」。範例包括 SHA 'hmac-sha1' 和 SHA2 'hmac-sha2-512'

    此清單也分為兩個方向。

  • compression - 是否壓縮訊息以及如何壓縮。範例包括 none,即不壓縮,以及 zlib

    此清單也分為兩個方向。

SSH 應用程式的機制

SSH 應用程式預設使用的演算法集取決於以下項目支援的演算法:

  • crypto 應用程式,
  • OTP 連結的 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,['aes256-gcm@openssh.com',
                          'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                          'aes192-ctr','aes128-gcm@openssh.com','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,'zlib@openssh.com',zlib]},
               {server2client,[none,'zlib@openssh.com',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,['aes256-gcm@openssh.com',
                          'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                          'aes192-ctr','aes128-gcm@openssh.com','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,'zlib@openssh.com',zlib]},
               {server2client,[none,'zlib@openssh.com',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,'zlib@openssh.com',zlib]},
               {server2client,[none,'zlib@openssh.com',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,['aes256-gcm@openssh.com','aes256-ctr',
                          'aes192-ctr','aes128-gcm@openssh.com','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,'zlib@openssh.com',zlib]},
               {server2client,[none,'zlib@openssh.com',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,      ...}
		    ]}

每個 ... 可以是 algs_list(),作為 preferred_algorithms 選項的引數。

範例 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,['aes256-gcm@openssh.com',
                          'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
                          'aes128-ctr','aes128-cbc','3des-cbc']},
          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                          'aes192-ctr','aes128-gcm@openssh.com','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,'zlib@openssh.com',zlib]},
               {server2client,[none,'zlib@openssh.com',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 中的配置章節。