Erlang SSL Forward Secrecy
Я использовал Erlang Mochiweb в качестве Http-сервера с SSL. Mochiweb использует чистую библиотеку SSL Erlang.
Как настроить erlang ssl для поддержки прямой секретности? Для получения дополнительной информации о SSL Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
1 ответ
Я использую Erlang/OTP 17 с openssl 1.0.2a (erlang нужен openssl для шифров, но не для рукопожатия или протокола, поэтому теоретически он должен поддерживать все шифры, поддерживаемые openssl), поэтому его модуль SSL по умолчанию поддерживает идеальную прямую секретность. Но он также поддерживает некоторые небезопасные протоколы или шифры, такие как sslv3 или des, или слабые шифры, такие как rc4 по умолчанию. SSLlabs ssltest даст вам ранг C для параметров по умолчанию. Возможно, вы захотите отключить небезопасный протокол и шифры.
И модуль erlang ssl по умолчанию учитывает предпочтения клиентского шифра. В результате некоторые IE используют обмен ключами RSA, потому что эти версии предпочитают обмен ключами RSA, а не ECDHE (см.: https://www.ssllabs.com/ssltest/viewClient.html?name=IE&version=8-10&platform=Win%207). Тебе понадобится {honor_cipher_order, true}
использовать предпочтения сервера. И вам нужно будет вручную настроить порядок предпочтений наборов шифров, чтобы соответствовать тому, что вам нужно. Порядок по умолчанию не полностью ранжируется PFS.
Если у вас есть контроль над клиентом (например, вашими приложениями, а не браузерами), и вы действительно хотите использовать только PFS, вы можете отключить обмен ключами rsa.
Пример сценария и опций для erlang: Я не переупорядочивал заказы на шифр.
Для mochiweb вы можете добавить эти опции в ваш ssl_opts.
#!/usr/bin/env escript
% these ciphers will got A- on ssllabs's ssltest.
% Because as mentioned above, some version's IE prefers non-PFS key exchange.
% And got A if {honor_cipher_order, true} is set.
% No manual adjusting needed to get A, because the first ciphersuite is PFS-enabled and supported by IEs.
% So you need to adjust orders to fit whatever you needed.
secure_ciphers() -> secure_ciphers(ssl:cipher_suites()).
% It includes insecure and weak ciphers, so it should get low rank on ssltest
pfs_ciphers() -> pfs_ciphers(ssl:cipher_suites()).
% Rank A on ssllabs' ssltest, all modern client is using perfect forward secrecy key-exchange
% but some client without PFS support will fail to handshake.
pfs_secure_ciphers() ->
sets:to_list(sets:intersection(sets:from_list(secure_ciphers()), sets:from_list(pfs_ciphers()))).
secure_ciphers([]) -> [];
secure_ciphers([{_, rc4_128, _} | T]) -> secure_ciphers(T);
secure_ciphers([{_, des_cbc, _} | T]) -> secure_ciphers(T);
secure_ciphers([{dhe_rsa, _, _} | T]) -> secure_ciphers(T);
secure_ciphers([{_, _, md5} | T]) -> secure_ciphers(T);
secure_ciphers([H | T]) -> [H | secure_ciphers(T)].
pfs_ciphers([]) -> [];
pfs_ciphers([{dhe_dss, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{dhe_rsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{ecdhe_ecdsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{ecdhe_rsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([_ | T]) -> pfs_ciphers(T).
accept(S) ->
{ok, Q} = ssl:transport_accept(S),
spawn(fun() -> accept(S) end),
ssl:ssl_accept(Q),
receive
Msg ->
io:format("~p~n", [Msg]),
ssl:send(Q, <<"HTTP/1.0 200 OK\r\n\r\nHello World\r\n">>),
ssl:close(Q)
end.
main(_) ->
ssl:start(),
{ok, P} = ssl:listen(443, [{certfile, "./aa.crt"}, {keyfile, "./aa.key"}, {ciphers, pfs_secure_ciphers()}, {versions, [tlsv1, 'tlsv1.1', 'tlsv1.2']}, {dhfile, "./dh4096.pem"}]),
accept(P),
receive
stop ->
ok
end.