Stories

Detail Return Return

【譯】使用TLS進行Erlang分發 - Stories Detail

        本節介紹Erlang發行版如何使用TLS來獲得額外的驗證和安全性。

        理論上,Erlang發行版可以使用幾乎所有基於連接的協議作為承載。但是,需要一個用於實現連接設置的協議特定部分的模塊。內核應用程序中的默認分發模塊是inet_tcp_dist。啓動分佈式的Erlang節點時,net_kernel使用此模塊設置偵聽端口和連接。

        在SSL應用程序中,可以使用一個額外的分發模塊inet_tls_dist作為替代。所有分發連接將使用TLS,並且分佈式系統中的所有參與的Erlang節點必須使用此分發模塊。

        安全級別取決於提供給TLS連接設置的參數。但是,始終使用Erlang節點cookie,因為它們可用於區分兩個不同的Erlang網絡。

        要通過TLS設置Erlang分發,請執行以下操作:

  • 步驟1:構建包括SSL應用程序在內的啓動腳本。
  • 步驟2:為net_kernel指定分發模塊。
  • 步驟3:指定安全選項和其他SSL選項。
  • 步驟4:將環境設置為始終使用TLS

        以下各節描述了這些步驟。

4.1 構建包括SSL應用程序在內的啓動腳本

        使用SASL應用程序中的systools實用程序來構建引導腳本。 有關systools的更多信息,請參見SASL文檔。 這僅僅是可以做的一個例子。

        最簡單的啓動腳本可能僅包括內核和STDLIB應用程序。 這樣的腳本位於Erlang發行版的bin目錄中。 該腳本的源代碼位於發行版/ <OTP版本> /start_clean.rel下的Erlang安裝目錄下。

請執行下列操作:

  • 將該腳本複製到另一個位置(最好是另一個名稱)。
  • STDLIB應用程序之後,添加應用程序CryptoPublic KeySSL及其當前版本號。

下面顯示了添加了TLS的示例.rel文件:

{release, {"OTP  APN 181 01","R15A"}, {erts, "5.9"},

      [{kernel,"2.15"},

      {stdlib,"1.18"},

      {crypto, "2.0.3"},

      {public_key, "0.12"},

      {asn1, "4.0"},

      {ssl, "5.0"}

      ]}.

        版本號在您的系統中有所不同。 每當腳本中包含的應用程序之一升級時,請更改腳本。

請執行下列操作:

  • 構建啓動腳本。

        假設.rel文件存儲在當前目錄的文件start_ssl.rel中,則可以如下構建啓動腳本:

 1> systools:make_script("start_ssl",[]).   

        現在,當前目錄中有一個start_ssl.boot文件。

請執行下列操作:

  • 測試啓動腳本。 為此,請使用-boot命令行參數指定此啓動腳本(具有其完整路徑,但不帶.boot後綴)來啓動Erlang。 在UNIX中,它可能如下所示:

$ erl -boot /home/me/ssl/start_ssl

Erlang (BEAM) emulator version 5.0

 

Eshell V5.0  (abort with ^G)

1> whereis(ssl_manager).

<0.41.0>

        whereis函數調用驗證SSL應用程序已啓動。

        作為構建引導腳本的替代方法,您可以在命令行上將路徑顯式添加到SSL ebin目錄。 這是通過命令行選項-pa完成的。 這可以工作,因為不需要啓動SSL應用程序即可發佈發行版本,因為SSL應用程序的克隆已掛接到內核應用程序中。 因此,只要可以訪問SSL應用程序代碼,就開始分發。 僅建議將-pa方法用於測試目的。

注意:SSL應用程序的克隆必須允許在建立發行版所需的早期引導階段使用SSL代碼。 但是,這使得無法軟升級SSL應用程序。

4.2 指定net_kernel的分發模塊

        TLS的分發模塊名為inet_tls_dist,並在命令行上使用選項-proto_dist指定。 -proto_dist的參數是不帶後綴_dist的模塊名稱。 因此,此分發模塊在命令行上通過-proto_dist inet_tls指定。

        擴展命令行給出以下內容:

$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls  

        對於要開始的分發,還要給仿真器起一個名字:

$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls -sname ssl_test

Erlang (BEAM) emulator version 5.0 [source]

 

Eshell V5.0  (abort with ^G)

(ssl_test@myhost)1>    

        但是,以這種方式啓動的節點拒絕與其他節點通信,因為沒有提供TLS參數(請參閲下一節)。

4.3 指定TLS選項

        可以將TLS分發選項寫入啓動節點時要查詢的文件。 然後,使用命令行參數-ssl_dist_optfile指定此文件名。

        可以在選項文件中指定任何可用的TLS選項,但請注意,採用fun()的選項必須使用語法fun Mod:Func/Arity,因為在查閲文件時無法編譯功能主體。

        不要篡改套接字選項列表,二進制文件,活動文件,數據包,nodelay和交付,因為它們由分發協議處理程序本身使用。 其他原始套接字選項(例如packet_size)可能會嚴重干擾,因此請注意!

        為了使TLS起作用,必須為服務器端至少指定一個公鑰和一個證書。 在以下示例中,PEM文件“ /home/me/ssl/erlserver.pem”包含服務器證書及其私鑰。

        創建一個名為“ /home/me/ssl/ssl_test@myhost.conf”的文件:

[{server,

  [{certfile, "/home/me/ssl/erlserver.pem"},

   {secure_renegotiate, true}]},

 {client,

  [{secure_renegotiate, true}]}].

        然後像這樣啓動節點(命令中的換行符是為了提高可讀性,鍵入時不應出現在換行符中):

$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls

  -ssl_dist_optfile "/home/me/ssl/ssl_test@myhost.conf"

  -sname ssl_test

        調用ssl:ssl_accept/3時,將使用{server,Opts}元組中的選項,而調用ssl:connect/4時,將使用{client,Opts}元組中的選項。

        對於客户端,在連接時會添加選項{server_name_indication,atom_to_list(TargetNode)}。這樣就可以使用客户端選項{verify,verify_peer},客户端將驗證證書是否與您要連接的節點名稱匹配。僅當服務器證書的名稱為atom_to_list(TargetNode)時,此方法才有效。

        對於服務器,也可以使用選項{verify,verify_peer},並且服務器將僅接受具有服務器已知根證書信任的證書的客户端連接。提供不可信證書的客户將被拒絕。此選項最好與{fail_if_no_peer_cert,true}組合,否則如果客户端不提供任何證書,則仍將被接受。

        使用TLS作為分發協議,以此方式啓動的節點可以正常運行。

4.4 指定TLS選項(舊版)

        與上一節一樣,PEM文件“ /home/me/ssl/erlserver.pem”包含服務器證書及其私鑰。

        在erl命令行上,您可以指定創建套接字時TLS分發添加的選項。

        可以通過在選項名稱中添加前綴server_或client_來指定以下列表中最簡單的TLS選項:

  • certfile
  • keyfile
  • password
  • cacertfile
  • verify
  • verify_fun (write as {Module, Function, InitialUserState})
  • crl_check
  • crl_cache (write as Erlang term)
  • reuse_sessions
  • secure_renegotiate
  • depth
  • hibernate_after
  • ciphers (use old string format)

        注意,因為在命令行上不接受funs,所以verify_fun需要以與相應的TLS選項不同的形式編寫。

        服務器還可以採用選項dhfile和fail_if_no_peer_cert(也帶有前綴)。

        當發行版啓動到另一個節點的連接時,將使用client_-prefixed選項。 接受來自遠程節點的連接時,將使用server_前綴選項。

        原始套接字選項(例如數據包和大小)不能在命令行上指定。

        用於指定TLS選項的命令行參數名為-ssl_dist_opt,後跟一對SSL選項及其值。 參數-ssl_dist_opt可以重複任意次。

        現在,與上一節中的示例相同的示例命令行如下所示(命令中的換行符是為了可讀性,鍵入時不應出現在換行符中):

$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls

  -ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"

  -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true

  -sname ssl_test

Erlang (BEAM) emulator version 5.0 [source]

Eshell V5.0  (abort with ^G)

(ssl_test@myhost)1>

4.5 設置環境以始終使用TLS(舊版)

        指定Erlang參數的簡便方法是使用環境變量ERL_FLAGS。 可以在該變量中指定使用TLS分發所需的所有標誌,然後將其解釋為所有後續Erlang調用的命令行參數。

        在Unix(Bourne)外殼程序中,它看起來可能如下所示(換行符是為了提高可讀性,鍵入時不要出現換行符):

$ ERL_FLAGS="-boot /home/me/ssl/start_ssl -proto_dist inet_tls

  -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem

  -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"

$ export ERL_FLAGS

$ erl -sname ssl_test

Erlang (BEAM) emulator version 5.0 [source]

 

Eshell V5.0  (abort with ^G)

(ssl_test@myhost)1> init:get_arguments().

[{root,["/usr/local/erlang"]},

 {progname,["erl "]},

 {sname,["ssl_test"]},

 {boot,["/home/me/ssl/start_ssl"]},

 {proto_dist,["inet_tls"]},

 {ssl_dist_opt,["server_certfile","/home/me/ssl/erlserver.pem"]},

 {ssl_dist_opt,["server_secure_renegotiate","true",

                "client_secure_renegotiate","true"]

 {home,["/home/me"]}]    

init:get_arguments()調用可驗證是否向模擬器提供了正確的參數。

4.6 在IPv6上使用TLS分發

        可以在IPv6而非IPv4上使用TLS分發。 為此,在命令行或ERL_FLAGS環境變量中啓動Erlang時,傳遞選項-proto_dist inet6_tls而不是-proto_dist inet_tls。

        使用此選項的示例命令行如下所示:

$ erl -boot /home/me/ssl/start_ssl -proto_dist inet6_tls

  -ssl_dist_optfile "/home/me/ssl/ssl_test@myhost.conf"

  -sname ssl_test

        以這種方式啓動的節點將只能使用通過IPv6的TLS分發與其他節點通信。

 

user avatar huazhu7k7k Avatar dx-2021 Avatar
Favorites 2 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.